diff --git a/bacnet-stack/demo/handler/h_gas_a.c b/bacnet-stack/demo/handler/h_gas_a.c new file mode 100644 index 00000000..e170bf00 --- /dev/null +++ b/bacnet-stack/demo/handler/h_gas_a.c @@ -0,0 +1,82 @@ +/** +* @file +* @author Daniel Blazevic +* @date 2013 +* @brief GetAlarmSummary ACK service handling +* +* @section LICENSE +* +* Copyright (C) 2013 Daniel Blazevic +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +* +* @section DESCRIPTION +* +* The GetAlarmSummary ACK service handler is used by a client BACnet-user to +* obtain a summary of "active alarms." The term "active alarm" refers to +* BACnet standard objects that have an Event_State property whose value is +* not equal to NORMAL and a Notify_Type property whose value is ALARM. +*/ +#include +#include "config.h" +#include "txbuf.h" +#include "bacdef.h" +#include "bacdcode.h" +#include "bacerror.h" +#include "apdu.h" +#include "npdu.h" +#include "abort.h" +#include "handlers.h" +#include "get_alarm_sum.h" + + +/** Example function to handle a GetAlarmSummary 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. + */ +void get_alarm_summary_ack_handler( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src, + BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data) +{ + uint16_t apdu_len = 0; + uint16_t len = 0; + BACNET_GET_ALARM_SUMMARY_DATA data; + + while(service_len - len){ + apdu_len = get_alarm_summary_ack_decode_apdu_data( + &service_request[len], + service_len - len, + &data); + + len += apdu_len; + + if(apdu_len > 0){ + /* FIXME: Add code to process data */ + } else { + break; + } + } +} diff --git a/bacnet-stack/demo/handler/h_get_alarm_sum.c b/bacnet-stack/demo/handler/h_get_alarm_sum.c index db3fe68f..fc0cdf3e 100644 --- a/bacnet-stack/demo/handler/h_get_alarm_sum.c +++ b/bacnet-stack/demo/handler/h_get_alarm_sum.c @@ -101,7 +101,7 @@ void handler_get_alarm_summary( alarm_value = Get_Alarm_Summary[i] (j, &getalarm_data); if (alarm_value > 0) { len = - get_alarm_sumary_ack_encode_apdu_data + get_alarm_summary_ack_encode_apdu_data (&Handler_Transmit_Buffer[pdu_len + apdu_len], service_data->max_resp - apdu_len, &getalarm_data); if (len <= 0) { diff --git a/bacnet-stack/include/get_alarm_sum.h b/bacnet-stack/include/get_alarm_sum.h index ab3d9bf5..ba715bfd 100644 --- a/bacnet-stack/include/get_alarm_sum.h +++ b/bacnet-stack/include/get_alarm_sum.h @@ -63,7 +63,12 @@ extern "C" { uint8_t * apdu, uint8_t invoke_id); - int get_alarm_sumary_ack_encode_apdu_data( + int get_alarm_summary_ack_encode_apdu_data( + uint8_t * apdu, + size_t max_apdu, + BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data); + + int get_alarm_summary_ack_decode_apdu_data( uint8_t * apdu, size_t max_apdu, BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data); diff --git a/bacnet-stack/include/handlers.h b/bacnet-stack/include/handlers.h index e7a926d6..5ca772f5 100644 --- a/bacnet-stack/include/handlers.h +++ b/bacnet-stack/include/handlers.h @@ -300,6 +300,12 @@ extern "C" { BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data); + void get_alarm_summary_ack_handler( + uint8_t *service_request, + uint16_t service_len, + BACNET_ADDRESS *src, + BACNET_CONFIRMED_SERVICE_ACK_DATA *service_data); + #ifdef __cplusplus } diff --git a/bacnet-stack/lib/Makefile b/bacnet-stack/lib/Makefile index b2450651..e25e7610 100644 --- a/bacnet-stack/lib/Makefile +++ b/bacnet-stack/lib/Makefile @@ -90,6 +90,7 @@ HANDLER_SRC = \ $(BACNET_HANDLER)/h_ccov.c \ $(BACNET_HANDLER)/h_ucov.c \ $(BACNET_HANDLER)/h_getevent.c \ + $(BACNET_HANDLER)/h_gas_a.c \ $(BACNET_HANDLER)/h_get_alarm_sum.c \ $(BACNET_HANDLER)/h_pt.c \ $(BACNET_HANDLER)/h_pt_a.c \ diff --git a/bacnet-stack/src/get_alarm_sum.c b/bacnet-stack/src/get_alarm_sum.c index 181d830e..439d4fbf 100644 --- a/bacnet-stack/src/get_alarm_sum.c +++ b/bacnet-stack/src/get_alarm_sum.c @@ -1,4 +1,10 @@ -/************************************************************************** +/** +* @file +* @author Krzysztof Malorny +* @date 2011 +* @brief GetAlarmSummary service encoding and decoding +* +* @section LICENSE * * Copyright (C) 2011 Krzysztof Malorny * @@ -21,7 +27,15 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * -*********************************************************************/ +* @section DESCRIPTION +* +* The GetAlarmSummary service is used by a client BACnet-user +* to obtain a summary of "active alarms." The term "active alarm" refers +* to BACnet standard objects that have an Event_State property whose value +* is not equal to NORMAL and a Notify_Type property whose value is ALARM. +* The GetEnrollmentSummary service provides a more sophisticated approach +* with various kinds of filters +*/ #include #include "bacdcode.h" @@ -29,6 +43,13 @@ #include "npdu.h" +/** Helper function encode the beginning of a GetAlarmSummary ACK. + * + * @param apdu - buffer where to put encoding + * @param invoke_id - unique sequence number sent with the message + * + * @return number of bytes encoded + */ int get_alarm_summary_ack_encode_apdu_init( uint8_t * apdu, uint8_t invoke_id) @@ -45,7 +66,15 @@ int get_alarm_summary_ack_encode_apdu_init( return apdu_len; } -int get_alarm_sumary_ack_encode_apdu_data( +/** Helper function encode the data portion of a GetAlarmSummary ACK. + * + * @param apdu - buffer where to put encoding + * @param max_apdu - number of bytes available in the buffer for encoding + * @param get_alarm_data - BACNET_GET_ALARM_SUMMARY_DATA type with data + * + * @return number of bytes encoded, or BACNET_STATUS_ERROR if an error. + */ +int get_alarm_summary_ack_encode_apdu_data( uint8_t * apdu, size_t max_apdu, BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data) @@ -74,3 +103,57 @@ int get_alarm_sumary_ack_encode_apdu_data( return apdu_len; } + +/** Helper function to decode the data portion of a GetAlarmSummary ACK. + * + * @param apdu - buffer where to put encoding + * @param max_apdu - number of bytes available in the buffer for encoding + * @param get_alarm_data - BACNET_GET_ALARM_SUMMARY_DATA type for data + * + * @return number of bytes decoded, or BACNET_STATUS_ERROR if an error. + */ +int get_alarm_summary_ack_decode_apdu_data( + uint8_t * apdu, + size_t max_apdu, + BACNET_GET_ALARM_SUMMARY_DATA * get_alarm_data) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + BACNET_APPLICATION_DATA_VALUE value; + + if (!apdu) { + apdu_len = BACNET_STATUS_ERROR; + } else if (max_apdu >= 10) { + /* tag 0 - Object Identifier */ + apdu_len += + bacapp_decode_application_data(&apdu[apdu_len], + max_apdu - apdu_len, + &value); + if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { + get_alarm_data->objectIdentifier = value.type.Object_Id; + } else { + return BACNET_STATUS_ERROR; + } + /* tag 1 - Alarm State */ + apdu_len += + bacapp_decode_application_data(&apdu[apdu_len], + max_apdu - apdu_len, + &value); + if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED){ + get_alarm_data->alarmState = (BACNET_EVENT_STATE)value.type.Enumerated; + } else { + return BACNET_STATUS_ERROR; + } + /* tag 2 - Acknowledged Transitions */ + apdu_len += + bacapp_decode_application_data(&apdu[apdu_len], + max_apdu - apdu_len, + &value); + if (value.tag == BACNET_APPLICATION_TAG_BIT_STRING) { + get_alarm_data->acknowledgedTransitions = value.type.Bit_String; + } else { + return BACNET_STATUS_ERROR; + } + } + + return apdu_len; +}