Feature/lighting output and command loose coupling (#1306)

* Refactor lighting output and lighting command structure for loose coupling.  Add locking callbacks in lighting command.

* Enhance lighting command handling with locking mechanism

- Added locking and unlocking functionality to critical sections in lighting command functions to ensure thread safety.
- Introduced new functions `lighting_command_lock` and `lighting_command_unlock` for explicit locking.
- Updated existing functions to utilize the new locking mechanism, preventing concurrent access issues.
- Refactored notification and clamping functions to support locking, ensuring data integrity during operations.
- Added getter and setter functions with internal locking to access the lighting command data
This commit is contained in:
Steve Karg
2026-04-20 16:17:40 -05:00
committed by GitHub
parent 1c3506403d
commit 9edf957366
4 changed files with 637 additions and 128 deletions
+69 -72
View File
@@ -507,29 +507,6 @@ unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
return priority; return priority;
} }
/**
* @brief Determine if fade, ramp, or warn command is currently executing
* @param pObject [in] object to apply the trim values to
* @param priority [in] priority of the command
*/
static bool Lighting_Command_In_Progress(struct object_data *pObject)
{
bool in_progress = false;
if (!pObject) {
return in_progress;
}
if ((pObject->Lighting_Command.In_Progress ==
BACNET_LIGHTING_FADE_ACTIVE) ||
(pObject->Lighting_Command.In_Progress ==
BACNET_LIGHTING_RAMP_ACTIVE) ||
(pObject->Lighting_Command.Blink.Duration > 0)) {
in_progress = true;
}
return in_progress;
}
/** /**
* @brief Configure the lighting command to apply low or high trim * @brief Configure the lighting command to apply low or high trim
* to the tracking value based on the priority of the command * to the tracking value based on the priority of the command
@@ -547,14 +524,12 @@ Lighting_Command_Trim_Apply(struct object_data *pObject, unsigned priority)
the Tracking_Value shall not be clamped. */ the Tracking_Value shall not be clamped. */
if ((priority == 1) || (priority == 2)) { if ((priority == 1) || (priority == 2)) {
/* remove any high or low trim */ /* remove any high or low trim */
pObject->Lighting_Command.High_Trim_Value = 100.0f; lighting_command_trim_set(&pObject->Lighting_Command, 100.0f, 1.0f, 0);
pObject->Lighting_Command.Low_Trim_Value = 1.0f;
pObject->Lighting_Command.Trim_Fade_Time = 0;
} else { } else {
/* apply high and low trim */ /* apply high and low trim */
pObject->Lighting_Command.High_Trim_Value = pObject->High_End_Trim; lighting_command_trim_set(
pObject->Lighting_Command.Low_Trim_Value = pObject->Low_End_Trim; &pObject->Lighting_Command, pObject->High_End_Trim,
pObject->Lighting_Command.Trim_Fade_Time = pObject->Trim_Fade_Time; pObject->Low_End_Trim, pObject->Trim_Fade_Time);
} }
} }
@@ -653,6 +628,7 @@ static void
Lighting_Command_Warn(struct object_data *pObject, unsigned priority) Lighting_Command_Warn(struct object_data *pObject, unsigned priority)
{ {
unsigned current_priority; unsigned current_priority;
BACNET_LIGHTING_COMMAND_WARN_DATA blink = { 0 };
if (!pObject) { if (!pObject) {
return; return;
@@ -669,9 +645,9 @@ Lighting_Command_Warn(struct object_data *pObject, unsigned priority)
active priority, or active priority, or
(b) The value at the specified priority is 0.0%, or (b) The value at the specified priority is 0.0%, or
(c) Blink_Warn_Enable is FALSE. */ (c) Blink_Warn_Enable is FALSE. */
lighting_command_blink_copy(&pObject->Lighting_Command, &blink);
lighting_command_blink_warn( lighting_command_blink_warn(
&pObject->Lighting_Command, BACNET_LIGHTS_WARN, &pObject->Lighting_Command, BACNET_LIGHTS_WARN, &blink);
&pObject->Lighting_Command.Blink);
} }
} }
@@ -720,7 +696,7 @@ static void
Lighting_Command_Warn_Off(struct object_data *pObject, unsigned priority) Lighting_Command_Warn_Off(struct object_data *pObject, unsigned priority)
{ {
unsigned current_priority; unsigned current_priority;
BACNET_LIGHTING_COMMAND_WARN_DATA blink; BACNET_LIGHTING_COMMAND_WARN_DATA blink = { 0 };
if (!pObject) { if (!pObject) {
return; return;
@@ -740,9 +716,7 @@ Lighting_Command_Warn_Off(struct object_data *pObject, unsigned priority)
active priority, or active priority, or
(b) The Present_Value is 0.0%, or (b) The Present_Value is 0.0%, or
(c) Blink_Warn_Enable is FALSE. */ (c) Blink_Warn_Enable is FALSE. */
memmove( lighting_command_blink_copy(&pObject->Lighting_Command, &blink);
&blink, &pObject->Lighting_Command.Blink,
sizeof(BACNET_LIGHTING_COMMAND_WARN_DATA));
blink.Duration = pObject->Egress_Time_Seconds * 1000UL; blink.Duration = pObject->Egress_Time_Seconds * 1000UL;
blink.Priority = priority; blink.Priority = priority;
blink.Callback = Lighting_Command_Blink_Stop; blink.Callback = Lighting_Command_Blink_Stop;
@@ -813,9 +787,7 @@ Lighting_Command_Warn_Relinquish(struct object_data *pObject, unsigned priority)
(b) The Present_Value is 0.0%, or (b) The Present_Value is 0.0%, or
(c) The Present_Value would not evaluate to 0.0% after (c) The Present_Value would not evaluate to 0.0% after
the priority slot is relinquished. */ the priority slot is relinquished. */
memmove( lighting_command_blink_copy(&pObject->Lighting_Command, &blink);
&blink, &pObject->Lighting_Command.Blink,
sizeof(BACNET_LIGHTING_COMMAND_WARN_DATA));
blink.Duration = pObject->Egress_Time_Seconds * 1000UL; blink.Duration = pObject->Egress_Time_Seconds * 1000UL;
blink.Priority = priority; blink.Priority = priority;
blink.Callback = Lighting_Command_Blink_Stop; blink.Callback = Lighting_Command_Blink_Stop;
@@ -860,7 +832,7 @@ static void Lighting_Command_Step_Up_On(
if (!pObject) { if (!pObject) {
return; return;
} }
value = pObject->Lighting_Command.Tracking_Value; value = lighting_command_tracking_value_get(&pObject->Lighting_Command);
if (operation == BACNET_LIGHTS_STEP_UP) { if (operation == BACNET_LIGHTS_STEP_UP) {
if (is_float_equal(value, 0.0)) { if (is_float_equal(value, 0.0)) {
/* If the starting level of Tracking_Value is 0.0%, /* If the starting level of Tracking_Value is 0.0%,
@@ -914,7 +886,7 @@ static void Lighting_Command_Step_Down_Off(
if (!pObject) { if (!pObject) {
return; return;
} }
value = pObject->Lighting_Command.Tracking_Value; value = lighting_command_tracking_value_get(&pObject->Lighting_Command);
if (is_float_equal(value, 0.0)) { if (is_float_equal(value, 0.0)) {
/* If the starting level of Tracking_Value is 0.0%, /* If the starting level of Tracking_Value is 0.0%,
then this operation is ignored. */ then this operation is ignored. */
@@ -959,7 +931,7 @@ Lighting_Command_Restore_On(struct object_data *pObject, unsigned priority)
if (!pObject) { if (!pObject) {
return; return;
} }
value = pObject->Lighting_Command.Last_On_Value; value = lighting_command_last_on_value_get(&pObject->Lighting_Command);
Lighting_Command_Transition_Default(pObject, priority, value); Lighting_Command_Transition_Default(pObject, priority, value);
} }
@@ -978,7 +950,7 @@ Lighting_Command_Default_On(struct object_data *pObject, unsigned priority)
if (!pObject) { if (!pObject) {
return; return;
} }
value = pObject->Lighting_Command.Default_On_Value; value = lighting_command_default_on_value_get(&pObject->Lighting_Command);
Lighting_Command_Transition_Default(pObject, priority, value); Lighting_Command_Transition_Default(pObject, priority, value);
} }
@@ -1001,7 +973,8 @@ Lighting_Command_Toggle_Restore(struct object_data *pObject, unsigned priority)
/* Prior to the execution of this command, if Present_Value is 0.0%, /* Prior to the execution of this command, if Present_Value is 0.0%,
write the Last_On_Value to the specified slot in the priority write the Last_On_Value to the specified slot in the priority
array. */ array. */
toggle_value = pObject->Lighting_Command.Last_On_Value; toggle_value =
lighting_command_last_on_value_get(&pObject->Lighting_Command);
} else { } else {
/* Prior to the execution of this command, if Present_Value is not 0.0%, /* Prior to the execution of this command, if Present_Value is not 0.0%,
write 0.0% to the specified slot in the priority array. */ write 0.0% to the specified slot in the priority array. */
@@ -1029,7 +1002,8 @@ Lighting_Command_Toggle_Default(struct object_data *pObject, unsigned priority)
/* Prior to the execution of this command, if Present_Value is 0.0%, /* Prior to the execution of this command, if Present_Value is 0.0%,
write the Default_On_Value to the specified slot in the priority write the Default_On_Value to the specified slot in the priority
array. */ array. */
toggle_value = pObject->Lighting_Command.Default_On_Value; toggle_value =
lighting_command_default_on_value_get(&pObject->Lighting_Command);
} else { } else {
/* Prior to the execution of this command, if Present_Value is not 0.0%, /* Prior to the execution of this command, if Present_Value is not 0.0%,
write 0.0% to the specified slot in the priority array. */ write 0.0% to the specified slot in the priority array. */
@@ -1467,10 +1441,11 @@ Lighting_Command_Stop(struct object_data *pObject, unsigned priority)
} }
current_priority = Present_Value_Priority(pObject); current_priority = Present_Value_Priority(pObject);
if (priority == current_priority) { if (priority == current_priority) {
if (Lighting_Command_In_Progress(pObject)) { if (lighting_command_active(&pObject->Lighting_Command)) {
/* fade, ramp, or warn command is currently /* fade, ramp, or warn command is currently
executing at the specified priority */ executing at the specified priority */
value = pObject->Lighting_Command.Tracking_Value; value =
lighting_command_tracking_value_get(&pObject->Lighting_Command);
Present_Value_Set(pObject, value, priority); Present_Value_Set(pObject, value, priority);
/* configure the Lighting Command */ /* configure the Lighting Command */
lighting_command_stop(&pObject->Lighting_Command); lighting_command_stop(&pObject->Lighting_Command);
@@ -1762,7 +1737,7 @@ Lighting_Output_In_Progress(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
value = pObject->Lighting_Command.In_Progress; value = lighting_command_in_progress_get(&pObject->Lighting_Command);
} }
return value; return value;
@@ -1785,7 +1760,8 @@ bool Lighting_Output_In_Progress_Set(
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
pObject->Lighting_Command.In_Progress = in_progress; lighting_command_in_progress_set(
&pObject->Lighting_Command, in_progress);
} }
return status; return status;
@@ -1805,7 +1781,7 @@ float Lighting_Output_Tracking_Value(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
value = pObject->Lighting_Command.Tracking_Value; value = lighting_command_tracking_value_get(&pObject->Lighting_Command);
} }
return value; return value;
@@ -1827,7 +1803,7 @@ bool Lighting_Output_Tracking_Value_Set(uint32_t object_instance, float value)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
pObject->Lighting_Command.Tracking_Value = value; lighting_command_tracking_value_set(&pObject->Lighting_Command, value);
status = true; status = true;
} }
@@ -1916,9 +1892,8 @@ bool Lighting_Output_Blink_Warn_Feature_Set(
} else if (isgreater(off_value, 100.0)) { } else if (isgreater(off_value, 100.0)) {
off_value = 100.0f; off_value = 100.0f;
} }
pObject->Lighting_Command.Blink.Off_Value = off_value; lighting_command_blink_warn_feature_set(
pObject->Lighting_Command.Blink.Interval = interval; &pObject->Lighting_Command, off_value, interval, count);
pObject->Lighting_Command.Blink.Count = count;
status = true; status = true;
} }
@@ -2023,9 +1998,8 @@ bool Lighting_Output_Egress_Active(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
if (pObject->Lighting_Command.Blink.Duration > 0) { value =
value = true; lighting_command_blink_egress_active(&pObject->Lighting_Command);
}
} }
return value; return value;
@@ -2357,7 +2331,7 @@ bool Lighting_Output_Out_Of_Service(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
value = pObject->Lighting_Command.Out_Of_Service; value = lighting_command_out_of_service_get(&pObject->Lighting_Command);
} }
return value; return value;
@@ -2377,7 +2351,7 @@ void Lighting_Output_Out_Of_Service_Set(uint32_t object_instance, bool value)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
pObject->Lighting_Command.Out_Of_Service = value; lighting_command_out_of_service_set(&pObject->Lighting_Command, value);
} }
} }
@@ -2477,7 +2451,7 @@ float Lighting_Output_Last_On_Value(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
value = pObject->Lighting_Command.Last_On_Value; value = lighting_command_last_on_value_get(&pObject->Lighting_Command);
} }
return value; return value;
@@ -2498,7 +2472,8 @@ bool Lighting_Output_Last_On_Value_Set(uint32_t object_instance, float value)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) { if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
pObject->Lighting_Command.Last_On_Value = value; lighting_command_last_on_value_set(
&pObject->Lighting_Command, value);
status = true; status = true;
} }
} }
@@ -2547,7 +2522,8 @@ float Lighting_Output_Default_On_Value(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
value = pObject->Lighting_Command.Default_On_Value; value =
lighting_command_default_on_value_get(&pObject->Lighting_Command);
} }
return value; return value;
@@ -2568,7 +2544,8 @@ bool Lighting_Output_Default_On_Value_Set(uint32_t object_instance, float value)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) { if (isgreaterequal(value, 1.0) && islessequal(value, 100.0)) {
pObject->Lighting_Command.Default_On_Value = value; lighting_command_default_on_value_set(
&pObject->Lighting_Command, value);
status = true; status = true;
} }
} }
@@ -2643,7 +2620,7 @@ bool Lighting_Output_High_End_Trim_Set(uint32_t object_instance, float value)
pObject->High_End_Trim = value; pObject->High_End_Trim = value;
Lighting_Command_Trim_Apply( Lighting_Command_Trim_Apply(
pObject, Present_Value_Priority(pObject)); pObject, Present_Value_Priority(pObject));
if (!Lighting_Command_In_Progress(pObject)) { if (!lighting_command_active(&pObject->Lighting_Command)) {
lighting_command_refresh(&pObject->Lighting_Command); lighting_command_refresh(&pObject->Lighting_Command);
} }
status = true; status = true;
@@ -2720,7 +2697,7 @@ bool Lighting_Output_Low_End_Trim_Set(uint32_t object_instance, float value)
pObject->Low_End_Trim = value; pObject->Low_End_Trim = value;
Lighting_Command_Trim_Apply( Lighting_Command_Trim_Apply(
pObject, Present_Value_Priority(pObject)); pObject, Present_Value_Priority(pObject));
if (!Lighting_Command_In_Progress(pObject)) { if (!lighting_command_active(&pObject->Lighting_Command)) {
lighting_command_refresh(&pObject->Lighting_Command); lighting_command_refresh(&pObject->Lighting_Command);
} }
status = true; status = true;
@@ -2798,7 +2775,7 @@ bool Lighting_Output_Trim_Fade_Time_Set(
pObject->Trim_Fade_Time = value; pObject->Trim_Fade_Time = value;
Lighting_Command_Trim_Apply( Lighting_Command_Trim_Apply(
pObject, Present_Value_Priority(pObject)); pObject, Present_Value_Priority(pObject));
if (!Lighting_Command_In_Progress(pObject)) { if (!lighting_command_active(&pObject->Lighting_Command)) {
lighting_command_refresh(&pObject->Lighting_Command); lighting_command_refresh(&pObject->Lighting_Command);
} }
status = true; status = true;
@@ -2927,8 +2904,7 @@ bool Lighting_Output_Overridden_Status(uint32_t object_instance)
pObject = Keylist_Data(Object_List, object_instance); pObject = Keylist_Data(Object_List, object_instance);
if (pObject) { if (pObject) {
status = pObject->Lighting_Command.Overridden || status = lighting_command_overridden_status(&pObject->Lighting_Command);
pObject->Lighting_Command.Overridden_Momentary;
} }
return status; return status;
@@ -3823,6 +3799,25 @@ void Lighting_Output_Context_Set(uint32_t object_instance, void *context)
} }
} }
/**
* @brief Get the lighting command data for a specific object instance
* @param object_instance [in] BACnet object instance number
* @return pointer to the lighting command data, or NULL if not found
*/
BACNET_LIGHTING_COMMAND_DATA *
Lighting_Output_Lighting_Command_Data(uint32_t object_instance)
{
BACNET_LIGHTING_COMMAND_DATA *data = NULL;
struct object_data *pObject;
pObject = Keylist_Data(Object_List, object_instance);
if (pObject) {
data = &pObject->Lighting_Command;
}
return data;
}
/** /**
* @brief Creates a Color object * @brief Creates a Color object
* @param object_instance - object-instance number of the object * @param object_instance - object-instance number of the object
@@ -3857,9 +3852,10 @@ uint32_t Lighting_Output_Create(uint32_t object_instance)
pObject->Description = NULL; pObject->Description = NULL;
pObject->Present_Value = 0.0f; pObject->Present_Value = 0.0f;
lighting_command_init(&pObject->Lighting_Command); lighting_command_init(&pObject->Lighting_Command);
pObject->Lighting_Command.Key = object_instance; lighting_command_key_set(&pObject->Lighting_Command, object_instance);
pObject->Lighting_Command.Notification_Head.callback = lighting_command_tracking_value_callback_set(
Lighting_Output_Tracking_Value_Callback; &pObject->Lighting_Command,
Lighting_Output_Tracking_Value_Callback);
pObject->Last_Lighting_Command.operation = BACNET_LIGHTS_NONE; pObject->Last_Lighting_Command.operation = BACNET_LIGHTS_NONE;
pObject->Last_Lighting_Command.use_target_level = false; pObject->Last_Lighting_Command.use_target_level = false;
pObject->Last_Lighting_Command.use_ramp_rate = false; pObject->Last_Lighting_Command.use_ramp_rate = false;
@@ -3868,9 +3864,10 @@ uint32_t Lighting_Output_Create(uint32_t object_instance)
pObject->Last_Lighting_Command.use_priority = false; pObject->Last_Lighting_Command.use_priority = false;
pObject->Blink_Warn_Enable = false; pObject->Blink_Warn_Enable = false;
pObject->High_End_Trim = 100.0f; pObject->High_End_Trim = 100.0f;
pObject->Lighting_Command.High_Trim_Value = pObject->High_End_Trim;
pObject->Low_End_Trim = 1.0f; pObject->Low_End_Trim = 1.0f;
pObject->Lighting_Command.Low_Trim_Value = pObject->Low_End_Trim; lighting_command_trim_set(
&pObject->Lighting_Command, pObject->High_End_Trim,
pObject->Low_End_Trim, pObject->Trim_Fade_Time);
pObject->Trim_Fade_Time = 0; pObject->Trim_Fade_Time = 0;
pObject->Egress_Time_Seconds = 0; pObject->Egress_Time_Seconds = 0;
pObject->Default_Fade_Time = 100; pObject->Default_Fade_Time = 100;
+4
View File
@@ -248,6 +248,10 @@ void *Lighting_Output_Context_Get(uint32_t object_instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void Lighting_Output_Context_Set(uint32_t object_instance, void *context); void Lighting_Output_Context_Set(uint32_t object_instance, void *context);
BACNET_STACK_EXPORT
BACNET_LIGHTING_COMMAND_DATA *
Lighting_Output_Lighting_Command_Data(uint32_t object_instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
uint32_t Lighting_Output_Create(uint32_t object_instance); uint32_t Lighting_Output_Create(uint32_t object_instance);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
+484 -56
View File
@@ -46,6 +46,11 @@ void lighting_command_notification_add(
{ {
struct lighting_command_notification *head; struct lighting_command_notification *head;
if (!data || !notification) {
return;
}
lighting_command_lock(data);
head = &data->Notification_Head; head = &data->Notification_Head;
do { do {
if (head->next == notification) { if (head->next == notification) {
@@ -58,6 +63,7 @@ void lighting_command_notification_add(
} }
head = head->next; head = head->next;
} while (head); } while (head);
lighting_command_unlock(data);
} }
/** /**
@@ -90,6 +96,11 @@ void lighting_command_timer_notfication_add(
{ {
struct lighting_command_timer_notification *head; struct lighting_command_timer_notification *head;
if (!data || !notification) {
return;
}
lighting_command_lock(data);
head = &data->Timer_Notification_Head; head = &data->Timer_Notification_Head;
do { do {
if (head->next == notification) { if (head->next == notification) {
@@ -102,6 +113,7 @@ void lighting_command_timer_notfication_add(
} }
head = head->next; head = head->next;
} while (head); } while (head);
lighting_command_unlock(data);
} }
/** /**
@@ -109,8 +121,8 @@ void lighting_command_timer_notfication_add(
* for WARN_OFF/WARN_RELINQUISH operations * for WARN_OFF/WARN_RELINQUISH operations
* @param data - dimmer data structure * @param data - dimmer data structure
*/ */
static void static void lighting_command_blink_stop_notify_nolock(
lighting_command_blink_stop_notify(struct bacnet_lighting_command_data *data) struct bacnet_lighting_command_data *data)
{ {
if (data->Blink.Callback) { if (data->Blink.Callback) {
/* do some checking to avoid extra callbacks */ /* do some checking to avoid extra callbacks */
@@ -288,7 +300,7 @@ static float lighting_command_trim_fade(
* @return value clamped within the operating range defined by the High_End_Trim * @return value clamped within the operating range defined by the High_End_Trim
* and Low_End_Trim property values * and Low_End_Trim property values
*/ */
float lighting_command_operating_range_clamp_fade( static float lighting_command_operating_range_clamp_fade_nolock(
struct bacnet_lighting_command_data *data, struct bacnet_lighting_command_data *data,
float value, float value,
uint16_t milliseconds) uint16_t milliseconds)
@@ -328,6 +340,24 @@ float lighting_command_operating_range_clamp_fade(
return value; return value;
} }
float lighting_command_operating_range_clamp_fade(
struct bacnet_lighting_command_data *data,
float value,
uint16_t milliseconds)
{
float clamped_value;
if (!data) {
return value;
}
lighting_command_lock(data);
clamped_value = lighting_command_operating_range_clamp_fade_nolock(
data, value, milliseconds);
lighting_command_unlock(data);
return clamped_value;
}
/** /**
* @brief Clamp the value within the operating range between low and high * @brief Clamp the value within the operating range between low and high
* end trim values immediately. * end trim values immediately.
@@ -342,10 +372,25 @@ float lighting_command_operating_range_clamp_fade(
* @return value clamped within the operating range defined by the High_End_Trim * @return value clamped within the operating range defined by the High_End_Trim
* and Low_End_Trim property values * and Low_End_Trim property values
*/ */
static float lighting_command_operating_range_clamp_nolock(
struct bacnet_lighting_command_data *data, float value)
{
return lighting_command_operating_range_clamp_fade_nolock(data, value, 0);
}
float lighting_command_operating_range_clamp( float lighting_command_operating_range_clamp(
struct bacnet_lighting_command_data *data, float value) struct bacnet_lighting_command_data *data, float value)
{ {
return lighting_command_operating_range_clamp_fade(data, value, 0); float clamped_value;
if (!data) {
return value;
}
lighting_command_lock(data);
clamped_value = lighting_command_operating_range_clamp_nolock(data, value);
lighting_command_unlock(data);
return clamped_value;
} }
/** /**
@@ -364,7 +409,7 @@ float lighting_command_operating_range_clamp(
* @return normalized value within the range defined by Min_Actual_Value * @return normalized value within the range defined by Min_Actual_Value
* and Max_Actual_Value * and Max_Actual_Value
*/ */
float lighting_command_normalized_on_range_clamp( static float lighting_command_normalized_on_range_clamp_nolock(
struct bacnet_lighting_command_data *data, float value) struct bacnet_lighting_command_data *data, float value)
{ {
float min_value, max_value, swap_value; float min_value, max_value, swap_value;
@@ -389,6 +434,22 @@ float lighting_command_normalized_on_range_clamp(
return value; return value;
} }
float lighting_command_normalized_on_range_clamp(
struct bacnet_lighting_command_data *data, float value)
{
float clamped_value;
if (!data) {
return value;
}
lighting_command_lock(data);
clamped_value =
lighting_command_normalized_on_range_clamp_nolock(data, value);
lighting_command_unlock(data);
return clamped_value;
}
/** /**
* @brief Normalize the value to the min/max range * @brief Normalize the value to the min/max range
* @details The physical output level, or non-normalized range, * @details The physical output level, or non-normalized range,
@@ -405,7 +466,7 @@ float lighting_command_normalized_on_range_clamp(
* @return normalized value within the range defined by * @return normalized value within the range defined by
* 0.0%, Min_Actual_Value, and Max_Actual_Value * 0.0%, Min_Actual_Value, and Max_Actual_Value
*/ */
float lighting_command_normalized_range_clamp( static float lighting_command_normalized_range_clamp_nolock(
struct bacnet_lighting_command_data *data, float value) struct bacnet_lighting_command_data *data, float value)
{ {
float normalized_value; float normalized_value;
@@ -436,6 +497,21 @@ float lighting_command_normalized_range_clamp(
return normalized_value; return normalized_value;
} }
float lighting_command_normalized_range_clamp(
struct bacnet_lighting_command_data *data, float value)
{
float clamped_value;
if (!data) {
return value;
}
lighting_command_lock(data);
clamped_value = lighting_command_normalized_range_clamp_nolock(data, value);
lighting_command_unlock(data);
return clamped_value;
}
/** /**
* @brief Callback for tracking value updates * @brief Callback for tracking value updates
* @param data - dimmer data structure * @param data - dimmer data structure
@@ -476,8 +552,8 @@ static void lighting_command_fade_handler(
old_value = data->Tracking_Value; old_value = data->Tracking_Value;
/* clamp Tracking value within the Normalized ON Range */ /* clamp Tracking value within the Normalized ON Range */
target_value = target_value = lighting_command_normalized_on_range_clamp_nolock(
lighting_command_normalized_on_range_clamp(data, data->Target_Level); data, data->Target_Level);
if ((milliseconds >= data->Fade_Time) || if ((milliseconds >= data->Fade_Time) ||
(!islessgreater(data->Tracking_Value, target_value))) { (!islessgreater(data->Tracking_Value, target_value))) {
/* stop fading */ /* stop fading */
@@ -506,7 +582,7 @@ static void lighting_command_fade_handler(
data->In_Progress = BACNET_LIGHTING_FADE_ACTIVE; data->In_Progress = BACNET_LIGHTING_FADE_ACTIVE;
} }
/* clamp Tracking Value inclusively within the Operating Range */ /* clamp Tracking Value inclusively within the Operating Range */
data->Tracking_Value = lighting_command_operating_range_clamp_fade( data->Tracking_Value = lighting_command_operating_range_clamp_fade_nolock(
data, data->Tracking_Value, milliseconds); data, data->Tracking_Value, milliseconds);
/* notify */ /* notify */
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
@@ -536,8 +612,8 @@ static void lighting_command_ramp_handler(
old_value = data->Tracking_Value; old_value = data->Tracking_Value;
/* clamp Tracking value within the Normalized ON Range */ /* clamp Tracking value within the Normalized ON Range */
target_value = target_value = lighting_command_normalized_on_range_clamp_nolock(
lighting_command_normalized_on_range_clamp(data, data->Target_Level); data, data->Target_Level);
if (!islessgreater(data->Tracking_Value, target_value)) { if (!islessgreater(data->Tracking_Value, target_value)) {
/* stop ramping */ /* stop ramping */
if (isless(data->Target_Level, 1.0f)) { if (isless(data->Target_Level, 1.0f)) {
@@ -581,7 +657,7 @@ static void lighting_command_ramp_handler(
} }
/* clamp target within min/max, if needed */ /* clamp target within min/max, if needed */
step_value = step_value =
lighting_command_normalized_on_range_clamp(data, step_value); lighting_command_normalized_on_range_clamp_nolock(data, step_value);
if (data->Lighting_Operation == BACNET_LIGHTS_STOP) { if (data->Lighting_Operation == BACNET_LIGHTS_STOP) {
if (isless(data->Target_Level, 1.0f)) { if (isless(data->Target_Level, 1.0f)) {
/* jump target to OFF if below normalized min */ /* jump target to OFF if below normalized min */
@@ -596,7 +672,7 @@ static void lighting_command_ramp_handler(
} }
} }
/* clamp Tracking_Value inclusively within the Operating Range */ /* clamp Tracking_Value inclusively within the Operating Range */
operating_value = lighting_command_operating_range_clamp_fade( operating_value = lighting_command_operating_range_clamp_fade_nolock(
data, data->Tracking_Value, milliseconds); data, data->Tracking_Value, milliseconds);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
/* notify */ /* notify */
@@ -625,12 +701,13 @@ lighting_command_step_up_handler(struct bacnet_lighting_command_data *data)
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
/* clamp Tracking value within the Normalized ON Range */ /* clamp Tracking value within the Normalized ON Range */
data->Tracking_Value = data->Tracking_Value =
lighting_command_normalized_on_range_clamp(data, target_value); lighting_command_normalized_on_range_clamp_nolock(
data, target_value);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value = lighting_command_operating_range_clamp_nolock(
lighting_command_operating_range_clamp(data, data->Tracking_Value); data, data->Tracking_Value);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
/* notify */ /* notify */
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
@@ -657,12 +734,12 @@ lighting_command_step_down_handler(struct bacnet_lighting_command_data *data)
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
/* clamp Tracking value within the Normalized ON Range */ /* clamp Tracking value within the Normalized ON Range */
data->Tracking_Value = data->Tracking_Value =
lighting_command_normalized_on_range_clamp(data, target_value); lighting_command_normalized_on_range_clamp_nolock(data, target_value);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value = lighting_command_operating_range_clamp_nolock(
lighting_command_operating_range_clamp(data, data->Tracking_Value); data, data->Tracking_Value);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
/* notify */ /* notify */
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
@@ -687,12 +764,12 @@ lighting_command_step_on_handler(struct bacnet_lighting_command_data *data)
target_value = lighting_command_step_up_target_value( target_value = lighting_command_step_up_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
data->Tracking_Value = data->Tracking_Value =
lighting_command_normalized_range_clamp(data, target_value); lighting_command_normalized_range_clamp_nolock(data, target_value);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value = lighting_command_operating_range_clamp_nolock(
lighting_command_operating_range_clamp(data, data->Tracking_Value); data, data->Tracking_Value);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
/* notify */ /* notify */
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
@@ -717,12 +794,12 @@ lighting_command_step_off_handler(struct bacnet_lighting_command_data *data)
target_value = lighting_command_step_down_target_value( target_value = lighting_command_step_down_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
data->Tracking_Value = data->Tracking_Value =
lighting_command_normalized_range_clamp(data, target_value); lighting_command_normalized_range_clamp_nolock(data, target_value);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value = lighting_command_operating_range_clamp_nolock(
lighting_command_operating_range_clamp(data, data->Tracking_Value); data, data->Tracking_Value);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
/* notify */ /* notify */
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
@@ -767,7 +844,7 @@ static void lighting_command_blink_handler(
} }
if (data->Blink.Duration == 0) { if (data->Blink.Duration == 0) {
/* 'end' operation */ /* 'end' operation */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
target_value = data->Blink.End_Value; target_value = data->Blink.End_Value;
@@ -799,7 +876,7 @@ static void lighting_command_blink_handler(
} }
if (data->Blink.Count == 0) { if (data->Blink.Count == 0) {
/* 'end' operation */ /* 'end' operation */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
data->In_Progress = BACNET_LIGHTING_IDLE; data->In_Progress = BACNET_LIGHTING_IDLE;
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
target_value = data->Blink.End_Value; target_value = data->Blink.End_Value;
@@ -807,10 +884,11 @@ static void lighting_command_blink_handler(
} }
} }
} }
target_value = lighting_command_normalized_range_clamp(data, target_value); target_value =
lighting_command_normalized_range_clamp_nolock(data, target_value);
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value =
lighting_command_operating_range_clamp(data, target_value); lighting_command_operating_range_clamp_nolock(data, target_value);
/* note: The blink-warn notifications shall not be reflected /* note: The blink-warn notifications shall not be reflected
in the tracking value. */ in the tracking value. */
if (data->In_Progress == BACNET_LIGHTING_IDLE) { if (data->In_Progress == BACNET_LIGHTING_IDLE) {
@@ -823,20 +901,32 @@ static void lighting_command_blink_handler(
* @brief Overrides the current lighting command with the provided value * @brief Overrides the current lighting command with the provided value
* @param data [in] dimmer data * @param data [in] dimmer data
*/ */
void lighting_command_override( static void lighting_command_override_nolock(
struct bacnet_lighting_command_data *data, float value) struct bacnet_lighting_command_data *data, float value)
{ {
float old_value; float old_value;
if (!data) {
return;
}
old_value = data->Tracking_Value; old_value = data->Tracking_Value;
data->Tracking_Value = lighting_command_physical_range_clamp(value); data->Tracking_Value = lighting_command_physical_range_clamp(value);
lighting_command_tracking_value_event( lighting_command_tracking_value_event(
data, old_value, data->Tracking_Value); data, old_value, data->Tracking_Value);
} }
/**
* @brief Overrides the current lighting command with the provided value
* @param data [in] dimmer data
*/
void lighting_command_override(
struct bacnet_lighting_command_data *data, float value)
{
if (!data) {
return;
}
lighting_command_lock(data);
lighting_command_override_nolock(data, value);
lighting_command_unlock(data);
}
/** /**
* @brief Overrides the current lighting command with the provided value * @brief Overrides the current lighting command with the provided value
* @param data [in] dimmer data * @param data [in] dimmer data
@@ -847,9 +937,11 @@ void lighting_command_override_set(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
data->Overridden = true; data->Overridden = true;
data->Overridden_Momentary = false; data->Overridden_Momentary = false;
lighting_command_override(data, value); lighting_command_override_nolock(data, value);
lighting_command_unlock(data);
} }
/** /**
@@ -864,16 +956,19 @@ void lighting_command_override_clear(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
data->Overridden = false; data->Overridden = false;
data->Overridden_Momentary = false; data->Overridden_Momentary = false;
old_value = data->Tracking_Value; old_value = data->Tracking_Value;
/* clamp Tracking value within the Normalized Range */ /* clamp Tracking value within the Normalized Range */
normalized_value = lighting_command_normalized_range_clamp(data, value); normalized_value =
lighting_command_normalized_range_clamp_nolock(data, value);
/* clamp Tracking value inclusively within the Operating Range */ /* clamp Tracking value inclusively within the Operating Range */
operating_value = operating_value =
lighting_command_operating_range_clamp(data, normalized_value); lighting_command_operating_range_clamp_nolock(data, normalized_value);
data->Tracking_Value = operating_value; data->Tracking_Value = operating_value;
lighting_command_tracking_value_event(data, old_value, operating_value); lighting_command_tracking_value_event(data, old_value, operating_value);
lighting_command_unlock(data);
} }
/** /**
@@ -886,9 +981,11 @@ void lighting_command_override_momentary(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
data->Overridden = true; data->Overridden = true;
data->Overridden_Momentary = true; data->Overridden_Momentary = true;
lighting_command_override(data, value); lighting_command_override_nolock(data, value);
lighting_command_unlock(data);
} }
/** /**
@@ -902,8 +999,10 @@ void lighting_command_refresh(struct bacnet_lighting_command_data *data)
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
value = data->Tracking_Value; value = data->Tracking_Value;
lighting_command_tracking_value_event(data, value, value); lighting_command_tracking_value_event(data, value, value);
lighting_command_unlock(data);
} }
/** /**
@@ -918,6 +1017,7 @@ void lighting_command_timer(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
if (data->Overridden) { if (data->Overridden) {
data->Lighting_Operation = BACNET_LIGHTS_NONE; data->Lighting_Operation = BACNET_LIGHTS_NONE;
} }
@@ -961,6 +1061,7 @@ void lighting_command_timer(
break; break;
} }
lighting_command_timer_notify(data, milliseconds); lighting_command_timer_notify(data, milliseconds);
lighting_command_unlock(data);
} }
/** /**
@@ -975,8 +1076,9 @@ void lighting_command_fade_to(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Fade_Time = fade_time; data->Fade_Time = fade_time;
data->Lighting_Operation = BACNET_LIGHTS_FADE_TO; data->Lighting_Operation = BACNET_LIGHTS_FADE_TO;
@@ -985,6 +1087,7 @@ void lighting_command_fade_to(
/* the last value that was greater than or equal to 1.0%.*/ /* the last value that was greater than or equal to 1.0%.*/
data->Last_On_Value = value; data->Last_On_Value = value;
} }
lighting_command_unlock(data);
} }
/** /**
@@ -999,8 +1102,9 @@ void lighting_command_ramp_to(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Ramp_Rate = lighting_command_ramp_rate_clamp(ramp_rate); data->Ramp_Rate = lighting_command_ramp_rate_clamp(ramp_rate);
data->Lighting_Operation = BACNET_LIGHTS_RAMP_TO; data->Lighting_Operation = BACNET_LIGHTS_RAMP_TO;
@@ -1009,6 +1113,7 @@ void lighting_command_ramp_to(
/* the last value that was greater than or equal to 1.0%.*/ /* the last value that was greater than or equal to 1.0%.*/
data->Last_On_Value = value; data->Last_On_Value = value;
} }
lighting_command_unlock(data);
} }
/** /**
@@ -1027,15 +1132,16 @@ void lighting_command_step(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
if (((operation == BACNET_LIGHTS_STEP_UP) || if (((operation == BACNET_LIGHTS_STEP_UP) ||
(operation == BACNET_LIGHTS_STEP_DOWN)) && (operation == BACNET_LIGHTS_STEP_DOWN)) &&
(!islessgreater(data->Tracking_Value, 0.0))) { (!islessgreater(data->Tracking_Value, 0.0))) {
/* If the starting level of Tracking_Value is 0.0%, /* If the starting level of Tracking_Value is 0.0%,
then this operation is ignored. */ then this operation is ignored. */
return; goto done;
} }
data->Lighting_Operation = operation; data->Lighting_Operation = operation;
data->Fade_Time = 0; data->Fade_Time = 0;
@@ -1044,30 +1150,33 @@ void lighting_command_step(
if (operation == BACNET_LIGHTS_STEP_UP) { if (operation == BACNET_LIGHTS_STEP_UP) {
target_value = lighting_command_step_up_target_value( target_value = lighting_command_step_up_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
target_value = target_value = lighting_command_normalized_on_range_clamp_nolock(
lighting_command_normalized_on_range_clamp(data, target_value); data, target_value);
} else if (operation == BACNET_LIGHTS_STEP_DOWN) { } else if (operation == BACNET_LIGHTS_STEP_DOWN) {
target_value = lighting_command_step_down_target_value( target_value = lighting_command_step_down_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
target_value = target_value = lighting_command_normalized_on_range_clamp_nolock(
lighting_command_normalized_on_range_clamp(data, target_value); data, target_value);
} else if (operation == BACNET_LIGHTS_STEP_ON) { } else if (operation == BACNET_LIGHTS_STEP_ON) {
target_value = lighting_command_step_up_target_value( target_value = lighting_command_step_up_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
target_value = target_value =
lighting_command_normalized_range_clamp(data, target_value); lighting_command_normalized_range_clamp_nolock(data, target_value);
} else if (operation == BACNET_LIGHTS_STEP_OFF) { } else if (operation == BACNET_LIGHTS_STEP_OFF) {
target_value = lighting_command_step_down_target_value( target_value = lighting_command_step_down_target_value(
data->Tracking_Value, data->Step_Increment); data->Tracking_Value, data->Step_Increment);
target_value = target_value =
lighting_command_normalized_range_clamp(data, target_value); lighting_command_normalized_range_clamp_nolock(data, target_value);
} else { } else {
return; goto done;
} }
if (isgreaterequal(target_value, 1.0)) { if (isgreaterequal(target_value, 1.0)) {
/* the last value that was greater than or equal to 1.0%.*/ /* the last value that was greater than or equal to 1.0%.*/
data->Last_On_Value = target_value; data->Last_On_Value = target_value;
} }
done:
lighting_command_unlock(data);
} }
/** /**
@@ -1081,11 +1190,12 @@ void lighting_command_blink_warn(
BACNET_LIGHTING_OPERATION operation, BACNET_LIGHTING_OPERATION operation,
struct bacnet_lighting_command_warn_data *blink) struct bacnet_lighting_command_warn_data *blink)
{ {
if (!data) { if (!data || !blink) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the new warning */ /* configure the new warning */
data->Lighting_Operation = operation; data->Lighting_Operation = operation;
data->Blink.Target_Interval = blink->Interval; data->Blink.Target_Interval = blink->Interval;
@@ -1101,6 +1211,33 @@ void lighting_command_blink_warn(
/* configure next interval */ /* configure next interval */
data->Blink.State = false; data->Blink.State = false;
data->Blink.Interval = blink->Interval; data->Blink.Interval = blink->Interval;
lighting_command_unlock(data);
}
/**
* @brief Copy the current blink data from the lighting command
* @param data [in] dimmer object instance
* @param blink [out] BACnet blink data to copy into
*/
void lighting_command_blink_copy(
struct bacnet_lighting_command_data *data,
struct bacnet_lighting_command_warn_data *blink)
{
if (!data || !blink) {
return;
}
lighting_command_lock(data);
blink->On_Value = data->Blink.On_Value;
blink->Off_Value = data->Blink.Off_Value;
blink->End_Value = data->Blink.End_Value;
blink->Priority = data->Blink.Priority;
blink->Callback = data->Blink.Callback;
blink->Target_Interval = data->Blink.Target_Interval;
blink->Interval = data->Blink.Interval;
blink->Duration = data->Blink.Duration;
blink->Count = data->Blink.Count;
blink->State = data->Blink.State;
lighting_command_unlock(data);
} }
/** /**
@@ -1113,14 +1250,16 @@ void lighting_command_stop(struct bacnet_lighting_command_data *data)
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Lighting_Operation = BACNET_LIGHTS_STOP; data->Lighting_Operation = BACNET_LIGHTS_STOP;
if (isgreaterequal(data->Tracking_Value, 1.0)) { if (isgreaterequal(data->Tracking_Value, 1.0)) {
/* the last value that was greater than or equal to 1.0%.*/ /* the last value that was greater than or equal to 1.0%.*/
data->Last_On_Value = data->Tracking_Value; data->Last_On_Value = data->Tracking_Value;
} }
lighting_command_unlock(data);
} }
/** /**
@@ -1133,10 +1272,12 @@ void lighting_command_none(struct bacnet_lighting_command_data *data)
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Lighting_Operation = BACNET_LIGHTS_NONE; data->Lighting_Operation = BACNET_LIGHTS_NONE;
lighting_command_unlock(data);
} }
/** /**
@@ -1150,12 +1291,14 @@ void lighting_command_restore_on(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Fade_Time = fade_time; data->Fade_Time = fade_time;
data->Lighting_Operation = BACNET_LIGHTS_RESTORE_ON; data->Lighting_Operation = BACNET_LIGHTS_RESTORE_ON;
data->Target_Level = data->Last_On_Value; data->Target_Level = data->Last_On_Value;
lighting_command_unlock(data);
} }
/** /**
@@ -1169,12 +1312,14 @@ void lighting_command_default_on(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Fade_Time = fade_time; data->Fade_Time = fade_time;
data->Lighting_Operation = BACNET_LIGHTS_DEFAULT_ON; data->Lighting_Operation = BACNET_LIGHTS_DEFAULT_ON;
data->Target_Level = data->Default_On_Value; data->Target_Level = data->Default_On_Value;
lighting_command_unlock(data);
} }
/** /**
@@ -1188,8 +1333,9 @@ void lighting_command_toggle_restore(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Fade_Time = fade_time; data->Fade_Time = fade_time;
data->Lighting_Operation = BACNET_LIGHTS_TOGGLE_RESTORE; data->Lighting_Operation = BACNET_LIGHTS_TOGGLE_RESTORE;
@@ -1200,6 +1346,7 @@ void lighting_command_toggle_restore(
/* not OFF, write 0.0% */ /* not OFF, write 0.0% */
data->Target_Level = 0.0f; data->Target_Level = 0.0f;
} }
lighting_command_unlock(data);
} }
/** /**
@@ -1213,8 +1360,9 @@ void lighting_command_toggle_default(
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
/* possibly interrupting a blink warn, so notify */ /* possibly interrupting a blink warn, so notify */
lighting_command_blink_stop_notify(data); lighting_command_blink_stop_notify_nolock(data);
/* configure the lighting operation */ /* configure the lighting operation */
data->Fade_Time = fade_time; data->Fade_Time = fade_time;
data->Lighting_Operation = BACNET_LIGHTS_TOGGLE_DEFAULT; data->Lighting_Operation = BACNET_LIGHTS_TOGGLE_DEFAULT;
@@ -1225,13 +1373,290 @@ void lighting_command_toggle_default(
/* not OFF, write 0.0% */ /* not OFF, write 0.0% */
data->Target_Level = 0.0f; data->Target_Level = 0.0f;
} }
lighting_command_unlock(data);
} }
/**
* @brief Configure the lighting command to apply low or high trim
* @param data [in] dimmer data
*/
void lighting_command_trim_set(
struct bacnet_lighting_command_data *data,
float High_End_Trim,
float Low_End_Trim,
uint32_t Trim_Fade_Time)
{
if (!data) {
return;
}
lighting_command_lock(data);
/* apply high and low trim */
data->High_Trim_Value = High_End_Trim;
data->Low_Trim_Value = Low_End_Trim;
data->Trim_Fade_Time = Trim_Fade_Time;
lighting_command_unlock(data);
}
void lighting_command_key_set(
struct bacnet_lighting_command_data *data, uint32_t key)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Key = key;
lighting_command_unlock(data);
}
void lighting_command_tracking_value_callback_set(
struct bacnet_lighting_command_data *data,
lighting_command_tracking_value_callback cb)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Notification_Head.callback = cb;
lighting_command_unlock(data);
}
BACNET_LIGHTING_IN_PROGRESS
lighting_command_in_progress_get(struct bacnet_lighting_command_data *data)
{
BACNET_LIGHTING_IN_PROGRESS in_progress = BACNET_LIGHTING_IDLE;
if (!data) {
return in_progress;
}
lighting_command_lock(data);
in_progress = data->In_Progress;
lighting_command_unlock(data);
return in_progress;
}
void lighting_command_in_progress_set(
struct bacnet_lighting_command_data *data,
BACNET_LIGHTING_IN_PROGRESS in_progress)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->In_Progress = in_progress;
lighting_command_unlock(data);
}
float lighting_command_tracking_value_get(
struct bacnet_lighting_command_data *data)
{
float value = 0.0f;
if (!data) {
return value;
}
lighting_command_lock(data);
value = data->Tracking_Value;
lighting_command_unlock(data);
return value;
}
void lighting_command_tracking_value_set(
struct bacnet_lighting_command_data *data, float value)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Tracking_Value = value;
lighting_command_unlock(data);
}
void lighting_command_blink_warn_feature_set(
struct bacnet_lighting_command_data *data,
float off_value,
uint16_t interval,
uint16_t count)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Blink.Off_Value = off_value;
data->Blink.Interval = interval;
data->Blink.Count = count;
lighting_command_unlock(data);
}
bool lighting_command_blink_egress_active(
struct bacnet_lighting_command_data *data)
{
bool active = false;
if (!data) {
return active;
}
lighting_command_lock(data);
active = data->Blink.Duration > 0;
lighting_command_unlock(data);
return active;
}
bool lighting_command_out_of_service_get(
struct bacnet_lighting_command_data *data)
{
bool value = false;
if (!data) {
return value;
}
lighting_command_lock(data);
value = data->Out_Of_Service;
lighting_command_unlock(data);
return value;
}
void lighting_command_out_of_service_set(
struct bacnet_lighting_command_data *data, bool value)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Out_Of_Service = value;
lighting_command_unlock(data);
}
float lighting_command_last_on_value_get(
struct bacnet_lighting_command_data *data)
{
float value = 0.0f;
if (!data) {
return value;
}
lighting_command_lock(data);
value = data->Last_On_Value;
lighting_command_unlock(data);
return value;
}
void lighting_command_last_on_value_set(
struct bacnet_lighting_command_data *data, float value)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Last_On_Value = value;
lighting_command_unlock(data);
}
float lighting_command_default_on_value_get(
struct bacnet_lighting_command_data *data)
{
float value = 0.0f;
if (!data) {
return value;
}
lighting_command_lock(data);
value = data->Default_On_Value;
lighting_command_unlock(data);
return value;
}
void lighting_command_default_on_value_set(
struct bacnet_lighting_command_data *data, float value)
{
if (!data) {
return;
}
lighting_command_lock(data);
data->Default_On_Value = value;
lighting_command_unlock(data);
}
bool lighting_command_overridden_status(
struct bacnet_lighting_command_data *data)
{
bool status = false;
if (!data) {
return status;
}
lighting_command_lock(data);
status = data->Overridden || data->Overridden_Momentary;
lighting_command_unlock(data);
return status;
}
/**
* @brief Determine if fade, ramp, or warn command is currently executing
* @param pObject [in] object to apply the trim values to
* @param priority [in] priority of the command
*/
bool lighting_command_active(struct bacnet_lighting_command_data *data)
{
bool in_progress = false;
if (!data) {
return in_progress;
}
lighting_command_lock(data);
if ((data->In_Progress == BACNET_LIGHTING_FADE_ACTIVE) ||
(data->In_Progress == BACNET_LIGHTING_RAMP_ACTIVE) ||
(data->Blink.Duration > 0)) {
in_progress = true;
}
lighting_command_unlock(data);
return in_progress;
}
/**
* @brief Locks the lighting command for exclusive access
* @param data [in] dimmer data
*/
void lighting_command_lock(struct bacnet_lighting_command_data *data)
{
if (!data) {
return;
}
if (data->Lock) {
data->Lock(data);
}
}
/**
* @brief Unlocks the lighting command for exclusive access
* @param data [in] dimmer data
*/
void lighting_command_unlock(struct bacnet_lighting_command_data *data)
{
if (!data) {
return;
}
if (data->Unlock) {
data->Unlock(data);
}
}
/**
* @brief Initializes the lighting command data structure to default values
*/
void lighting_command_init(struct bacnet_lighting_command_data *data) void lighting_command_init(struct bacnet_lighting_command_data *data)
{ {
if (!data) { if (!data) {
return; return;
} }
lighting_command_lock(data);
data->Tracking_Value = 0.0f; data->Tracking_Value = 0.0f;
data->Lighting_Operation = BACNET_LIGHTS_NONE; data->Lighting_Operation = BACNET_LIGHTS_NONE;
data->In_Progress = BACNET_LIGHTING_NOT_CONTROLLED; data->In_Progress = BACNET_LIGHTING_NOT_CONTROLLED;
@@ -1256,4 +1681,7 @@ void lighting_command_init(struct bacnet_lighting_command_data *data)
data->Blink.State = false; data->Blink.State = false;
data->Notification_Head.next = NULL; data->Notification_Head.next = NULL;
data->Notification_Head.callback = NULL; data->Notification_Head.callback = NULL;
data->Timer_Notification_Head.next = NULL;
data->Timer_Notification_Head.callback = NULL;
lighting_command_unlock(data);
} }
+80
View File
@@ -41,6 +41,13 @@ struct lighting_command_timer_notification {
lighting_command_timer_callback callback; lighting_command_timer_callback callback;
}; };
/**
* @brief Callback for locking shared state during lighting command processing
* @param data - dimmer data structure
*/
typedef void (*lighting_command_lock_callback)(
struct bacnet_lighting_command_data *);
/** /**
* @brief Callback that manipulates the value at the specified priority slot * @brief Callback that manipulates the value at the specified priority slot
after a delay of Egress_Time seconds. after a delay of Egress_Time seconds.
@@ -91,6 +98,10 @@ typedef struct bacnet_lighting_command_data {
uint32_t Key; uint32_t Key;
struct lighting_command_notification Notification_Head; struct lighting_command_notification Notification_Head;
struct lighting_command_timer_notification Timer_Notification_Head; struct lighting_command_timer_notification Timer_Notification_Head;
/* lock for accessing shared state */
lighting_command_lock_callback Lock;
lighting_command_lock_callback Unlock;
void *Context;
} BACNET_LIGHTING_COMMAND_DATA; } BACNET_LIGHTING_COMMAND_DATA;
#ifdef __cplusplus #ifdef __cplusplus
@@ -117,6 +128,10 @@ void lighting_command_blink_warn(
BACNET_LIGHTING_OPERATION operation, BACNET_LIGHTING_OPERATION operation,
struct bacnet_lighting_command_warn_data *blink); struct bacnet_lighting_command_warn_data *blink);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void lighting_command_blink_copy(
struct bacnet_lighting_command_data *data,
struct bacnet_lighting_command_warn_data *blink);
BACNET_STACK_EXPORT
void lighting_command_stop(struct bacnet_lighting_command_data *data); void lighting_command_stop(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void lighting_command_none(struct bacnet_lighting_command_data *data); void lighting_command_none(struct bacnet_lighting_command_data *data);
@@ -167,6 +182,71 @@ float lighting_command_normalized_on_range_clamp(
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
float lighting_command_physical_range_clamp(float value); float lighting_command_physical_range_clamp(float value);
BACNET_STACK_EXPORT
void lighting_command_trim_set(
struct bacnet_lighting_command_data *data,
float High_End_Trim,
float Low_End_Trim,
uint32_t Trim_Fade_Time);
BACNET_STACK_EXPORT
void lighting_command_key_set(
struct bacnet_lighting_command_data *data, uint32_t key);
BACNET_STACK_EXPORT
void lighting_command_tracking_value_callback_set(
struct bacnet_lighting_command_data *data,
lighting_command_tracking_value_callback cb);
BACNET_STACK_EXPORT
BACNET_LIGHTING_IN_PROGRESS
lighting_command_in_progress_get(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_in_progress_set(
struct bacnet_lighting_command_data *data,
BACNET_LIGHTING_IN_PROGRESS in_progress);
BACNET_STACK_EXPORT
float lighting_command_tracking_value_get(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_tracking_value_set(
struct bacnet_lighting_command_data *data, float value);
BACNET_STACK_EXPORT
void lighting_command_blink_warn_feature_set(
struct bacnet_lighting_command_data *data,
float off_value,
uint16_t interval,
uint16_t count);
BACNET_STACK_EXPORT
bool lighting_command_blink_egress_active(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
bool lighting_command_out_of_service_get(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_out_of_service_set(
struct bacnet_lighting_command_data *data, bool value);
BACNET_STACK_EXPORT
float lighting_command_last_on_value_get(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_last_on_value_set(
struct bacnet_lighting_command_data *data, float value);
BACNET_STACK_EXPORT
float lighting_command_default_on_value_get(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_default_on_value_set(
struct bacnet_lighting_command_data *data, float value);
BACNET_STACK_EXPORT
bool lighting_command_overridden_status(
struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
bool lighting_command_active(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_lock(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT
void lighting_command_unlock(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT
void lighting_command_refresh(struct bacnet_lighting_command_data *data); void lighting_command_refresh(struct bacnet_lighting_command_data *data);
BACNET_STACK_EXPORT BACNET_STACK_EXPORT