Acknowledge Alarm for Analog-Input and Analog-Value objects.

Moved initialization of handlers to GetEventInformations to specific init object.
This commit is contained in:
k001a
2011-07-21 20:44:57 +00:00
parent 52e0d00f4f
commit 8199008092
9 changed files with 297 additions and 28 deletions
+65 -13
View File
@@ -1,6 +1,7 @@
/************************************************************************** /**************************************************************************
* *
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net> * Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@@ -27,10 +28,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include "config.h" #include "config.h"
#include "txbuf.h" #include "txbuf.h"
#include "bacdef.h" #include "bacdef.h"
#include "bacdcode.h" #include "bacdcode.h"
#include "bacerror.h"
#include "bactext.h"
#include "apdu.h" #include "apdu.h"
#include "npdu.h" #include "npdu.h"
#include "abort.h" #include "abort.h"
@@ -39,6 +43,17 @@
/** @file h_alarm_ack.c Handles Alarm Acknowledgment. */ /** @file h_alarm_ack.c Handles Alarm Acknowledgment. */
static alarm_ack_function Alarm_Ack[MAX_BACNET_OBJECT_TYPE];
void handler_alarm_ack_set(
BACNET_OBJECT_TYPE object_type,
alarm_ack_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Alarm_Ack[object_type] = pFunction;
}
}
/** Handler for an Alarm/Event Acknowledgement. /** Handler for an Alarm/Event Acknowledgement.
* @ingroup ALMACK * @ingroup ALMACK
* This handler will be invoked by apdu_handler() if it has been enabled * This handler will be invoked by apdu_handler() if it has been enabled
@@ -61,12 +76,14 @@ void handler_alarm_ack(
BACNET_ADDRESS * src, BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data) BACNET_CONFIRMED_SERVICE_DATA * service_data)
{ {
BACNET_ALARM_ACK_DATA data;
int len = 0; int len = 0;
int pdu_len = 0; int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
int bytes_sent = 0; int bytes_sent = 0;
int ack_result = 0;
BACNET_ADDRESS my_address; BACNET_ADDRESS my_address;
BACNET_NPDU_DATA npdu_data;
BACNET_ALARM_ACK_DATA data;
BACNET_ERROR_CODE error_code;
/* encode the NPDU portion of the packet */ /* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address); datalink_get_my_address(&my_address);
@@ -103,25 +120,60 @@ void handler_alarm_ack(
goto AA_ABORT; goto AA_ABORT;
} }
/*
** Process Life Safety Operation Here
*/
#if PRINT_ENABLED #if PRINT_ENABLED
fprintf(stderr, fprintf(stderr,
"Alarm Ack Operation: Received acknowledge for object id %lu from %s for process id %lu for object %lu\n", "Alarm Ack Operation: Received acknowledge for object id (%d, %lu) from %s for process id %lu \n",
data.eventObjectIdentifier.type,
(unsigned long) data.eventObjectIdentifier.instance, (unsigned long) data.eventObjectIdentifier.instance,
data.ackSource.value, (unsigned long) data.ackProcessIdentifier, data.ackSource.value, (unsigned long) data.ackProcessIdentifier);
(unsigned long) data.eventObjectIdentifier.instance);
#endif #endif
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len], if (Alarm_Ack[data.eventObjectIdentifier.type]) {
service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM);
ack_result = Alarm_Ack[data.eventObjectIdentifier.type](&data, &error_code);
switch (ack_result)
{
case 1:
len = encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM);
#if PRINT_ENABLED #if PRINT_ENABLED
fprintf(stderr, "Alarm Acknowledge: " "Sending Simple Ack!\n"); fprintf(stderr, "Alarm Acknowledge: " "Sending Simple Ack!\n");
#endif #endif
break;
AA_ABORT: case -1:
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
ERROR_CLASS_OBJECT, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Alarm Acknowledge: error %s!\n",
bactext_error_code_name(error_code));
#endif
break;
default:
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr, "Alarm Acknowledge: abort other!\n");
#endif
break;
}
}
else {
len = bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
ERROR_CLASS_OBJECT, ERROR_CODE_NO_ALARM_CONFIGURED);
#if PRINT_ENABLED
fprintf(stderr, "Alarm Acknowledge: error %s!\n",
bactext_error_code_name(ERROR_CODE_NO_ALARM_CONFIGURED));
#endif
}
AA_ABORT:
pdu_len += len; pdu_len += len;
bytes_sent = bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0], datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
+103 -2
View File
@@ -122,6 +122,13 @@ void Analog_Input_Init(
datetime_wildcard_set(&AI_Descr[i].Event_Time_Stamps[j]); datetime_wildcard_set(&AI_Descr[i].Event_Time_Stamps[j]);
AI_Descr[i].Acked_Transitions[j].bIsAcked = true; AI_Descr[i].Acked_Transitions[j].bIsAcked = true;
} }
/* Set handler for GetEventInformation function */
handler_get_event_information_set(OBJECT_ANALOG_INPUT,
Analog_Input_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(OBJECT_ANALOG_INPUT,
Analog_Input_Alarm_Ack);
#endif #endif
} }
} }
@@ -873,10 +880,10 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
} }
#if defined(INTRINSIC_REPORTING)
int Analog_Input_Event_Information(unsigned index, int Analog_Input_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data) BACNET_GET_EVENT_INFORMATION_DATA * getevent_data)
{ {
#if defined(INTRINSIC_REPORTING)
bool IsNotAckedTransitions; bool IsNotAckedTransitions;
bool IsActiveEvent; bool IsActiveEvent;
int i; int i;
@@ -934,10 +941,104 @@ int Analog_Input_Event_Information(unsigned index,
} }
else else
return 0; /* no active event at this index */ return 0; /* no active event at this index */
#endif /* defined(INTRINSIC_REPORTING) */
} }
int Analog_Input_Alarm_Ack(BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code)
{
ANALOG_INPUT_DESCR *CurrentAI;
unsigned int object_index;
object_index = Analog_Input_Instance_To_Index(
alarmack_data->eventObjectIdentifier.instance);
if (object_index < MAX_ANALOG_INPUTS)
CurrentAI = &AI_Descr[object_index];
else {
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return -1;
}
switch (alarmack_data->eventStateAcked)
{
case EVENT_STATE_OFFNORMAL:
case EVENT_STATE_HIGH_LIMIT:
case EVENT_STATE_LOW_LIMIT:
if(CurrentAI->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(&CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_FAULT:
if(CurrentAI->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(&CurrentAI->Acked_Transitions[TRANSITION_TO_NORMAL].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_NORMAL:
if(CurrentAI->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(&CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAI->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
default:
return -2;
}
return 1;
}
#endif /* defined(INTRINSIC_REPORTING) */
#ifdef TEST #ifdef TEST
#include <assert.h> #include <assert.h>
+3
View File
@@ -113,6 +113,9 @@ extern "C" {
int Analog_Input_Event_Information(unsigned index, int Analog_Input_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data); BACNET_GET_EVENT_INFORMATION_DATA * getevent_data);
int Analog_Input_Alarm_Ack(BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code);
void Analog_Input_Init( void Analog_Input_Init(
void); void);
+103 -2
View File
@@ -37,6 +37,7 @@
#include "bacapp.h" #include "bacapp.h"
#include "bactext.h" #include "bactext.h"
#include "config.h" /* the custom stuff */ #include "config.h" /* the custom stuff */
#include "alarm_ack.h"
#include "getevent.h" #include "getevent.h"
#include "wp.h" #include "wp.h"
#include "rp.h" #include "rp.h"
@@ -131,6 +132,13 @@ void Analog_Value_Init(
datetime_wildcard_set(&AV_Descr[i].Event_Time_Stamps[j]); datetime_wildcard_set(&AV_Descr[i].Event_Time_Stamps[j]);
AV_Descr[i].Acked_Transitions[j].bIsAcked = true; AV_Descr[i].Acked_Transitions[j].bIsAcked = true;
} }
/* Set handler for GetEventInformation function */
handler_get_event_information_set(OBJECT_ANALOG_VALUE,
Analog_Value_Event_Information);
/* Set handler for AcknowledgeAlarm function */
handler_alarm_ack_set(OBJECT_ANALOG_VALUE,
Analog_Value_Alarm_Ack);
#endif #endif
} }
} }
@@ -983,10 +991,10 @@ void Analog_Value_Intrinsic_Reporting(uint32_t object_instance)
} }
#if defined(INTRINSIC_REPORTING)
int Analog_Value_Event_Information(unsigned index, int Analog_Value_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data) BACNET_GET_EVENT_INFORMATION_DATA * getevent_data)
{ {
#if defined(INTRINSIC_REPORTING)
bool IsNotAckedTransitions; bool IsNotAckedTransitions;
bool IsActiveEvent; bool IsActiveEvent;
int i; int i;
@@ -1044,9 +1052,102 @@ int Analog_Value_Event_Information(unsigned index,
} }
else else
return 0; /* no active event at this index */ return 0; /* no active event at this index */
#endif /* defined(INTRINSIC_REPORTING) */
} }
int Analog_Value_Alarm_Ack(BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code)
{
ANALOG_VALUE_DESCR *CurrentAV;
unsigned int object_index;
object_index = Analog_Value_Instance_To_Index(
alarmack_data->eventObjectIdentifier.instance);
if (object_index < MAX_ANALOG_VALUES)
CurrentAV = &AV_Descr[object_index];
else {
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return -1;
}
switch (alarmack_data->eventStateAcked)
{
case EVENT_STATE_OFFNORMAL:
case EVENT_STATE_HIGH_LIMIT:
case EVENT_STATE_LOW_LIMIT:
if(CurrentAV->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(&CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_FAULT:
if(CurrentAV->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(&CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
case EVENT_STATE_NORMAL:
if(CurrentAV->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(&CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].Time_Stamp,
&alarmack_data->eventTimeStamp.value.dateTime) > 0)
{
*error_code = ERROR_CODE_INVALID_TIME_STAMP;
return -1;
}
/* FIXME: Send ack notification */
CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked = true;
}
else {
*error_code = ERROR_CODE_INVALID_EVENT_STATE;
return -1;
}
break;
default:
return -2;
}
return 1;
}
#endif /* defined(INTRINSIC_REPORTING) */
#ifdef TEST #ifdef TEST
+3
View File
@@ -100,6 +100,9 @@ extern "C" {
int Analog_Value_Event_Information(unsigned index, int Analog_Value_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data); BACNET_GET_EVENT_INFORMATION_DATA * getevent_data);
int Analog_Value_Alarm_Ack(BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code);
void Analog_Value_Init( void Analog_Value_Init(
void); void);
+3 -8
View File
@@ -127,15 +127,10 @@ static void Init_Service_Handlers(
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL, apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control); handler_device_communication_control);
#if defined(INTRINSIC_REPORTING) #if defined(INTRINSIC_REPORTING)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
handler_alarm_ack);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_GET_EVENT_INFORMATION, apdu_set_confirmed_handler(SERVICE_CONFIRMED_GET_EVENT_INFORMATION,
handler_get_event_information); handler_get_event_information);
/* Set handlers for GetEventInformation
for all objects that support intrinsic reporting. */
handler_get_event_information_set(OBJECT_ANALOG_INPUT,
Analog_Input_Event_Information);
handler_get_event_information_set(OBJECT_ANALOG_VALUE,
Analog_Value_Event_Information);
#endif /* defined(INTRINSIC_REPORTING) */ #endif /* defined(INTRINSIC_REPORTING) */
} }
@@ -169,7 +164,7 @@ int main(
0 0
}; /* address where message came from */ }; /* address where message came from */
uint16_t pdu_len = 0; uint16_t pdu_len = 0;
unsigned timeout = 1000; /* milliseconds */ unsigned timeout = 100; /* milliseconds */
time_t last_seconds = 0; time_t last_seconds = 0;
time_t current_seconds = 0; time_t current_seconds = 0;
uint32_t elapsed_seconds = 0; uint32_t elapsed_seconds = 0;
+8
View File
@@ -50,6 +50,14 @@ typedef struct {
BACNET_TIMESTAMP ackTimeStamp; BACNET_TIMESTAMP ackTimeStamp;
} BACNET_ALARM_ACK_DATA; } BACNET_ALARM_ACK_DATA;
/* return +1 if alarm was acknowledged
return -1 if any error occurred
return -2 abort */
typedef int (
*alarm_ack_function) (
BACNET_ALARM_ACK_DATA * alarmack_data,
BACNET_ERROR_CODE * error_code);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
+5
View File
@@ -37,6 +37,7 @@
#include "wp.h" #include "wp.h"
#include "readrange.h" #include "readrange.h"
#include "getevent.h" #include "getevent.h"
#include "alarm_ack.h"
#ifdef __cplusplus #ifdef __cplusplus
@@ -250,6 +251,10 @@ extern "C" {
BACNET_ADDRESS * src, BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data); BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_alarm_ack_set(
BACNET_OBJECT_TYPE object_type,
alarm_ack_function pFunction);
void handler_conf_private_trans( void handler_conf_private_trans(
uint8_t * service_request, uint8_t * service_request,
uint16_t service_len, uint16_t service_len,
+1
View File
@@ -75,6 +75,7 @@ HANDLER_SRC = \
$(BACNET_HANDLER)/h_rr.c \ $(BACNET_HANDLER)/h_rr.c \
$(BACNET_HANDLER)/h_wp.c \ $(BACNET_HANDLER)/h_wp.c \
$(BACNET_HANDLER)/h_wpm.c \ $(BACNET_HANDLER)/h_wpm.c \
$(BACNET_HANDLER)/h_alarm_ack.c \
$(BACNET_HANDLER)/h_arf.c \ $(BACNET_HANDLER)/h_arf.c \
$(BACNET_HANDLER)/h_arf_a.c \ $(BACNET_HANDLER)/h_arf_a.c \
$(BACNET_HANDLER)/h_awf.c \ $(BACNET_HANDLER)/h_awf.c \