Added Binary Input and Binary Value intrinsic reporting CHANGE_OF_STATE algorithm as per 13.3.2 as per ASHRAE 135-2020 (#689)

This commit is contained in:
Tomasz Kazimierz Motyl
2024-07-16 14:16:33 +01:00
committed by GitHub
parent 299d4f36e0
commit f4637325ad
8 changed files with 1883 additions and 8 deletions
+827 -6
View File
@@ -16,6 +16,8 @@
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacdcode.h"
#include "bacnet/bacenum.h"
#include "bacnet/bactext.h"
#include "bacnet/bacapp.h"
#include "bacnet/rp.h"
#include "bacnet/wp.h"
@@ -26,6 +28,11 @@
/* me! */
#include "bacnet/basic/object/bi.h"
#include "bacnet/basic/sys/debug.h"
#if !defined(PRINT)
#define PRINT debug_perror
#endif
static const char *Default_Active_Text = "Active";
static const char *Default_Inactive_Text = "Inactive";
struct object_data {
@@ -34,11 +41,26 @@ struct object_data {
bool Present_Value : 1;
bool Polarity : 1;
bool Write_Enabled : 1;
unsigned Event_State:3;
uint8_t Reliability;
const char *Object_Name;
const char *Active_Text;
const char *Inactive_Text;
const char *Description;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
uint32_t Time_Delay;
uint32_t Notification_Class;
unsigned Event_Enable:3;
unsigned Event_Detection_Enable:1;
unsigned Notify_Type:1;
ACKED_INFO Acked_Transitions[MAX_BACNET_EVENT_TRANSITION];
BACNET_DATE_TIME Event_Time_Stamps[MAX_BACNET_EVENT_TRANSITION];
/* time to generate event notification */
uint32_t Remaining_Time_Delay;
/* AckNotification information */
ACK_NOTIFICATION Ack_notify_data;
BACNET_BINARY_PV Alarm_Value;
#endif
};
/* Key List for storing the object data sorted by instance number */
static OS_Keylist Object_List;
@@ -55,9 +77,16 @@ static const int Properties_Required[] = {
PROP_OUT_OF_SERVICE, PROP_POLARITY, -1
};
static const int Properties_Optional[] = { PROP_RELIABILITY, PROP_DESCRIPTION,
PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT,
-1 };
static const int Properties_Optional[] = { PROP_RELIABILITY,
PROP_DESCRIPTION, PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT,
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUE,
PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS,
PROP_EVENT_DETECTION_ENABLE,
#endif
-1 };
static const int Properties_Proprietary[] = { -1 };
@@ -114,7 +143,7 @@ bool Binary_Input_Valid_Instance(uint32_t object_instance)
/**
* @brief Determines the number of objects
* @return Number of Analog Value objects
* @return Number of Binary Input objects
*/
unsigned Binary_Input_Count(void)
{
@@ -269,8 +298,7 @@ bool Binary_Input_Out_Of_Service(uint32_t object_instance)
}
/**
* @brief For a given object instance-number, sets the out-of-service property
* value
* @brief For a given object instance-number, sets the out-of-service property value
* @param object_instance - object-instance number of the object
* @param value - boolean out-of-service value
* @return true if the out-of-service property value was set
@@ -736,6 +764,55 @@ bool Binary_Input_Active_Text_Set(uint32_t object_instance, char *new_name)
return status;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
/**
* @brief Encode a EventTimeStamps property element
* @param object_instance [in] BACnet network port 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 Binary_Input_Event_Time_Stamps_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = 0, len = 0;
struct object_data *pObject = Binary_Input_Object(object_instance);
if (pObject) {
if (index < MAX_BACNET_EVENT_TRANSITION) {
len = encode_opening_tag(apdu, TIME_STAMP_DATETIME);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_application_date(
apdu, &pObject->Event_Time_Stamps[index].date);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_application_time(
apdu, &pObject->Event_Time_Stamps[index].time);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_closing_tag(apdu, TIME_STAMP_DATETIME);
apdu_len += len;
} else {
apdu_len = BACNET_STATUS_ERROR;
}
} else {
apdu_len = BACNET_STATUS_ERROR;
}
return apdu_len;
}
#endif
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
@@ -753,12 +830,25 @@ int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
bool state = false;
struct object_data *pObject;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
int apdu_size = 0;
#endif
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
if(!(pObject = Binary_Input_Object(rpdata->object_instance))) {
#if !(defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING))
(void) pObject;
#endif
return BACNET_STATUS_ERROR;
}
apdu = rpdata->application_data;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
apdu_size = rpdata->application_data_len;
#endif
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
@@ -825,6 +915,73 @@ int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
case PROP_ALARM_VALUE:
/* note: you need to look up the actual value */
apdu_len = encode_application_enumerated(
&apdu[0], pObject->Alarm_Value);
break;
case PROP_TIME_DELAY:
apdu_len =
encode_application_unsigned(&apdu[0], pObject->Time_Delay);
break;
case PROP_NOTIFICATION_CLASS:
apdu_len = encode_application_unsigned(
&apdu[0], pObject->Notification_Class);
break;
case PROP_EVENT_ENABLE:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true
: false);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
(pObject->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true
: false);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true
: false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_DETECTION_ENABLE:
apdu_len =
encode_application_boolean(&apdu[0], pObject->Event_Detection_Enable);
break;
case PROP_ACKED_TRANSITIONS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_NOTIFY_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], pObject->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM);
break;
case PROP_EVENT_TIME_STAMPS:
apdu_len = bacnet_array_encode(
rpdata->object_instance, rpdata->array_index,
Binary_Input_Event_Time_Stamps_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;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
@@ -855,6 +1012,7 @@ bool Binary_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
struct object_data *pObject;
/* decode the some of the request */
len = bacapp_decode_application_data(
@@ -866,6 +1024,12 @@ bool Binary_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if(!(pObject = Binary_Input_Object(wp_data->object_instance))) {
#if (!BINARY_INPUT_INTRINSIC_REPORTING)
(void) pObject;
#endif
return BACNET_STATUS_ERROR;
}
/* only array properties can have array options */
if (wp_data->array_index != BACNET_ARRAY_ALL) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -905,6 +1069,73 @@ bool Binary_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
}
}
break;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
case PROP_TIME_DELAY:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_UNSIGNED_INT);
if (status) {
pObject->Time_Delay = value.type.Unsigned_Int;
pObject->Remaining_Time_Delay = pObject->Time_Delay;
}
break;
case PROP_NOTIFICATION_CLASS:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_UNSIGNED_INT);
if (status) {
pObject->Notification_Class = value.type.Unsigned_Int;
}
break;
case PROP_ALARM_VALUE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
if (status) {
if (value.type.Enumerated <= MAX_BINARY_PV) {
Binary_Input_Alarm_Value_Set(wp_data->object_instance,
(BACNET_BINARY_PV) value.type.Enumerated);
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_EVENT_ENABLE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_BIT_STRING);
if (status) {
if (value.type.Bit_String.bits_used == 3) {
pObject->Event_Enable = value.type.Bit_String.value[0];
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
status = false;
}
}
break;
case PROP_NOTIFY_TYPE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
if (status) {
switch ((BACNET_NOTIFY_TYPE)value.type.Enumerated) {
case NOTIFY_EVENT:
pObject->Notify_Type = 1;
break;
case NOTIFY_ALARM:
pObject->Notify_Type = 0;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
status = false;
break;
}
}
break;
#endif
default:
if (property_lists_member(
Properties_Required, Properties_Optional,
@@ -1001,6 +1232,9 @@ uint32_t Binary_Input_Create(uint32_t object_instance)
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
if (pObject) {
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
unsigned j;
#endif
pObject->Object_Name = NULL;
pObject->Description = NULL;
pObject->Reliability = RELIABILITY_NO_FAULT_DETECTED;
@@ -1011,6 +1245,26 @@ uint32_t Binary_Input_Create(uint32_t object_instance)
pObject->Change_Of_Value = false;
pObject->Write_Enabled = false;
pObject->Polarity = false;
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
pObject->Event_State = EVENT_STATE_NORMAL;
pObject->Event_Detection_Enable = true;
/* 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;
}
/* Set handler for GetEventInformation function */
handler_get_event_information_set(
Object_Type, Binary_Input_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(Object_Type, Binary_Input_Alarm_Ack);
/* Set handler for GetAlarmSummary Service */
handler_get_alarm_summary_set(
Object_Type, Binary_Input_Alarm_Summary);
#endif
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index < 0) {
@@ -1072,3 +1326,570 @@ void Binary_Input_Init(void)
Object_List = Keylist_Create();
}
}
/**
* For a given object instance-number, gets the event-state property value
*
* @param object_instance - object-instance number of the object
*
* @return event-state property value
*/
unsigned Binary_Input_Event_State(uint32_t object_instance)
{
unsigned state = EVENT_STATE_NORMAL;
#if !(defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING))
(void) object_instance;
#else
struct object_data *pObject = Binary_Input_Object(object_instance);
if (pObject) {
state = pObject->Event_State;
}
#endif
return state;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
/**
* For a given object instance-number, gets the event-detection-enable property value
*
* @param object_instance - object-instance number of the object
*
* @return event-detection-enable property value
*/
bool Binary_Input_Event_Detection_Enable(uint32_t object_instance)
{
bool retval = false;
#if !(defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING))
(void) object_instance;
#else
struct object_data *pObject = Binary_Input_Object(object_instance);
if (pObject) {
retval = pObject->Event_Detection_Enable;
}
#endif
return retval;
}
/**
* For a given object instance-number, sets the event-detection-enable property value
*
* @param object_instance - object-instance number of the object
*
* @return event-detection-enable property value
*/
bool Binary_Input_Event_Detection_Enable_Set(uint32_t object_instance, bool value)
{
bool retval = false;
#if !(defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING))
(void) object_instance;
(void) value;
#else
struct object_data *pObject = Binary_Input_Object(object_instance);
if (pObject) {
pObject->Event_Detection_Enable = value;
retval = true;
}
#endif
return retval;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
/**
* @brief Gets an object from the list using its index in the list
* @param index - index of the object in the list
* @return object found in the list, or NULL if not found
*/
static struct object_data *Binary_Input_Object_Index(int index)
{
return Keylist_Data_Index(Object_List, index);
}
#endif
int Binary_Input_Event_Information(
unsigned index, BACNET_GET_EVENT_INFORMATION_DATA *getevent_data)
{
struct object_data *pObject = Binary_Input_Object_Index(index);
bool IsNotAckedTransitions;
bool IsActiveEvent;
int i;
/* check index */
if (pObject) {
/* Event_State not equal to NORMAL */
IsActiveEvent = (pObject->Event_State != EVENT_STATE_NORMAL);
/* Acked_Transitions property, which has at least one of the bits
(TO-OFFNORMAL, TO-FAULT, TONORMAL) set to FALSE. */
IsNotAckedTransitions =
(pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked ==
false) |
(pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked ==
false) |
(pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked ==
false);
} else
return -1; /* end of list */
if ((IsActiveEvent) || (IsNotAckedTransitions)) {
/* Object Identifier */
getevent_data->objectIdentifier.type = Object_Type;
getevent_data->objectIdentifier.instance =
Binary_Input_Index_To_Instance(index);
/* Event State */
getevent_data->eventState = pObject->Event_State;
/* Acknowledged Transitions */
bitstring_init(&getevent_data->acknowledgedTransitions);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
/* Event Time Stamps */
for (i = 0; i < 3; i++) {
getevent_data->eventTimeStamps[i].tag = TIME_STAMP_DATETIME;
getevent_data->eventTimeStamps[i].value.dateTime =
pObject->Event_Time_Stamps[i];
}
/* Notify Type */
getevent_data->notifyType = pObject->Notify_Type;
/* Event Enable */
bitstring_init(&getevent_data->eventEnable);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_OFFNORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true : false);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_FAULT,
(pObject->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true : false);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_NORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true : false);
/* Event Priorities */
Notification_Class_Get_Priorities(
pObject->Notification_Class, getevent_data->eventPriorities);
return 1; /* active event */
} else
return 0; /* no active event at this index */
}
int Binary_Input_Alarm_Ack(
BACNET_ALARM_ACK_DATA *alarmack_data, BACNET_ERROR_CODE *error_code)
{
struct object_data *pObject = NULL;
if (!alarmack_data) {
return -1;
}
pObject = Binary_Input_Object(alarmack_data->eventObjectIdentifier.instance);
if (!pObject) {
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return -1;
}
switch (alarmack_data->eventStateAcked) {
case EVENT_STATE_OFFNORMAL:
if (pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.bIsAcked == false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_FAULT:
if (pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked ==
false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_FAULT]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_NORMAL:
if (pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked ==
false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
default:
return -2;
}
pObject->Ack_notify_data.bSendAckNotify = true;
pObject->Ack_notify_data.EventState = alarmack_data->eventStateAcked;
return 1;
}
int Binary_Input_Alarm_Summary(
unsigned index, BACNET_GET_ALARM_SUMMARY_DATA *getalarm_data)
{
struct object_data *pObject = Binary_Input_Object_Index(index);
if(getalarm_data == NULL) {
PRINT("[%s %d]: NULL pointer parameter! getalarm_data = %p\r\n", __FILE__, __LINE__, (void *) getalarm_data);
return -2;
}
/* check index */
if (pObject) {
/* Event_State is not equal to NORMAL and
Notify_Type property value is ALARM */
if ((pObject->Event_State != EVENT_STATE_NORMAL) &&
(pObject->Notify_Type == NOTIFY_ALARM)) {
/* Object Identifier */
getalarm_data->objectIdentifier.type = Object_Type;
getalarm_data->objectIdentifier.instance =
Binary_Input_Index_To_Instance(index);
/* Alarm State */
getalarm_data->alarmState = pObject->Event_State;
/* Acknowledged Transitions */
bitstring_init(&getalarm_data->acknowledgedTransitions);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
return 1; /* active alarm */
} else
return 0; /* no active alarm at this index */
} else
return -1; /* end of list */
}
bool Binary_Input_Alarm_Value_Set(
uint32_t object_instance, BACNET_BINARY_PV value)
{
bool status = false;
struct object_data *pObject = Binary_Input_Object(object_instance);
if (pObject) {
if (pObject->Polarity != POLARITY_NORMAL) {
value = (value == BINARY_INACTIVE) ? BINARY_ACTIVE : BINARY_INACTIVE;
}
pObject->Alarm_Value = value;
status = true;
}
return status;
}
#endif /* (INTRINSIC_REPORTING) */
void Binary_Input_Intrinsic_Reporting(uint32_t object_instance)
{
#if !(defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING))
(void) object_instance;
#else
BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 };
BACNET_CHARACTER_STRING msgText = { 0 };
uint8_t FromState = 0;
uint8_t ToState = 0;
BACNET_BINARY_PV PresentVal = BINARY_INACTIVE;
bool SendNotify = false;
struct object_data *pObject = Binary_Input_Object(object_instance);
if (!pObject) {
return;
}
/* check whether Intrinsic reporting is enabled */
if (!pObject->Event_Detection_Enable) {
return; /* limits are not configured */
}
if (pObject->Ack_notify_data.bSendAckNotify) {
/* clean bSendAckNotify flag */
pObject->Ack_notify_data.bSendAckNotify = false;
/* copy toState */
ToState = pObject->Ack_notify_data.EventState;
PRINT("Binary-Input[%d]: Send AckNotification.\n", object_instance);
characterstring_init_ansi(&msgText, "AckNotification");
/* Notify Type */
event_data.notifyType = NOTIFY_ACK_NOTIFICATION;
/* Send EventNotification. */
SendNotify = true;
} else {
/* actual Present_Value */
PresentVal = Binary_Input_Present_Value(object_instance);
FromState = pObject->Event_State;
switch (pObject->Event_State) {
case EVENT_STATE_NORMAL:
/* (a) If pCurrentState is NORMAL, and pMonitoredValue is equal to any of the values contained in pAlarmValues for
pTimeDelay, then indicate a transition to the OFFNORMAL event state.
*/
if ((PresentVal == pObject->Alarm_Value) &&
((pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ==
EVENT_ENABLE_TO_OFFNORMAL)) {
if (!pObject->Remaining_Time_Delay)
pObject->Event_State = EVENT_STATE_OFFNORMAL;
else
pObject->Remaining_Time_Delay--;
break;
}
/* value of the object is still in the same event state */
pObject->Remaining_Time_Delay = pObject->Time_Delay;
break;
case EVENT_STATE_OFFNORMAL:
/* (b) If pCurrentState is OFFNORMAL, and pMonitoredValue is not equal to any of the values contained in pAlarmValues
for pTimeDelayNormal, then indicate a transition to the NORMAL event state.
*/
if ((PresentVal != pObject->Alarm_Value) &&
((pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
EVENT_ENABLE_TO_NORMAL)) {
if (!pObject->Remaining_Time_Delay)
pObject->Event_State = EVENT_STATE_NORMAL;
else
pObject->Remaining_Time_Delay--;
break;
}
/* value of the object is still in the same event state */
pObject->Remaining_Time_Delay = pObject->Time_Delay;
break;
default:
return; /* shouldn't happen */
} /* switch (FromState) */
ToState = pObject->Event_State;
if (FromState != ToState) {
/* 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_NORMAL:
characterstring_init_ansi( &msgText, "Back to normal state from off-normal");
break;
case EVENT_STATE_OFFNORMAL:
characterstring_init_ansi( &msgText, "Back to off-normal state from normal");
break;
default:
break;
} /* switch (ToState) */
PRINT("Binary-Input[%d]: Event_State goes from %.128s to %.128s.\n",
object_instance, bactext_event_state_name(FromState),
bactext_event_state_name(ToState));
/* Notify Type */
event_data.notifyType = pObject->Notify_Type;
/* Send EventNotification. */
SendNotify = true;
}
}
if (SendNotify) {
/* Event Object Identifier */
event_data.eventObjectIdentifier.type = Object_Type;
event_data.eventObjectIdentifier.instance = object_instance;
/* Time Stamp */
event_data.timeStamp.tag = TIME_STAMP_DATETIME;
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) {
datetime_local(
&event_data.timeStamp.value.dateTime.date,
&event_data.timeStamp.value.dateTime.time, NULL, NULL);
/* fill Event_Time_Stamps */
switch (ToState) {
case EVENT_STATE_OFFNORMAL:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL],
&event_data.timeStamp.value.dateTime);
break;
case EVENT_STATE_FAULT:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_FAULT],
&event_data.timeStamp.value.dateTime);
break;
case EVENT_STATE_NORMAL:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_NORMAL],
&event_data.timeStamp.value.dateTime);
break;
default:
break;
}
} else {
/* fill event_data timeStamp */
switch (ToState) {
case EVENT_STATE_FAULT:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_FAULT]);
break;
case EVENT_STATE_NORMAL:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_NORMAL]);
break;
case EVENT_STATE_OFFNORMAL:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL]);
break;
default:
break;
}
}
/* Notification Class */
event_data.notificationClass = pObject->Notification_Class;
/* Event Type */
event_data.eventType = EVENT_CHANGE_OF_STATE;
/* Message Text */
event_data.messageText = &msgText;
/* Notify Type */
/* filled before */
/* From State */
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION)
event_data.fromState = FromState;
/* To State */
event_data.toState = pObject->Event_State;
/* Event Values */
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) {
/* Value that exceeded a limit. */
event_data.notificationParams.changeOfState.newState =
(BACNET_PROPERTY_STATE) { .tag = PROP_STATE_BINARY_VALUE, .state = { .binaryValue = pObject->Present_Value } };
/* Status_Flags of the referenced object. */
bitstring_init(
&event_data.notificationParams.changeOfState.statusFlags);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_IN_ALARM,
pObject->Event_State != EVENT_STATE_NORMAL);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_FAULT, false);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_OUT_OF_SERVICE, pObject->Out_Of_Service);
}
/* add data from notification class */
PRINT("Binary-Input[%d]: Notification Class[%d]-%s "
"%u/%u/%u-%u:%u:%u.%u!\n",
object_instance, event_data.notificationClass,
bactext_event_type_name(event_data.eventType),
(unsigned)event_data.timeStamp.value.dateTime.date.year,
(unsigned)event_data.timeStamp.value.dateTime.date.month,
(unsigned)event_data.timeStamp.value.dateTime.date.day,
(unsigned)event_data.timeStamp.value.dateTime.time.hour,
(unsigned)event_data.timeStamp.value.dateTime.time.min,
(unsigned)event_data.timeStamp.value.dateTime.time.sec,
(unsigned)event_data.timeStamp.value.dateTime.time.hundredths);
Notification_Class_common_reporting_function(&event_data);
/* Ack required */
if ((event_data.notifyType != NOTIFY_ACK_NOTIFICATION) &&
(event_data.ackRequired == true)) {
PRINT("Binary-Input[%d]: Ack Required!\n", object_instance);
switch (event_data.toState) {
case EVENT_STATE_OFFNORMAL:
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.bIsAcked = false;
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
case EVENT_STATE_FAULT:
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked =
false;
pObject->Acked_Transitions[TRANSITION_TO_FAULT]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
case EVENT_STATE_NORMAL:
pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.bIsAcked = false;
pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
default: /* shouldn't happen */
break;
}
}
}
#endif /* defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING) */
}
+45 -1
View File
@@ -20,6 +20,13 @@
#include "bacnet/rp.h"
#include "bacnet/wp.h"
#if (INTRINSIC_REPORTING)
#include "bacnet/basic/object/nc.h"
#include "bacnet/getevent.h"
#include "bacnet/alarm_ack.h"
#include "bacnet/get_alarm_sum.h"
#endif
/**
* @brief Callback for gateway write present value request
* @param object_instance - object-instance number of the object
@@ -121,6 +128,10 @@ extern "C" {
uint32_t object_instance,
bool value);
BACNET_STACK_EXPORT
unsigned Binary_Input_Event_State(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Binary_Input_Encode_Value_List(
uint32_t object_instance,
@@ -141,7 +152,7 @@ extern "C" {
BACNET_STACK_EXPORT
void Binary_Input_Write_Present_Value_Callback_Set(
binary_input_write_present_value_callback cb);
BACNET_STACK_EXPORT
uint32_t Binary_Input_Create(
uint32_t object_instance);
@@ -155,6 +166,39 @@ extern "C" {
void Binary_Input_Init(
void);
#if defined(INTRINSIC_REPORTING) && (BINARY_INPUT_INTRINSIC_REPORTING)
BACNET_STACK_EXPORT
bool Binary_Input_Event_Detection_Enable(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Binary_Input_Event_Detection_Enable_Set(
uint32_t object_instance, bool value);
BACNET_STACK_EXPORT
int Binary_Input_Event_Information(
unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data);
BACNET_STACK_EXPORT
int Binary_Input_Alarm_Ack(
BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code);
BACNET_STACK_EXPORT
int Binary_Input_Alarm_Summary(
unsigned index,
BACNET_GET_ALARM_SUMMARY_DATA * getalarm_data);
BACNET_STACK_EXPORT
bool Binary_Input_Alarm_Value_Set(
uint32_t object_instance, BACNET_BINARY_PV value);
BACNET_STACK_EXPORT
void Binary_Input_Intrinsic_Reporting(
uint32_t object_instance);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
+823 -1
View File
@@ -16,14 +16,23 @@
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacdcode.h"
#include "bacnet/bacenum.h"
#include "bacnet/bactext.h"
#include "bacnet/bacapp.h"
#include "bacnet/wp.h"
#include "bacnet/rp.h"
#include "bacnet/cov.h"
#include "bacnet/basic/services.h"
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/sys/keylist.h"
/* me! */
#include "bacnet/basic/object/bv.h"
#include "bacnet/basic/sys/debug.h"
#if !defined(PRINT)
#define PRINT debug_perror
#endif
static const char *Default_Active_Text = "Active";
static const char *Default_Inactive_Text = "Inactive";
struct object_data {
@@ -32,11 +41,26 @@ struct object_data {
bool Present_Value : 1;
bool Write_Enabled : 1;
bool Polarity : 1;
unsigned Event_State:3;
uint8_t Reliability;
const char *Object_Name;
const char *Active_Text;
const char *Inactive_Text;
const char *Description;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
uint32_t Time_Delay;
uint32_t Notification_Class;
unsigned Event_Enable:3;
unsigned Event_Detection_Enable:1;
unsigned Notify_Type:1;
ACKED_INFO Acked_Transitions[MAX_BACNET_EVENT_TRANSITION];
BACNET_DATE_TIME Event_Time_Stamps[MAX_BACNET_EVENT_TRANSITION];
/* time to generate event notification */
uint32_t Remaining_Time_Delay;
/* AckNotification information */
ACK_NOTIFICATION Ack_notify_data;
BACNET_BINARY_PV Alarm_Value;
#endif
};
/* Key List for storing the object data sorted by instance number */
static OS_Keylist Object_List;
@@ -55,7 +79,15 @@ static const int Binary_Value_Properties_Required[] = {
};
static const int Binary_Value_Properties_Optional[] = {
PROP_DESCRIPTION, PROP_RELIABILITY, PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT, -1
PROP_DESCRIPTION, PROP_RELIABILITY, PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT,
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS,
PROP_ALARM_VALUE,
PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS,
PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS,
PROP_EVENT_DETECTION_ENABLE,
#endif
-1
};
static const int Binary_Value_Properties_Proprietary[] = { -1 };
@@ -741,6 +773,55 @@ bool Binary_Value_Inactive_Text_Set(uint32_t object_instance, char *new_name)
return status;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
/**
* @brief Encode a EventTimeStamps property element
* @param object_instance [in] BACnet network port 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 Binary_Value_Event_Time_Stamps_Encode(
uint32_t object_instance, BACNET_ARRAY_INDEX index, uint8_t *apdu)
{
int apdu_len = 0, len = 0;
struct object_data *pObject = Binary_Value_Object(object_instance);
if (pObject) {
if (index < MAX_BACNET_EVENT_TRANSITION) {
len = encode_opening_tag(apdu, TIME_STAMP_DATETIME);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_application_date(
apdu, &pObject->Event_Time_Stamps[index].date);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_application_time(
apdu, &pObject->Event_Time_Stamps[index].time);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_closing_tag(apdu, TIME_STAMP_DATETIME);
apdu_len += len;
} else {
apdu_len = BACNET_STATUS_ERROR;
}
} else {
apdu_len = BACNET_STATUS_ERROR;
}
return apdu_len;
}
#endif
/**
* ReadProperty handler for this object. For the given ReadProperty
* data, the application_data is loaded or the error flags are set.
@@ -758,12 +839,25 @@ int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
bool state = false;
struct object_data *pObject;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
int apdu_size = 0;
#endif
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
if(!(pObject = Binary_Value_Object(rpdata->object_instance))) {
#if !(defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING))
(void) pObject;
#endif
return BACNET_STATUS_ERROR;
}
apdu = rpdata->application_data;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
apdu_size = rpdata->application_data_len;
#endif
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(
@@ -830,6 +924,70 @@ int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
case PROP_ALARM_VALUE:
/* note: you need to look up the actual value */
apdu_len = encode_application_enumerated(
&apdu[0], pObject->Alarm_Value);
break;
case PROP_TIME_DELAY:
apdu_len =
encode_application_unsigned(&apdu[0], pObject->Time_Delay);
break;
case PROP_NOTIFICATION_CLASS:
apdu_len = encode_application_unsigned(
&apdu[0], pObject->Notification_Class);
break;
case PROP_EVENT_ENABLE:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true : false);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
(pObject->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true : false);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true : false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_DETECTION_ENABLE:
apdu_len =
encode_application_boolean(&apdu[0], pObject->Event_Detection_Enable);
break;
case PROP_ACKED_TRANSITIONS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_NOTIFY_TYPE:
apdu_len = encode_application_enumerated(
&apdu[0], pObject->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM);
break;
case PROP_EVENT_TIME_STAMPS:
apdu_len = bacnet_array_encode(
rpdata->object_instance, rpdata->array_index,
Binary_Value_Event_Time_Stamps_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;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
@@ -860,6 +1018,7 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
struct object_data *pObject;
/* Valid data? */
if (wp_data == NULL) {
@@ -879,6 +1038,12 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
return false;
}
if(!(pObject = Binary_Value_Object(wp_data->object_instance))) {
#if (!BINARY_VALUE_INTRINSIC_REPORTING)
(void) pObject;
#endif
return BACNET_STATUS_ERROR;
}
/* Only array properties can have array options. */
if ((wp_data->object_property != PROP_PRIORITY_ARRAY) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
@@ -919,6 +1084,73 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
}
}
break;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
case PROP_TIME_DELAY:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_UNSIGNED_INT);
if (status) {
pObject->Time_Delay = value.type.Unsigned_Int;
pObject->Remaining_Time_Delay = pObject->Time_Delay;
}
break;
case PROP_NOTIFICATION_CLASS:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_UNSIGNED_INT);
if (status) {
pObject->Notification_Class = value.type.Unsigned_Int;
}
break;
case PROP_ALARM_VALUE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
if (status) {
if (value.type.Enumerated <= MAX_BINARY_PV) {
Binary_Value_Alarm_Value_Set(wp_data->object_instance,
(BACNET_BINARY_PV) value.type.Enumerated);
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_EVENT_ENABLE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_BIT_STRING);
if (status) {
if (value.type.Bit_String.bits_used == 3) {
pObject->Event_Enable = value.type.Bit_String.value[0];
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
status = false;
}
}
break;
case PROP_NOTIFY_TYPE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
if (status) {
switch ((BACNET_NOTIFY_TYPE)value.type.Enumerated) {
case NOTIFY_EVENT:
pObject->Notify_Type = 1;
break;
case NOTIFY_ALARM:
pObject->Notify_Type = 0;
break;
default:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
status = false;
break;
}
}
break;
#endif
default:
if (property_lists_member(
Binary_Value_Properties_Required,
@@ -1017,6 +1249,9 @@ uint32_t Binary_Value_Create(uint32_t object_instance)
if (!pObject) {
pObject = calloc(1, sizeof(struct object_data));
if (pObject) {
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
unsigned j;
#endif
pObject->Object_Name = NULL;
pObject->Description = NULL;
pObject->Reliability = RELIABILITY_NO_FAULT_DETECTED;
@@ -1027,6 +1262,26 @@ uint32_t Binary_Value_Create(uint32_t object_instance)
pObject->Change_Of_Value = false;
pObject->Write_Enabled = false;
pObject->Polarity = false;
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
pObject->Event_State = EVENT_STATE_NORMAL;
pObject->Event_Detection_Enable = true;
/* 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;
}
/* Set handler for GetEventInformation function */
handler_get_event_information_set(
Object_Type, Binary_Value_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(Object_Type, Binary_Value_Alarm_Ack);
/* Set handler for GetAlarmSummary Service */
handler_get_alarm_summary_set(
Object_Type, Binary_Value_Alarm_Summary);
#endif
/* add to list */
index = Keylist_Data_Add(Object_List, object_instance, pObject);
if (index < 0) {
@@ -1086,3 +1341,570 @@ void Binary_Value_Init(void)
Object_List = Keylist_Create();
}
}
/**
* For a given object instance-number, gets the event-state property value
*
* @param object_instance - object-instance number of the object
*
* @return event-state property value
*/
unsigned Binary_Value_Event_State(uint32_t object_instance)
{
unsigned state = EVENT_STATE_NORMAL;
#if !defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
(void) object_instance;
#else
struct object_data *pObject = Binary_Value_Object(object_instance);
if (pObject) {
state = pObject->Event_State;
}
#endif
return state;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
/**
* For a given object instance-number, gets the event-detection-enable property value
*
* @param object_instance - object-instance number of the object
*
* @return event-detection-enable property value
*/
bool Binary_Value_Event_Detection_Enable(uint32_t object_instance)
{
bool retval = false;
#if !(defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING))
(void) object_instance;
#else
struct object_data *pObject = Binary_Value_Object(object_instance);
if (pObject) {
retval = pObject->Event_Detection_Enable;
}
#endif
return retval;
}
/**
* For a given object instance-number, sets the event-detection-enable property value
*
* @param object_instance - object-instance number of the object
*
* @return event-detection-enable property value
*/
bool Binary_Value_Event_Detection_Enable_Set(uint32_t object_instance, bool value)
{
bool retval = false;
#if !(defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING))
(void) object_instance;
(void) value;
#else
struct object_data *pObject = Binary_Value_Object(object_instance);
if (pObject) {
pObject->Event_Detection_Enable = value;
retval = true;
}
#endif
return retval;
}
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
/**
* @brief Gets an object from the list using its index in the list
* @param index - index of the object in the list
* @return object found in the list, or NULL if not found
*/
static struct object_data *Binary_Value_Object_Index(int index)
{
return Keylist_Data_Index(Object_List, index);
}
#endif
int Binary_Value_Event_Information(
unsigned index, BACNET_GET_EVENT_INFORMATION_DATA *getevent_data)
{
struct object_data *pObject = Binary_Value_Object_Index(index);
bool IsNotAckedTransitions;
bool IsActiveEvent;
int i;
/* check index */
if (pObject) {
/* Event_State not equal to NORMAL */
IsActiveEvent = (pObject->Event_State != EVENT_STATE_NORMAL);
/* Acked_Transitions property, which has at least one of the bits
(TO-OFFNORMAL, TO-FAULT, TONORMAL) set to FALSE. */
IsNotAckedTransitions =
(pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked ==
false) |
(pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked ==
false) |
(pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked ==
false);
} else
return -1; /* end of list */
if ((IsActiveEvent) || (IsNotAckedTransitions)) {
/* Object Identifier */
getevent_data->objectIdentifier.type = Object_Type;
getevent_data->objectIdentifier.instance =
Binary_Value_Index_To_Instance(index);
/* Event State */
getevent_data->eventState = pObject->Event_State;
/* Acknowledged Transitions */
bitstring_init(&getevent_data->acknowledgedTransitions);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&getevent_data->acknowledgedTransitions,
TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
/* Event Time Stamps */
for (i = 0; i < 3; i++) {
getevent_data->eventTimeStamps[i].tag = TIME_STAMP_DATETIME;
getevent_data->eventTimeStamps[i].value.dateTime =
pObject->Event_Time_Stamps[i];
}
/* Notify Type */
getevent_data->notifyType = pObject->Notify_Type;
/* Event Enable */
bitstring_init(&getevent_data->eventEnable);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_OFFNORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true : false);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_FAULT,
(pObject->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true : false);
bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_NORMAL,
(pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true : false);
/* Event Priorities */
Notification_Class_Get_Priorities(
pObject->Notification_Class, getevent_data->eventPriorities);
return 1; /* active event */
} else
return 0; /* no active event at this index */
}
int Binary_Value_Alarm_Ack(
BACNET_ALARM_ACK_DATA *alarmack_data, BACNET_ERROR_CODE *error_code)
{
struct object_data *pObject = NULL;
if (!alarmack_data) {
return -1;
}
pObject = Binary_Value_Object(alarmack_data->eventObjectIdentifier.instance);
if (!pObject) {
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return -1;
}
switch (alarmack_data->eventStateAcked) {
case EVENT_STATE_OFFNORMAL:
if (pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.bIsAcked == false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_FAULT:
if (pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked ==
false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_FAULT]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_NORMAL:
if (pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked ==
false) {
if (alarmack_data->eventTimeStamp.tag != TIME_STAMP_DATETIME) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
if (datetime_compare(
&pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0) {
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* Send ack notification */
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked =
true;
} else if (alarmack_data->eventStateAcked ==
pObject->Event_State) {
/* Send ack notification */
} else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
default:
return -2;
}
pObject->Ack_notify_data.bSendAckNotify = true;
pObject->Ack_notify_data.EventState = alarmack_data->eventStateAcked;
return 1;
}
int Binary_Value_Alarm_Summary(
unsigned index, BACNET_GET_ALARM_SUMMARY_DATA *getalarm_data)
{
struct object_data *pObject = Binary_Value_Object_Index(index);
if(getalarm_data == NULL) {
PRINT("[%s %d]: NULL pointer parameter! getalarm_data = %p\r\n", __FILE__, __LINE__, (void *) getalarm_data);
return -2;
}
/* check index */
if (pObject) {
/* Event_State is not equal to NORMAL and
Notify_Type property value is ALARM */
if ((pObject->Event_State != EVENT_STATE_NORMAL) &&
(pObject->Notify_Type == NOTIFY_ALARM)) {
/* Object Identifier */
getalarm_data->objectIdentifier.type = Object_Type;
getalarm_data->objectIdentifier.instance =
Binary_Value_Index_To_Instance(index);
/* Alarm State */
getalarm_data->alarmState = pObject->Event_State;
/* Acknowledged Transitions */
bitstring_init(&getalarm_data->acknowledgedTransitions);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_OFFNORMAL,
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_FAULT,
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked);
bitstring_set_bit(&getalarm_data->acknowledgedTransitions,
TRANSITION_TO_NORMAL,
pObject->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked);
return 1; /* active alarm */
} else
return 0; /* no active alarm at this index */
} else
return -1; /* end of list */
}
bool Binary_Value_Alarm_Value_Set(
uint32_t object_instance, BACNET_BINARY_PV value)
{
bool status = false;
struct object_data *pObject = Binary_Value_Object(object_instance);
if (pObject) {
if (pObject->Polarity != POLARITY_NORMAL) {
value = (value == BINARY_INACTIVE) ? BINARY_ACTIVE : BINARY_INACTIVE;
}
pObject->Alarm_Value = value;
status = true;
}
return status;
}
#endif /* (INTRINSIC_REPORTING) */
void Binary_Value_Intrinsic_Reporting(uint32_t object_instance)
{
#if !(defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING))
(void) object_instance;
#else
BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 };
BACNET_CHARACTER_STRING msgText = { 0 };
uint8_t FromState = 0;
uint8_t ToState = 0;
BACNET_BINARY_PV PresentVal = BINARY_INACTIVE;
bool SendNotify = false;
struct object_data *pObject = Binary_Value_Object(object_instance);
if (!pObject) {
return;
}
/* check whether Intrinsic reporting is enabled */
if (!pObject->Event_Detection_Enable) {
return; /* limits are not configured */
}
if (pObject->Ack_notify_data.bSendAckNotify) {
/* clean bSendAckNotify flag */
pObject->Ack_notify_data.bSendAckNotify = false;
/* copy toState */
ToState = pObject->Ack_notify_data.EventState;
PRINT("Binary-Input[%d]: Send AckNotification.\n", object_instance);
characterstring_init_ansi(&msgText, "AckNotification");
/* Notify Type */
event_data.notifyType = NOTIFY_ACK_NOTIFICATION;
/* Send EventNotification. */
SendNotify = true;
} else {
/* actual Present_Value */
PresentVal = Binary_Value_Present_Value(object_instance);
FromState = pObject->Event_State;
switch (pObject->Event_State) {
case EVENT_STATE_NORMAL:
/* (a) If pCurrentState is NORMAL, and pMonitoredValue is equal to any of the values contained in pAlarmValues for
pTimeDelay, then indicate a transition to the OFFNORMAL event state.
*/
if ((PresentVal == pObject->Alarm_Value) &&
((pObject->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ==
EVENT_ENABLE_TO_OFFNORMAL)) {
if (!pObject->Remaining_Time_Delay)
pObject->Event_State = EVENT_STATE_OFFNORMAL;
else
pObject->Remaining_Time_Delay--;
break;
}
/* value of the object is still in the same event state */
pObject->Remaining_Time_Delay = pObject->Time_Delay;
break;
case EVENT_STATE_OFFNORMAL:
/* (b) If pCurrentState is OFFNORMAL, and pMonitoredValue is not equal to any of the values contained in pAlarmValues
for pTimeDelayNormal, then indicate a transition to the NORMAL event state.
*/
if ((PresentVal != pObject->Alarm_Value) &&
((pObject->Event_Enable & EVENT_ENABLE_TO_NORMAL) ==
EVENT_ENABLE_TO_NORMAL)) {
if (!pObject->Remaining_Time_Delay)
pObject->Event_State = EVENT_STATE_NORMAL;
else
pObject->Remaining_Time_Delay--;
break;
}
/* value of the object is still in the same event state */
pObject->Remaining_Time_Delay = pObject->Time_Delay;
break;
default:
return; /* shouldn't happen */
} /* switch (FromState) */
ToState = pObject->Event_State;
if (FromState != ToState) {
/* 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_NORMAL:
characterstring_init_ansi( &msgText, "Back to normal state from off-normal");
break;
case EVENT_STATE_OFFNORMAL:
characterstring_init_ansi( &msgText, "Back to off-normal state from normal");
break;
default:
break;
} /* switch (ToState) */
PRINT("Binary-Input[%d]: Event_State goes from %.128s to %.128s.\n",
object_instance, bactext_event_state_name(FromState),
bactext_event_state_name(ToState));
/* Notify Type */
event_data.notifyType = pObject->Notify_Type;
/* Send EventNotification. */
SendNotify = true;
}
}
if (SendNotify) {
/* Event Object Identifier */
event_data.eventObjectIdentifier.type = Object_Type;
event_data.eventObjectIdentifier.instance = object_instance;
/* Time Stamp */
event_data.timeStamp.tag = TIME_STAMP_DATETIME;
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) {
datetime_local(
&event_data.timeStamp.value.dateTime.date,
&event_data.timeStamp.value.dateTime.time, NULL, NULL);
/* fill Event_Time_Stamps */
switch (ToState) {
case EVENT_STATE_OFFNORMAL:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL],
&event_data.timeStamp.value.dateTime);
break;
case EVENT_STATE_FAULT:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_FAULT],
&event_data.timeStamp.value.dateTime);
break;
case EVENT_STATE_NORMAL:
datetime_copy(
&pObject->Event_Time_Stamps[TRANSITION_TO_NORMAL],
&event_data.timeStamp.value.dateTime);
break;
default:
break;
}
} else {
/* fill event_data timeStamp */
switch (ToState) {
case EVENT_STATE_FAULT:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_FAULT]);
break;
case EVENT_STATE_NORMAL:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_NORMAL]);
break;
case EVENT_STATE_OFFNORMAL:
datetime_copy(&event_data.timeStamp.value.dateTime,
&pObject->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL]);
break;
default:
break;
}
}
/* Notification Class */
event_data.notificationClass = pObject->Notification_Class;
/* Event Type */
event_data.eventType = EVENT_CHANGE_OF_STATE;
/* Message Text */
event_data.messageText = &msgText;
/* Notify Type */
/* filled before */
/* From State */
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION)
event_data.fromState = FromState;
/* To State */
event_data.toState = pObject->Event_State;
/* Event Values */
if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) {
/* Value that exceeded a limit. */
event_data.notificationParams.changeOfState.newState =
(BACNET_PROPERTY_STATE) { .tag = PROP_STATE_BINARY_VALUE, .state = { .binaryValue = pObject->Present_Value } };
/* Status_Flags of the referenced object. */
bitstring_init(
&event_data.notificationParams.changeOfState.statusFlags);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_IN_ALARM,
pObject->Event_State != EVENT_STATE_NORMAL);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_FAULT, false);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(
&event_data.notificationParams.changeOfState.statusFlags,
STATUS_FLAG_OUT_OF_SERVICE, pObject->Out_Of_Service);
}
/* add data from notification class */
PRINT("Binary-Value[%d]: Notification Class[%d]-%s "
"%u/%u/%u-%u:%u:%u.%u!\n",
object_instance, event_data.notificationClass,
bactext_event_type_name(event_data.eventType),
(unsigned)event_data.timeStamp.value.dateTime.date.year,
(unsigned)event_data.timeStamp.value.dateTime.date.month,
(unsigned)event_data.timeStamp.value.dateTime.date.day,
(unsigned)event_data.timeStamp.value.dateTime.time.hour,
(unsigned)event_data.timeStamp.value.dateTime.time.min,
(unsigned)event_data.timeStamp.value.dateTime.time.sec,
(unsigned)event_data.timeStamp.value.dateTime.time.hundredths);
Notification_Class_common_reporting_function(&event_data);
/* Ack required */
if ((event_data.notifyType != NOTIFY_ACK_NOTIFICATION) &&
(event_data.ackRequired == true)) {
PRINT("Binary-Value[%d]: Ack Required!\n", object_instance);
switch (event_data.toState) {
case EVENT_STATE_OFFNORMAL:
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.bIsAcked = false;
pObject->Acked_Transitions[TRANSITION_TO_OFFNORMAL]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
case EVENT_STATE_FAULT:
pObject->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked =
false;
pObject->Acked_Transitions[TRANSITION_TO_FAULT]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
case EVENT_STATE_NORMAL:
pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.bIsAcked = false;
pObject->Acked_Transitions[TRANSITION_TO_NORMAL]
.Time_Stamp = event_data.timeStamp.value.dateTime;
break;
default: /* shouldn't happen */
break;
}
}
}
#endif /* defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING) */
}
+48
View File
@@ -19,6 +19,12 @@
#include "bacnet/rp.h"
#include "bacnet/wp.h"
#if (INTRINSIC_REPORTING)
#include "bacnet/basic/object/nc.h"
#include "bacnet/getevent.h"
#include "bacnet/alarm_ack.h"
#include "bacnet/get_alarm_sum.h"
#endif
/**
* @brief Callback for gateway write present value request
* @param object_instance - object-instance number of the object
@@ -153,6 +159,48 @@ extern "C" {
BACNET_STACK_EXPORT
void Binary_Value_Cleanup(
void);
BACNET_STACK_EXPORT
bool Binary_Value_Change_Of_Value(
uint32_t object_instance);
BACNET_STACK_EXPORT
void Binary_Value_Change_Of_Value_Clear(
uint32_t object_instance);
BACNET_STACK_EXPORT
unsigned Binary_Input_Event_State(
uint32_t object_instance);
#if defined(INTRINSIC_REPORTING) && (BINARY_VALUE_INTRINSIC_REPORTING)
BACNET_STACK_EXPORT
bool Binary_Value_Event_Detection_Enable(
uint32_t object_instance);
BACNET_STACK_EXPORT
bool Binary_Value_Event_Detection_Enable_Set(
uint32_t object_instance, bool value);
BACNET_STACK_EXPORT
int Binary_Value_Event_Information(
unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data);
BACNET_STACK_EXPORT
int Binary_Value_Alarm_Ack(
BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code);
BACNET_STACK_EXPORT
int Binary_Value_Alarm_Summary(
unsigned index,
BACNET_GET_ALARM_SUMMARY_DATA * getalarm_data);
BACNET_STACK_EXPORT
bool Binary_Value_Alarm_Value_Set(
uint32_t object_instance, BACNET_BINARY_PV value);
BACNET_STACK_EXPORT
void Binary_Value_Intrinsic_Reporting(
uint32_t object_instance);
#endif
#ifdef __cplusplus
}
@@ -23,6 +23,8 @@ set(ZTST_DIR "${TST_DIR}/ztest/src")
add_compile_definitions(
BIG_ENDIAN=0
CONFIG_ZTEST=1
INTRINSIC_REPORTING=1
BINARY_INPUT_INTRINSIC_REPORTING=1
)
include_directories(
@@ -64,6 +66,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/keylist.c
# Test and test library files
./src/main.c
./stubs.c
${TST_DIR}/bacnet/basic/object/property_test.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
+67
View File
@@ -0,0 +1,67 @@
/**
* @file
* @brief Stub functions for unit test of a BACnet object
* @author Steve Karg <skarg@users.sourceforge.net>
* @date December 2022
*
* SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bacnet/bacdef.h"
#include "bacnet/alarm_ack.h"
#include "bacnet/datetime.h"
#include "bacnet/event.h"
#include "bacnet/getevent.h"
#include "bacnet/get_alarm_sum.h"
#include "bacnet/npdu.h"
bool datetime_local(
BACNET_DATE *bdate,
BACNET_TIME *btime,
int16_t *utc_offset_minutes,
bool *dst_active)
{
(void)bdate;
(void)btime;
(void)utc_offset_minutes;
(void)dst_active;
return false;
}
void Notification_Class_common_reporting_function(
BACNET_EVENT_NOTIFICATION_DATA *event_data)
{
(void)event_data;
}
void Notification_Class_Get_Priorities(
uint32_t Object_Instance, uint32_t *pPriorityArray)
{
(void)Object_Instance;
(void)pPriorityArray;
}
void handler_get_event_information_set(
BACNET_OBJECT_TYPE object_type, get_event_info_function pFunction)
{
(void)object_type;
(void)pFunction;
}
void handler_alarm_ack_set(
BACNET_OBJECT_TYPE object_type, alarm_ack_function pFunction)
{
(void)object_type;
(void)pFunction;
}
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type, get_alarm_summary_function pFunction)
{
(void)object_type;
(void)pFunction;
}
@@ -23,6 +23,8 @@ set(ZTST_DIR "${TST_DIR}/ztest/src")
add_compile_definitions(
BIG_ENDIAN=0
CONFIG_ZTEST=1
INTRINSIC_REPORTING=1
BINARY_VALUE_INTRINSIC_REPORTING=1
)
include_directories(
@@ -63,6 +65,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/sys/keylist.c
# Test and test library files
./src/main.c
./stubs.c
${TST_DIR}/bacnet/basic/object/property_test.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
+67
View File
@@ -0,0 +1,67 @@
/**
* @file
* @brief Stub functions for unit test of a BACnet object
* @author Steve Karg <skarg@users.sourceforge.net>
* @date December 2022
*
* SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "bacnet/bacdef.h"
#include "bacnet/alarm_ack.h"
#include "bacnet/datetime.h"
#include "bacnet/event.h"
#include "bacnet/getevent.h"
#include "bacnet/get_alarm_sum.h"
#include "bacnet/npdu.h"
bool datetime_local(
BACNET_DATE *bdate,
BACNET_TIME *btime,
int16_t *utc_offset_minutes,
bool *dst_active)
{
(void)bdate;
(void)btime;
(void)utc_offset_minutes;
(void)dst_active;
return false;
}
void Notification_Class_common_reporting_function(
BACNET_EVENT_NOTIFICATION_DATA *event_data)
{
(void)event_data;
}
void Notification_Class_Get_Priorities(
uint32_t Object_Instance, uint32_t *pPriorityArray)
{
(void)Object_Instance;
(void)pPriorityArray;
}
void handler_get_event_information_set(
BACNET_OBJECT_TYPE object_type, get_event_info_function pFunction)
{
(void)object_type;
(void)pFunction;
}
void handler_alarm_ack_set(
BACNET_OBJECT_TYPE object_type, alarm_ack_function pFunction)
{
(void)object_type;
(void)pFunction;
}
void handler_get_alarm_summary_set(
BACNET_OBJECT_TYPE object_type, get_alarm_summary_function pFunction)
{
(void)object_type;
(void)pFunction;
}