Add support for Event_Message_Texts and Fault Event Notifications in Analog Input objects (#1188)
This commit is contained in:
+349
-148
@@ -55,6 +55,7 @@ static const int32_t Properties_Optional[] = {
|
||||
PROP_NOTIFY_TYPE,
|
||||
PROP_EVENT_TIME_STAMPS,
|
||||
PROP_EVENT_DETECTION_ENABLE,
|
||||
PROP_EVENT_MESSAGE_TEXTS,
|
||||
#endif
|
||||
-1
|
||||
};
|
||||
@@ -462,6 +463,21 @@ bool Analog_Input_Notify_Type_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
Analog_Input_Reset_Event_Properties(struct analog_input_descr *pObject)
|
||||
{
|
||||
unsigned j;
|
||||
/* initialize Event time stamps using wildcards
|
||||
and set Acked_transitions */
|
||||
for (j = 0; j < MAX_BACNET_EVENT_TRANSITION; j++) {
|
||||
datetime_wildcard_set(&pObject->Event_Time_Stamps[j]);
|
||||
pObject->Acked_Transitions[j].bIsAcked = true;
|
||||
pObject->Event_Message_Texts[j] = NULL;
|
||||
}
|
||||
pObject->Event_State = EVENT_STATE_NORMAL;
|
||||
pObject->Last_ToFault_Event_Reliability = RELIABILITY_NO_FAULT_DETECTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, gets the event-detection-enable property
|
||||
* value
|
||||
@@ -500,6 +516,13 @@ bool Analog_Input_Event_Detection_Enable_Set(
|
||||
|
||||
if (pObject) {
|
||||
pObject->Event_Detection_Enable = value;
|
||||
if (!pObject->Event_Detection_Enable) {
|
||||
/*When this property is FALSE, Event_State shall be NORMAL, and the
|
||||
properties Acked_Transitions, Event_Time_Stamps, and
|
||||
Event_Message_Texts shall be equal to their respective initial
|
||||
conditions.*/
|
||||
Analog_Input_Reset_Event_Properties(pObject);
|
||||
}
|
||||
retval = true;
|
||||
}
|
||||
|
||||
@@ -808,6 +831,59 @@ void Analog_Input_Out_Of_Service_Set(uint32_t object_instance, bool value)
|
||||
}
|
||||
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number and event transition, returns the
|
||||
* event message text
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param transition - transition type
|
||||
* @return event message text or NULL if object not found or transition invalid
|
||||
*/
|
||||
const char *Analog_Input_Event_Message_Text(
|
||||
const uint32_t object_instance,
|
||||
const enum BACnetEventTransitionBits transition)
|
||||
{
|
||||
const char *text = NULL;
|
||||
const struct analog_input_descr *pObject;
|
||||
|
||||
pObject = Analog_Input_Object(object_instance);
|
||||
if (pObject && transition < MAX_BACNET_EVENT_TRANSITION) {
|
||||
text = pObject->Event_Message_Texts[transition];
|
||||
if (!text) {
|
||||
text = "";
|
||||
}
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief For a given object instance-number and event transition, sets the
|
||||
* custom event message text
|
||||
* NOTE: Event_Message_Text will be generated on event if custom_text is null
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param transition - transition type
|
||||
* @param custom_text - holds the event message text to be set
|
||||
* @return true if custom event message text was set
|
||||
*/
|
||||
|
||||
bool Analog_Input_Event_Message_Text_Custom_Set(
|
||||
const uint32_t object_instance,
|
||||
const enum BACnetEventTransitionBits transition,
|
||||
const char *const custom_text)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
struct analog_input_descr *pObject;
|
||||
|
||||
pObject = Analog_Input_Object(object_instance);
|
||||
if (pObject && transition < MAX_BACNET_EVENT_TRANSITION) {
|
||||
pObject->Event_Message_Texts_Custom[transition] = custom_text;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a EventTimeStamps property element
|
||||
* @param object_instance [in] BACnet network port object instance number
|
||||
@@ -855,6 +931,32 @@ static int Analog_Input_Event_Time_Stamps_Encode(
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Encode a BACnetARRAY property element
|
||||
* @param object_instance [in] object instance number
|
||||
* @param index [in] array index requested:
|
||||
* 0 to N for individual array members
|
||||
* @param apdu [out] Buffer in which the APDU contents are built, or NULL to
|
||||
* return the length of buffer if it had been built
|
||||
* @return The length of the apdu encoded or
|
||||
* BACNET_STATUS_ERROR for ERROR_CODE_INVALID_ARRAY_INDEX
|
||||
*/
|
||||
static int Analog_Input_Event_Message_Texts_Encode(
|
||||
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
const char *text = NULL; /* return value */
|
||||
BACNET_CHARACTER_STRING char_string = { 0 };
|
||||
|
||||
text = Analog_Input_Event_Message_Text(object_instance, index);
|
||||
if (text) {
|
||||
characterstring_init_ansi(&char_string, text);
|
||||
apdu_len = encode_application_character_string(apdu, &char_string);
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -1021,6 +1123,19 @@ int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
}
|
||||
break;
|
||||
case PROP_EVENT_MESSAGE_TEXTS:
|
||||
apdu_len = bacnet_array_encode(
|
||||
rpdata->object_instance, rpdata->array_index,
|
||||
Analog_Input_Event_Message_Texts_Encode,
|
||||
MAX_BACNET_EVENT_TRANSITION, apdu, apdu_size);
|
||||
if (apdu_len == BACNET_STATUS_ABORT) {
|
||||
rpdata->error_code =
|
||||
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||
} else if (apdu_len == BACNET_STATUS_ERROR) {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
@@ -1216,6 +1331,20 @@ bool Analog_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
return status;
|
||||
}
|
||||
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
static const char *Analog_Input_Event_Message(
|
||||
struct analog_input_descr *pObject,
|
||||
enum BACnetEventTransitionBits transition,
|
||||
const char *default_text)
|
||||
{
|
||||
if (pObject && transition < MAX_BACNET_EVENT_TRANSITION &&
|
||||
pObject->Event_Message_Texts_Custom[transition]) {
|
||||
return pObject->Event_Message_Texts_Custom[transition];
|
||||
}
|
||||
return default_text;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Handles the Intrinsic Reporting Service for the Analog Input Object
|
||||
* @param object_instance - object-instance number of the object
|
||||
@@ -1224,12 +1353,15 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
{
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 };
|
||||
BACNET_CHARACTER_STRING msgText = { 0 };
|
||||
const char *msgText = NULL;
|
||||
BACNET_CHARACTER_STRING msgCharString = { 0 };
|
||||
struct analog_input_descr *CurrentAI = NULL;
|
||||
uint8_t FromState = 0;
|
||||
uint8_t ToState = 0;
|
||||
float ExceededLimit = 0.0f;
|
||||
float PresentVal = 0.0f;
|
||||
BACNET_RELIABILITY Reliability = RELIABILITY_NO_FAULT_DETECTED;
|
||||
BACNET_PROPERTY_VALUE propertyValues = { 0 };
|
||||
bool SendNotify = false;
|
||||
|
||||
CurrentAI = Analog_Input_Object(object_instance);
|
||||
@@ -1249,151 +1381,184 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
ToState = CurrentAI->Ack_notify_data.EventState;
|
||||
debug_printf(
|
||||
"Analog-Input[%d]: Send AckNotification.\n", object_instance);
|
||||
characterstring_init_ansi(&msgText, "AckNotification");
|
||||
msgText = "AckNotification";
|
||||
/* Notify Type */
|
||||
event_data.notifyType = NOTIFY_ACK_NOTIFICATION;
|
||||
/* Send EventNotification. */
|
||||
SendNotify = true;
|
||||
} else {
|
||||
/* actual Present_Value */
|
||||
PresentVal = Analog_Input_Present_Value(object_instance);
|
||||
PresentVal = CurrentAI->Present_Value;
|
||||
FromState = CurrentAI->Event_State;
|
||||
switch (CurrentAI->Event_State) {
|
||||
case EVENT_STATE_NORMAL:
|
||||
/* A TO-OFFNORMAL event is generated under these conditions:
|
||||
(a) the Present_Value must exceed the High_Limit for a
|
||||
minimum period of time, specified in the Time_Delay property,
|
||||
and (b) the HighLimitEnable flag must be set in the
|
||||
Limit_Enable property, and
|
||||
(c) the TO-OFFNORMAL flag must be set in the Event_Enable
|
||||
property. */
|
||||
if ((PresentVal > CurrentAI->High_Limit) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ==
|
||||
EVENT_HIGH_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ==
|
||||
EVENT_ENABLE_TO_OFFNORMAL)) {
|
||||
if (!CurrentAI->Remaining_Time_Delay) {
|
||||
CurrentAI->Event_State = EVENT_STATE_HIGH_LIMIT;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
Reliability = CurrentAI->Reliability;
|
||||
if (Reliability != RELIABILITY_NO_FAULT_DETECTED) {
|
||||
/*Fault detection takes precedence over the detection of normal and
|
||||
offnormal states. As such, when Reliability has a value other than
|
||||
NO_FAULT_DETECTED, the event-state-detection process will determine
|
||||
the object's event state to be FAULT.*/
|
||||
CurrentAI->Event_State = EVENT_STATE_FAULT;
|
||||
} else if (FromState == EVENT_STATE_FAULT) {
|
||||
CurrentAI->Event_State = EVENT_STATE_NORMAL;
|
||||
} else {
|
||||
switch (CurrentAI->Event_State) {
|
||||
case EVENT_STATE_NORMAL:
|
||||
/* A TO-OFFNORMAL event is generated under these conditions:
|
||||
(a) the Present_Value must exceed the High_Limit for a
|
||||
minimum period of time, specified in the Time_Delay
|
||||
property, and (b) the HighLimitEnable flag must be set in
|
||||
the Limit_Enable property, and (c) the TO-OFFNORMAL flag
|
||||
must be set in the Event_Enable property. */
|
||||
if ((PresentVal > CurrentAI->High_Limit) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ==
|
||||
EVENT_HIGH_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable &
|
||||
EVENT_ENABLE_TO_OFFNORMAL) ==
|
||||
EVENT_ENABLE_TO_OFFNORMAL)) {
|
||||
if (!CurrentAI->Remaining_Time_Delay) {
|
||||
CurrentAI->Event_State = EVENT_STATE_HIGH_LIMIT;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* A TO-OFFNORMAL event is generated under these conditions:
|
||||
(a) the Present_Value must exceed the Low_Limit plus the
|
||||
Deadband for a minimum period of time, specified in the
|
||||
Time_Delay property, and (b) the LowLimitEnable flag must be
|
||||
set in the Limit_Enable property, and
|
||||
(c) the TO-NORMAL flag must be set in the Event_Enable
|
||||
property. */
|
||||
if ((PresentVal < CurrentAI->Low_Limit) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ==
|
||||
EVENT_LOW_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ==
|
||||
EVENT_ENABLE_TO_OFFNORMAL)) {
|
||||
if (!CurrentAI->Remaining_Time_Delay) {
|
||||
CurrentAI->Event_State = EVENT_STATE_LOW_LIMIT;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
/* A TO-OFFNORMAL event is generated under these conditions:
|
||||
(a) the Present_Value must exceed the Low_Limit plus the
|
||||
Deadband for a minimum period of time, specified in the
|
||||
Time_Delay property, and (b) the LowLimitEnable flag must be
|
||||
set in the Limit_Enable property, and
|
||||
(c) the TO-NORMAL flag must be set in the Event_Enable
|
||||
property. */
|
||||
if ((PresentVal < CurrentAI->Low_Limit) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ==
|
||||
EVENT_LOW_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable &
|
||||
EVENT_ENABLE_TO_OFFNORMAL) ==
|
||||
EVENT_ENABLE_TO_OFFNORMAL)) {
|
||||
if (!CurrentAI->Remaining_Time_Delay) {
|
||||
CurrentAI->Event_State = EVENT_STATE_LOW_LIMIT;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
case EVENT_STATE_HIGH_LIMIT:
|
||||
/* Once exceeded, the Present_Value must fall below the
|
||||
High_Limit minus the Deadband before a TO-NORMAL event is
|
||||
generated under these conditions: (a) the Present_Value must
|
||||
fall below the High_Limit minus the Deadband for a minimum
|
||||
period of time, specified in the Time_Delay property, and (b)
|
||||
the HighLimitEnable flag must be set in the Limit_Enable
|
||||
property, and (c) the TO-NORMAL flag must be set in the
|
||||
Event_Enable property. */
|
||||
if (((PresentVal <
|
||||
CurrentAI->High_Limit - CurrentAI->Deadband) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ==
|
||||
EVENT_HIGH_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
|
||||
EVENT_ENABLE_TO_NORMAL)) ||
|
||||
/* 13.3.6 (c) If pCurrentState is HIGH_LIMIT, and the
|
||||
* HighLimitEnable flag of pLimitEnable is FALSE, then
|
||||
* indicate a transition to the NORMAL event state. */
|
||||
(!(CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE))) {
|
||||
if ((!CurrentAI->Remaining_Time_Delay) ||
|
||||
case EVENT_STATE_HIGH_LIMIT:
|
||||
/* Once exceeded, the Present_Value must fall below the
|
||||
High_Limit minus the Deadband before a TO-NORMAL event is
|
||||
generated under these conditions: (a) the Present_Value must
|
||||
fall below the High_Limit minus the Deadband for a minimum
|
||||
period of time, specified in the Time_Delay property, and
|
||||
(b) the HighLimitEnable flag must be set in the Limit_Enable
|
||||
property, and (c) the TO-NORMAL flag must be set in the
|
||||
Event_Enable property. */
|
||||
if (((PresentVal <
|
||||
CurrentAI->High_Limit - CurrentAI->Deadband) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ==
|
||||
EVENT_HIGH_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
|
||||
EVENT_ENABLE_TO_NORMAL)) ||
|
||||
/* 13.3.6 (c) If pCurrentState is HIGH_LIMIT, and the
|
||||
* HighLimitEnable flag of pLimitEnable is FALSE, then
|
||||
* indicate a transition to the NORMAL event state. */
|
||||
(!(CurrentAI->Limit_Enable &
|
||||
EVENT_HIGH_LIMIT_ENABLE))) {
|
||||
CurrentAI->Event_State = EVENT_STATE_NORMAL;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
if ((!CurrentAI->Remaining_Time_Delay) ||
|
||||
(!(CurrentAI->Limit_Enable &
|
||||
EVENT_HIGH_LIMIT_ENABLE))) {
|
||||
CurrentAI->Event_State = EVENT_STATE_NORMAL;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
case EVENT_STATE_LOW_LIMIT:
|
||||
/* Once the Present_Value has fallen below the Low_Limit,
|
||||
the Present_Value must exceed the Low_Limit plus the Deadband
|
||||
before a TO-NORMAL event is generated under these conditions:
|
||||
(a) the Present_Value must exceed the Low_Limit plus the
|
||||
Deadband for a minimum period of time, specified in the
|
||||
Time_Delay property, and (b) the LowLimitEnable flag must be
|
||||
set in the Limit_Enable property, and
|
||||
(c) the TO-NORMAL flag must be set in the Event_Enable
|
||||
property. */
|
||||
if (((PresentVal >
|
||||
CurrentAI->Low_Limit + CurrentAI->Deadband) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ==
|
||||
EVENT_LOW_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
|
||||
EVENT_ENABLE_TO_NORMAL)) ||
|
||||
/* 13.3.6 (f) If pCurrentState is LOW_LIMIT, and the
|
||||
* LowLimitEnable flag of pLimitEnable is FALSE, then
|
||||
* indicate a transition to the NORMAL event state. */
|
||||
(!(CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE))) {
|
||||
if ((!CurrentAI->Remaining_Time_Delay) ||
|
||||
case EVENT_STATE_LOW_LIMIT:
|
||||
/* Once the Present_Value has fallen below the Low_Limit,
|
||||
the Present_Value must exceed the Low_Limit plus the
|
||||
Deadband before a TO-NORMAL event is generated under these
|
||||
conditions: (a) the Present_Value must exceed the Low_Limit
|
||||
plus the Deadband for a minimum period of time, specified in
|
||||
the Time_Delay property, and (b) the LowLimitEnable flag
|
||||
must be set in the Limit_Enable property, and (c) the
|
||||
TO-NORMAL flag must be set in the Event_Enable property. */
|
||||
if (((PresentVal >
|
||||
CurrentAI->Low_Limit + CurrentAI->Deadband) &&
|
||||
((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ==
|
||||
EVENT_LOW_LIMIT_ENABLE) &&
|
||||
((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
|
||||
EVENT_ENABLE_TO_NORMAL)) ||
|
||||
/* 13.3.6 (f) If pCurrentState is LOW_LIMIT, and the
|
||||
* LowLimitEnable flag of pLimitEnable is FALSE, then
|
||||
* indicate a transition to the NORMAL event state. */
|
||||
(!(CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE))) {
|
||||
CurrentAI->Event_State = EVENT_STATE_NORMAL;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
if ((!CurrentAI->Remaining_Time_Delay) ||
|
||||
(!(CurrentAI->Limit_Enable &
|
||||
EVENT_LOW_LIMIT_ENABLE))) {
|
||||
CurrentAI->Event_State = EVENT_STATE_NORMAL;
|
||||
} else {
|
||||
CurrentAI->Remaining_Time_Delay--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
}
|
||||
/* value of the object is still in the same event state */
|
||||
CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay;
|
||||
break;
|
||||
default:
|
||||
return; /* shouldn't happen */
|
||||
} /* switch (FromState) */
|
||||
default:
|
||||
return; /* shouldn't happen */
|
||||
} /* switch (FromState) */
|
||||
}
|
||||
ToState = CurrentAI->Event_State;
|
||||
if (FromState != ToState) {
|
||||
if (FromState != ToState ||
|
||||
(ToState == EVENT_STATE_FAULT &&
|
||||
Reliability != CurrentAI->Last_ToFault_Event_Reliability)) {
|
||||
/* Event_State has changed.
|
||||
Need to fill only the basic parameters of this type of event.
|
||||
Other parameters will be filled in common function. */
|
||||
switch (ToState) {
|
||||
case EVENT_STATE_HIGH_LIMIT:
|
||||
ExceededLimit = CurrentAI->High_Limit;
|
||||
characterstring_init_ansi(&msgText, "Goes to high limit");
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_OFFNORMAL,
|
||||
"Goes to high limit");
|
||||
break;
|
||||
|
||||
case EVENT_STATE_LOW_LIMIT:
|
||||
ExceededLimit = CurrentAI->Low_Limit;
|
||||
characterstring_init_ansi(&msgText, "Goes to low limit");
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_OFFNORMAL,
|
||||
"Goes to low limit");
|
||||
break;
|
||||
|
||||
case EVENT_STATE_NORMAL:
|
||||
if (FromState == EVENT_STATE_HIGH_LIMIT) {
|
||||
ExceededLimit = CurrentAI->High_Limit;
|
||||
characterstring_init_ansi(
|
||||
&msgText, "Back to normal state from high limit");
|
||||
} else {
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_NORMAL,
|
||||
"Back to normal state from high limit");
|
||||
} else if (FromState == EVENT_STATE_LOW_LIMIT) {
|
||||
ExceededLimit = CurrentAI->Low_Limit;
|
||||
characterstring_init_ansi(
|
||||
&msgText, "Back to normal state from low limit");
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_NORMAL,
|
||||
"Back to normal state from low limit");
|
||||
} else {
|
||||
ExceededLimit = 0;
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_NORMAL,
|
||||
"Back to normal state from fault");
|
||||
}
|
||||
break;
|
||||
|
||||
case EVENT_STATE_FAULT:
|
||||
ExceededLimit = 0;
|
||||
msgText = Analog_Input_Event_Message(
|
||||
CurrentAI, TRANSITION_TO_FAULT,
|
||||
bactext_reliability_name(Reliability));
|
||||
CurrentAI->Last_ToFault_Event_Reliability = Reliability;
|
||||
break;
|
||||
|
||||
default:
|
||||
ExceededLimit = 0;
|
||||
break;
|
||||
@@ -1419,23 +1584,35 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
datetime_local(
|
||||
&event_data.timeStamp.value.dateTime.date,
|
||||
&event_data.timeStamp.value.dateTime.time, NULL, NULL);
|
||||
/* fill Event_Time_Stamps */
|
||||
/* set eventType and fill Event_Time_Stamps and
|
||||
* Event_Message_Texts*/
|
||||
switch (ToState) {
|
||||
case EVENT_STATE_HIGH_LIMIT:
|
||||
case EVENT_STATE_LOW_LIMIT:
|
||||
event_data.eventType = EVENT_OUT_OF_RANGE;
|
||||
datetime_copy(
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL],
|
||||
&event_data.timeStamp.value.dateTime);
|
||||
CurrentAI->Event_Message_Texts[TRANSITION_TO_OFFNORMAL] =
|
||||
msgText;
|
||||
break;
|
||||
case EVENT_STATE_FAULT:
|
||||
event_data.eventType = EVENT_CHANGE_OF_RELIABILITY;
|
||||
datetime_copy(
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_FAULT],
|
||||
&event_data.timeStamp.value.dateTime);
|
||||
CurrentAI->Event_Message_Texts[TRANSITION_TO_FAULT] =
|
||||
msgText;
|
||||
break;
|
||||
case EVENT_STATE_NORMAL:
|
||||
event_data.eventType = FromState == EVENT_STATE_FAULT
|
||||
? EVENT_CHANGE_OF_RELIABILITY
|
||||
: EVENT_OUT_OF_RANGE;
|
||||
datetime_copy(
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_NORMAL],
|
||||
&event_data.timeStamp.value.dateTime);
|
||||
CurrentAI->Event_Message_Texts[TRANSITION_TO_NORMAL] =
|
||||
msgText;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -1445,16 +1622,21 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
switch (ToState) {
|
||||
case EVENT_STATE_HIGH_LIMIT:
|
||||
case EVENT_STATE_LOW_LIMIT:
|
||||
event_data.eventType = EVENT_OUT_OF_RANGE;
|
||||
datetime_copy(
|
||||
&event_data.timeStamp.value.dateTime,
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL]);
|
||||
break;
|
||||
case EVENT_STATE_FAULT:
|
||||
event_data.eventType = EVENT_CHANGE_OF_RELIABILITY;
|
||||
datetime_copy(
|
||||
&event_data.timeStamp.value.dateTime,
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_FAULT]);
|
||||
break;
|
||||
case EVENT_STATE_NORMAL:
|
||||
event_data.eventType = FromState == EVENT_STATE_FAULT
|
||||
? EVENT_CHANGE_OF_RELIABILITY
|
||||
: EVENT_OUT_OF_RANGE;
|
||||
datetime_copy(
|
||||
&event_data.timeStamp.value.dateTime,
|
||||
&CurrentAI->Event_Time_Stamps[TRANSITION_TO_NORMAL]);
|
||||
@@ -1465,10 +1647,9 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
}
|
||||
/* Notification Class */
|
||||
event_data.notificationClass = CurrentAI->Notification_Class;
|
||||
/* Event Type */
|
||||
event_data.eventType = EVENT_OUT_OF_RANGE;
|
||||
/* Message Text */
|
||||
event_data.messageText = &msgText;
|
||||
characterstring_init_ansi(&msgCharString, msgText);
|
||||
event_data.messageText = &msgCharString;
|
||||
/* Notify Type */
|
||||
/* filled before */
|
||||
/* From State */
|
||||
@@ -1479,31 +1660,59 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
|
||||
event_data.toState = CurrentAI->Event_State;
|
||||
/* Event Values */
|
||||
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) {
|
||||
/* Value that exceeded a limit. */
|
||||
event_data.notificationParams.outOfRange.exceedingValue =
|
||||
PresentVal;
|
||||
/* Status_Flags of the referenced object. */
|
||||
bitstring_init(
|
||||
&event_data.notificationParams.outOfRange.statusFlags);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_IN_ALARM,
|
||||
CurrentAI->Event_State != EVENT_STATE_NORMAL);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OUT_OF_SERVICE, CurrentAI->Out_Of_Service);
|
||||
/* Deadband used for limit checking. */
|
||||
event_data.notificationParams.outOfRange.deadband =
|
||||
CurrentAI->Deadband;
|
||||
/* Limit that was exceeded. */
|
||||
event_data.notificationParams.outOfRange.exceededLimit =
|
||||
ExceededLimit;
|
||||
if (event_data.eventType == EVENT_OUT_OF_RANGE) {
|
||||
/* Value that exceeded a limit. */
|
||||
event_data.notificationParams.outOfRange.exceedingValue =
|
||||
PresentVal;
|
||||
/* Status_Flags of the referenced object. */
|
||||
bitstring_init(
|
||||
&event_data.notificationParams.outOfRange.statusFlags);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_IN_ALARM,
|
||||
CurrentAI->Event_State != EVENT_STATE_NORMAL);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_FAULT, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OUT_OF_SERVICE, CurrentAI->Out_Of_Service);
|
||||
/* Deadband used for limit checking. */
|
||||
event_data.notificationParams.outOfRange.deadband =
|
||||
CurrentAI->Deadband;
|
||||
/* Limit that was exceeded. */
|
||||
event_data.notificationParams.outOfRange.exceededLimit =
|
||||
ExceededLimit;
|
||||
} else {
|
||||
event_data.notificationParams.changeOfReliability.reliability =
|
||||
Reliability;
|
||||
|
||||
propertyValues.propertyIdentifier = PROP_PRESENT_VALUE;
|
||||
propertyValues.propertyArrayIndex = BACNET_ARRAY_ALL;
|
||||
propertyValues.value.tag = BACNET_APPLICATION_TAG_REAL;
|
||||
propertyValues.value.type.Real = PresentVal;
|
||||
event_data.notificationParams.changeOfReliability
|
||||
.propertyValues = &propertyValues;
|
||||
|
||||
bitstring_init(&event_data.notificationParams
|
||||
.changeOfReliability.statusFlags);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_IN_ALARM, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_FAULT,
|
||||
CurrentAI->Event_State != EVENT_STATE_NORMAL);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OVERRIDDEN, false);
|
||||
bitstring_set_bit(
|
||||
&event_data.notificationParams.outOfRange.statusFlags,
|
||||
STATUS_FLAG_OUT_OF_SERVICE, CurrentAI->Out_Of_Service);
|
||||
}
|
||||
}
|
||||
/* add data from notification class */
|
||||
debug_printf(
|
||||
@@ -1832,9 +2041,6 @@ uint32_t Analog_Input_Create(uint32_t object_instance)
|
||||
{
|
||||
struct analog_input_descr *pObject = NULL;
|
||||
int index = 0;
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
unsigned j;
|
||||
#endif
|
||||
|
||||
if (!Object_List) {
|
||||
Object_List = Keylist_Create();
|
||||
@@ -1868,12 +2074,7 @@ uint32_t Analog_Input_Create(uint32_t object_instance)
|
||||
pObject->Time_Delay = 0;
|
||||
/* notification class not connected */
|
||||
pObject->Notification_Class = BACNET_MAX_INSTANCE;
|
||||
/* initialize Event time stamps using wildcards
|
||||
and set Acked_transitions */
|
||||
for (j = 0; j < MAX_BACNET_EVENT_TRANSITION; j++) {
|
||||
datetime_wildcard_set(&pObject->Event_Time_Stamps[j]);
|
||||
pObject->Acked_Transitions[j].bIsAcked = true;
|
||||
}
|
||||
Analog_Input_Reset_Event_Properties(pObject);
|
||||
#endif
|
||||
/* add to list */
|
||||
index = Keylist_Data_Add(Object_List, object_instance, pObject);
|
||||
|
||||
@@ -47,10 +47,13 @@ typedef struct analog_input_descr {
|
||||
unsigned Notify_Type : 1;
|
||||
ACKED_INFO Acked_Transitions[MAX_BACNET_EVENT_TRANSITION];
|
||||
BACNET_DATE_TIME Event_Time_Stamps[MAX_BACNET_EVENT_TRANSITION];
|
||||
const char *Event_Message_Texts[MAX_BACNET_EVENT_TRANSITION];
|
||||
const char *Event_Message_Texts_Custom[MAX_BACNET_EVENT_TRANSITION];
|
||||
/* time to generate event notification */
|
||||
uint32_t Remaining_Time_Delay;
|
||||
/* AckNotification information */
|
||||
ACK_NOTIFICATION Ack_notify_data;
|
||||
BACNET_RELIABILITY Last_ToFault_Event_Reliability;
|
||||
#endif
|
||||
} ANALOG_INPUT_DESCR;
|
||||
|
||||
@@ -115,9 +118,13 @@ BACNET_STACK_EXPORT
|
||||
void Analog_Input_Out_Of_Service_Set(uint32_t object_instance, bool oos_flag);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
unsigned Analog_Input_Event_State(uint32_t object_instance);
|
||||
const char *Analog_Input_Event_Message_Text(
|
||||
uint32_t object_instance, enum BACnetEventTransitionBits transition);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Analog_Input_Event_State_Set(uint32_t object_instance, unsigned state);
|
||||
bool Analog_Input_Event_Message_Text_Custom_Set(
|
||||
uint32_t object_instance,
|
||||
enum BACnetEventTransitionBits transition,
|
||||
const char *custom_text);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Analog_Input_Change_Of_Value(uint32_t instance);
|
||||
|
||||
@@ -62,8 +62,12 @@ typedef enum {
|
||||
#endif
|
||||
|
||||
#ifndef BACNET_EVENT_CHANGE_OF_RELIABILITY_ENABLED
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
#define BACNET_EVENT_CHANGE_OF_RELIABILITY_ENABLED 1
|
||||
#else
|
||||
#define BACNET_EVENT_CHANGE_OF_RELIABILITY_ENABLED 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef BACNET_EVENT_CHANGE_OF_DISCRETE_VALUE_ENABLED
|
||||
#define BACNET_EVENT_CHANGE_OF_DISCRETE_VALUE_ENABLED 0
|
||||
|
||||
Reference in New Issue
Block a user