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
+68 -16
View File
@@ -1,6 +1,7 @@
/**************************************************************************
*
* 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
* a copy of this software and associated documentation files (the
@@ -27,10 +28,13 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "config.h"
#include "txbuf.h"
#include "bacdef.h"
#include "bacdcode.h"
#include "bacerror.h"
#include "bactext.h"
#include "apdu.h"
#include "npdu.h"
#include "abort.h"
@@ -39,6 +43,17 @@
/** @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.
* @ingroup ALMACK
* This handler will be invoked by apdu_handler() if it has been enabled
@@ -48,12 +63,12 @@
* - the message is segmented
* - if decoding fails
* - Otherwise, sends a simple ACK
*
*
* @param service_request [in] The contents of the service request.
* @param service_len [in] The length of the service_request.
* @param src [in] BACNET_ADDRESS of the source of the message
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
* @param service_data [in] The BACNET_CONFIRMED_SERVICE_DATA information
* decoded from the APDU header of this message.
*/
void handler_alarm_ack(
uint8_t * service_request,
@@ -61,12 +76,14 @@ void handler_alarm_ack(
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_ALARM_ACK_DATA data;
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
int bytes_sent = 0;
int ack_result = 0;
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 */
datalink_get_my_address(&my_address);
@@ -103,25 +120,60 @@ void handler_alarm_ack(
goto AA_ABORT;
}
/*
** Process Life Safety Operation Here
*/
#if PRINT_ENABLED
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,
data.ackSource.value, (unsigned long) data.ackProcessIdentifier,
(unsigned long) data.eventObjectIdentifier.instance);
data.ackSource.value, (unsigned long) data.ackProcessIdentifier);
#endif
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM);
if (Alarm_Ack[data.eventObjectIdentifier.type]) {
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
fprintf(stderr, "Alarm Acknowledge: " "Sending Simple Ack!\n");
fprintf(stderr, "Alarm Acknowledge: " "Sending Simple Ack!\n");
#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;
bytes_sent =
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]);
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
}
}
@@ -873,10 +880,10 @@ void Analog_Input_Intrinsic_Reporting(uint32_t object_instance)
}
#if defined(INTRINSIC_REPORTING)
int Analog_Input_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data)
{
#if defined(INTRINSIC_REPORTING)
bool IsNotAckedTransitions;
bool IsActiveEvent;
int i;
@@ -934,10 +941,104 @@ int Analog_Input_Event_Information(unsigned index,
}
else
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
#include <assert.h>
+3
View File
@@ -113,6 +113,9 @@ extern "C" {
int Analog_Input_Event_Information(unsigned index,
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);
+103 -2
View File
@@ -37,6 +37,7 @@
#include "bacapp.h"
#include "bactext.h"
#include "config.h" /* the custom stuff */
#include "alarm_ack.h"
#include "getevent.h"
#include "wp.h"
#include "rp.h"
@@ -131,6 +132,13 @@ void Analog_Value_Init(
datetime_wildcard_set(&AV_Descr[i].Event_Time_Stamps[j]);
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
}
}
@@ -983,10 +991,10 @@ void Analog_Value_Intrinsic_Reporting(uint32_t object_instance)
}
#if defined(INTRINSIC_REPORTING)
int Analog_Value_Event_Information(unsigned index,
BACNET_GET_EVENT_INFORMATION_DATA * getevent_data)
{
#if defined(INTRINSIC_REPORTING)
bool IsNotAckedTransitions;
bool IsActiveEvent;
int i;
@@ -1044,9 +1052,102 @@ int Analog_Value_Event_Information(unsigned index,
}
else
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
+3
View File
@@ -100,6 +100,9 @@ extern "C" {
int Analog_Value_Event_Information(unsigned index,
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);
+3 -8
View File
@@ -127,15 +127,10 @@ static void Init_Service_Handlers(
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
handler_device_communication_control);
#if defined(INTRINSIC_REPORTING)
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
handler_alarm_ack);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_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) */
}
@@ -169,7 +164,7 @@ int main(
0
}; /* address where message came from */
uint16_t pdu_len = 0;
unsigned timeout = 1000; /* milliseconds */
unsigned timeout = 100; /* milliseconds */
time_t last_seconds = 0;
time_t current_seconds = 0;
uint32_t elapsed_seconds = 0;
+8
View File
@@ -50,6 +50,14 @@ typedef struct {
BACNET_TIMESTAMP ackTimeStamp;
} 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
extern "C" {
#endif /* __cplusplus */
+5
View File
@@ -37,6 +37,7 @@
#include "wp.h"
#include "readrange.h"
#include "getevent.h"
#include "alarm_ack.h"
#ifdef __cplusplus
@@ -250,6 +251,10 @@ extern "C" {
BACNET_ADDRESS * src,
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(
uint8_t * service_request,
uint16_t service_len,
+1
View File
@@ -75,6 +75,7 @@ HANDLER_SRC = \
$(BACNET_HANDLER)/h_rr.c \
$(BACNET_HANDLER)/h_wp.c \
$(BACNET_HANDLER)/h_wpm.c \
$(BACNET_HANDLER)/h_alarm_ack.c \
$(BACNET_HANDLER)/h_arf.c \
$(BACNET_HANDLER)/h_arf_a.c \
$(BACNET_HANDLER)/h_awf.c \