diff --git a/ports/zephyr/ai.c b/ports/zephyr/ai.c deleted file mode 100644 index 61b928f1..00000000 --- a/ports/zephyr/ai.c +++ /dev/null @@ -1,1352 +0,0 @@ -/************************************************************************** - * - * Copyright (C) 2005 Steve Karg - * Copyright (C) 2011 Krzysztof Malorny - * - * 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. - * - *********************************************************************/ - -/* Analog Input Objects customize for your use */ - -#include -#include -#include - -#include "bacnet/bacdef.h" -#include "bacnet/bacdcode.h" -#include "bacnet/bacenum.h" -#include "bacnet/bactext.h" -#include "bacnet/config.h" /* the custom stuff */ -#include "bacnet/basic/object/device.h" -#include "bacnet/basic/services.h" -#include "bacnet/proplist.h" -#include "bacnet/timestamp.h" -#include "bacnet/basic/object/ai.h" - -#if PRINT_ENABLED -#include -#define PRINTF(...) fprintf(stderr,__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -#ifndef MAX_ANALOG_INPUTS -#define MAX_ANALOG_INPUTS 4 -#endif - -static ANALOG_INPUT_DESCR AI_Descr[MAX_ANALOG_INPUTS]; - -/* These three arrays are used by the ReadPropertyMultiple handler */ -static const int Properties_Required[] = { PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, - PROP_EVENT_STATE, PROP_OUT_OF_SERVICE, PROP_UNITS, -1 }; - -static const int Properties_Optional[] = { PROP_DESCRIPTION, PROP_RELIABILITY, - PROP_COV_INCREMENT, -#if defined(INTRINSIC_REPORTING) - PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS, PROP_HIGH_LIMIT, PROP_LOW_LIMIT, - PROP_DEADBAND, PROP_LIMIT_ENABLE, PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS, - PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS, -#endif - -1 }; - -static const int Properties_Proprietary[] = { 9997, 9998, 9999, -1 }; - -void Analog_Input_Property_Lists( - const int **pRequired, const int **pOptional, const int **pProprietary) -{ - if (pRequired) { - *pRequired = Properties_Required; - } - if (pOptional) { - *pOptional = Properties_Optional; - } - if (pProprietary) { - *pProprietary = Properties_Proprietary; - } - - return; -} - -void Analog_Input_Init(void) -{ - unsigned i; -#if defined(INTRINSIC_REPORTING) - unsigned j; -#endif - - for (i = 0; i < MAX_ANALOG_INPUTS; i++) { - AI_Descr[i].Present_Value = 0.0f; - AI_Descr[i].Out_Of_Service = false; - AI_Descr[i].Units = UNITS_PERCENT; - AI_Descr[i].Reliability = RELIABILITY_NO_FAULT_DETECTED; - AI_Descr[i].Prior_Value = 0.0f; - AI_Descr[i].COV_Increment = 1.0f; - AI_Descr[i].Changed = false; -#if defined(INTRINSIC_REPORTING) - AI_Descr[i].Event_State = EVENT_STATE_NORMAL; - /* notification class not connected */ - AI_Descr[i].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(&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); - /* Set handler for GetAlarmSummary Service */ - handler_get_alarm_summary_set( - OBJECT_ANALOG_INPUT, Analog_Input_Alarm_Summary); -#endif - } -} - -/* we simply have 0-n object instances. Yours might be */ -/* more complex, and then you need validate that the */ -/* given instance exists */ -bool Analog_Input_Valid_Instance(uint32_t object_instance) -{ - unsigned int index; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - return true; - } - - return false; -} - -/* we simply have 0-n object instances. Yours might be */ -/* more complex, and then count how many you have */ -unsigned Analog_Input_Count(void) -{ - return MAX_ANALOG_INPUTS; -} - -/* we simply have 0-n object instances. Yours might be */ -/* more complex, and then you need to return the instance */ -/* that correlates to the correct index */ -uint32_t Analog_Input_Index_To_Instance(unsigned index) -{ - return index; -} - -/* we simply have 0-n object instances. Yours might be */ -/* more complex, and then you need to return the index */ -/* that correlates to the correct instance number */ -unsigned Analog_Input_Instance_To_Index(uint32_t object_instance) -{ - unsigned index = MAX_ANALOG_INPUTS; - - if (object_instance < MAX_ANALOG_INPUTS) { - index = object_instance; - } - - return index; -} - -float Analog_Input_Present_Value(uint32_t object_instance) -{ - float value = 0.0; - unsigned int index; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - value = AI_Descr[index].Present_Value; - } - - return value; -} - -static void Analog_Input_COV_Detect(unsigned int index, float value) -{ - float prior_value = 0.0; - float cov_increment = 0.0; - float cov_delta = 0.0; - - if (index < MAX_ANALOG_INPUTS) { - prior_value = AI_Descr[index].Prior_Value; - cov_increment = AI_Descr[index].COV_Increment; - if (prior_value > value) { - cov_delta = prior_value - value; - } else { - cov_delta = value - prior_value; - } - if (cov_delta >= cov_increment) { - AI_Descr[index].Changed = true; - AI_Descr[index].Prior_Value = value; - } - } -} - -void Analog_Input_Present_Value_Set(uint32_t object_instance, float value) -{ - unsigned int index = 0; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - Analog_Input_COV_Detect(index, value); - AI_Descr[index].Present_Value = value; - } -} - -bool Analog_Input_Object_Name( - uint32_t object_instance, BACNET_CHARACTER_STRING *object_name) -{ - static char text_string[32] = ""; /* okay for single thread */ - unsigned int index; - bool status = false; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - sprintf(text_string, "ANALOG INPUT %lu", (unsigned long)index); - status = characterstring_init_ansi(object_name, text_string); - } - - return status; -} - -/** - * 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 Analog_Input_Event_State(uint32_t object_instance) -{ - unsigned state = EVENT_STATE_NORMAL; - -#if defined(INTRINSIC_REPORTING) - unsigned index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - state = AI_Descr[index].Event_State; - } -#endif - - return state; -} - -bool Analog_Input_Change_Of_Value(uint32_t object_instance) -{ - unsigned index = 0; - bool changed = false; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - changed = AI_Descr[index].Changed; - } - - return changed; -} - -void Analog_Input_Change_Of_Value_Clear(uint32_t object_instance) -{ - unsigned index = 0; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - AI_Descr[index].Changed = false; - } -} - -/** - * For a given object instance-number, loads the value_list with the COV data. - * - * @param object_instance - object-instance number of the object - * @param value_list - list of COV data - * - * @return true if the value list is encoded - */ -bool Analog_Input_Encode_Value_List( - uint32_t object_instance, BACNET_PROPERTY_VALUE *value_list) -{ - bool status = false; - bool in_alarm = false; - bool out_of_service = false; - const bool fault = false; - const bool overridden = false; - float present_value = 0.0; - unsigned index = 0; /* offset from instance lookup */ - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - if (AI_Descr[index].Event_State != EVENT_STATE_NORMAL) { - in_alarm = true; - } - out_of_service = AI_Descr[index].Out_Of_Service; - present_value = AI_Descr[index].Present_Value; - status = cov_value_list_encode_real(value_list, present_value, - in_alarm, fault, overridden, out_of_service); - } - - return status; -} - -float Analog_Input_COV_Increment(uint32_t object_instance) -{ - unsigned index = 0; - float value = 0; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - value = AI_Descr[index].COV_Increment; - } - - return value; -} - -void Analog_Input_COV_Increment_Set(uint32_t object_instance, float value) -{ - unsigned index = 0; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - AI_Descr[index].COV_Increment = value; - Analog_Input_COV_Detect(index, AI_Descr[index].Present_Value); - } -} - -bool Analog_Input_Out_Of_Service(uint32_t object_instance) -{ - unsigned index = 0; - bool value = false; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - value = AI_Descr[index].Out_Of_Service; - } - - return value; -} - -void Analog_Input_Out_Of_Service_Set(uint32_t object_instance, bool value) -{ - unsigned index = 0; - - index = Analog_Input_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_INPUTS) { - /* BACnet Testing Observed Incident oi00104 - The Changed flag was not being set when a client wrote to the - Out-of-Service bit. Revealed by BACnet Test Client v1.8.16 ( - www.bac-test.com/bacnet-test-client-download ) BC 135.1: 8.2.1-A BC - 135.1: 8.2.2-A Any discussions can be directed to edward@bac-test.com - Please feel free to remove this comment when my changes accepted after - suitable time for review by all interested parties. Say 6 months -> - September 2016 */ - if (AI_Descr[index].Out_Of_Service != value) { - AI_Descr[index].Changed = true; - } - AI_Descr[index].Out_Of_Service = value; - } -} - -/* return apdu length, or BACNET_STATUS_ERROR on error */ -/* assumption - object already exists */ -int Analog_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) -{ - int apdu_len = 0; /* return value */ - BACNET_BIT_STRING bit_string; - BACNET_CHARACTER_STRING char_string; - ANALOG_INPUT_DESCR *CurrentAI; - unsigned object_index = 0; -#if defined(INTRINSIC_REPORTING) - unsigned i = 0; - int len = 0; -#endif - uint8_t *apdu = NULL; - - if ((rpdata == NULL) || (rpdata->application_data == NULL) || - (rpdata->application_data_len == 0)) { - return 0; - } - - object_index = Analog_Input_Instance_To_Index(rpdata->object_instance); - if (object_index < MAX_ANALOG_INPUTS) { - CurrentAI = &AI_Descr[object_index]; - } else { - return BACNET_STATUS_ERROR; - } - - apdu = rpdata->application_data; - switch ((int)rpdata->object_property) { - case PROP_OBJECT_IDENTIFIER: - apdu_len = encode_application_object_id( - &apdu[0], OBJECT_ANALOG_INPUT, rpdata->object_instance); - break; - - case PROP_OBJECT_NAME: - case PROP_DESCRIPTION: - Analog_Input_Object_Name(rpdata->object_instance, &char_string); - apdu_len = - encode_application_character_string(&apdu[0], &char_string); - break; - - case PROP_OBJECT_TYPE: - apdu_len = - encode_application_enumerated(&apdu[0], OBJECT_ANALOG_INPUT); - break; - - case PROP_PRESENT_VALUE: - apdu_len = encode_application_real( - &apdu[0], Analog_Input_Present_Value(rpdata->object_instance)); - break; - - case PROP_STATUS_FLAGS: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, - Analog_Input_Event_State(rpdata->object_instance) != - EVENT_STATE_NORMAL); - bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); - bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); - bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, - CurrentAI->Out_Of_Service); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_EVENT_STATE: - apdu_len = - encode_application_enumerated(&apdu[0], - Analog_Input_Event_State(rpdata->object_instance)); - break; - - case PROP_RELIABILITY: - apdu_len = - encode_application_enumerated(&apdu[0], CurrentAI->Reliability); - break; - - case PROP_OUT_OF_SERVICE: - apdu_len = - encode_application_boolean(&apdu[0], CurrentAI->Out_Of_Service); - break; - - case PROP_UNITS: - apdu_len = - encode_application_enumerated(&apdu[0], CurrentAI->Units); - break; - - case PROP_COV_INCREMENT: - apdu_len = - encode_application_real(&apdu[0], CurrentAI->COV_Increment); - break; - -#if defined(INTRINSIC_REPORTING) - case PROP_TIME_DELAY: - apdu_len = - encode_application_unsigned(&apdu[0], CurrentAI->Time_Delay); - break; - - case PROP_NOTIFICATION_CLASS: - apdu_len = encode_application_unsigned( - &apdu[0], CurrentAI->Notification_Class); - break; - - case PROP_HIGH_LIMIT: - apdu_len = encode_application_real(&apdu[0], CurrentAI->High_Limit); - break; - - case PROP_LOW_LIMIT: - apdu_len = encode_application_real(&apdu[0], CurrentAI->Low_Limit); - break; - - case PROP_DEADBAND: - apdu_len = encode_application_real(&apdu[0], CurrentAI->Deadband); - break; - - case PROP_LIMIT_ENABLE: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, 0, - (CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ? true - : false); - bitstring_set_bit(&bit_string, 1, - (CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ? true - : false); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_EVENT_ENABLE: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, - (CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true - : false); - bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, - (CurrentAI->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true - : false); - bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, - (CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true - : false); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_ACKED_TRANSITIONS: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, - CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked); - bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, - CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked); - bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, - CurrentAI->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], CurrentAI->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM); - break; - - case PROP_EVENT_TIME_STAMPS: - /* Array element zero is the number of elements in the array */ - if (rpdata->array_index == 0) - apdu_len = encode_application_unsigned( - &apdu[0], MAX_BACNET_EVENT_TRANSITION); - /* if no index was specified, then try to encode the entire list */ - /* into one packet. */ - else if (rpdata->array_index == BACNET_ARRAY_ALL) { - for (i = 0; i < MAX_BACNET_EVENT_TRANSITION; i++) { - len = encode_opening_tag( - &apdu[apdu_len], TIME_STAMP_DATETIME); - len += encode_application_date(&apdu[apdu_len + len], - &CurrentAI->Event_Time_Stamps[i].date); - len += encode_application_time(&apdu[apdu_len + len], - &CurrentAI->Event_Time_Stamps[i].time); - len += encode_closing_tag( - &apdu[apdu_len + len], TIME_STAMP_DATETIME); - - /* add it if we have room */ - if ((apdu_len + len) < MAX_APDU) - apdu_len += len; - else { - rpdata->error_code = - ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; - apdu_len = BACNET_STATUS_ABORT; - break; - } - } - } else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) { - apdu_len = - encode_opening_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); - apdu_len += encode_application_date(&apdu[apdu_len], - &CurrentAI->Event_Time_Stamps[rpdata->array_index].date); - apdu_len += encode_application_time(&apdu[apdu_len], - &CurrentAI->Event_Time_Stamps[rpdata->array_index].time); - apdu_len += - encode_closing_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); - } else { - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; - apdu_len = BACNET_STATUS_ERROR; - } - break; -#endif - case 9997: - /* test case for real encoding-decoding real value correctly */ - apdu_len = encode_application_real(&apdu[0], 90.510F); - break; - case 9998: - /* test case for unsigned encoding-decoding unsigned value correctly - */ - apdu_len = encode_application_unsigned(&apdu[0], 90); - break; - case 9999: - /* test case for signed encoding-decoding negative value correctly - */ - apdu_len = encode_application_signed(&apdu[0], -200); - break; - default: - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; - apdu_len = BACNET_STATUS_ERROR; - break; - } - /* only array properties can have array options */ - if ((apdu_len >= 0) && - (rpdata->object_property != PROP_EVENT_TIME_STAMPS) && - (rpdata->array_index != BACNET_ARRAY_ALL)) { - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; - apdu_len = BACNET_STATUS_ERROR; - } - - return apdu_len; -} - -/* returns true if successful */ -bool Analog_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) -{ - bool status = false; /* return value */ - unsigned int object_index = 0; - int len = 0; - BACNET_APPLICATION_DATA_VALUE value; - ANALOG_INPUT_DESCR *CurrentAI; - - /* decode the some of the request */ - len = bacapp_decode_application_data( - wp_data->application_data, wp_data->application_data_len, &value); - /* FIXME: len < application_data_len: more data? */ - if (len < 0) { - /* error while decoding - a value larger than we can handle */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - return false; - } - /* only array properties can have array options */ - if ((wp_data->object_property != PROP_EVENT_TIME_STAMPS) && - (wp_data->array_index != BACNET_ARRAY_ALL)) { - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; - return false; - } - object_index = Analog_Input_Instance_To_Index(wp_data->object_instance); - if (object_index < MAX_ANALOG_INPUTS) { - CurrentAI = &AI_Descr[object_index]; - } else { - return false; - } - - switch ((int)wp_data->object_property) { - case PROP_PRESENT_VALUE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - if (CurrentAI->Out_Of_Service == true) { - Analog_Input_Present_Value_Set( - wp_data->object_instance, value.type.Real); - } else { - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - status = false; - } - } - break; - - case PROP_OUT_OF_SERVICE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_BOOLEAN); - if (status) { - Analog_Input_Out_Of_Service_Set( - wp_data->object_instance, value.type.Boolean); - } - break; - - case PROP_UNITS: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_ENUMERATED); - if (status) { - CurrentAI->Units = value.type.Enumerated; - } - break; - - case PROP_COV_INCREMENT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - if (value.type.Real >= 0.0) { - Analog_Input_COV_Increment_Set( - wp_data->object_instance, value.type.Real); - } else { - status = false; - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - } - } - break; - -#if defined(INTRINSIC_REPORTING) - case PROP_TIME_DELAY: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_UNSIGNED_INT); - if (status) { - CurrentAI->Time_Delay = value.type.Unsigned_Int; - CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay; - } - break; - - case PROP_NOTIFICATION_CLASS: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_UNSIGNED_INT); - if (status) { - CurrentAI->Notification_Class = value.type.Unsigned_Int; - } - break; - - case PROP_HIGH_LIMIT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAI->High_Limit = value.type.Real; - } - break; - - case PROP_LOW_LIMIT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAI->Low_Limit = value.type.Real; - } - break; - - case PROP_DEADBAND: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAI->Deadband = value.type.Real; - } - break; - - case PROP_LIMIT_ENABLE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_BIT_STRING); - if (status) { - if (value.type.Bit_String.bits_used == 2) { - CurrentAI->Limit_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_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) { - CurrentAI->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: - CurrentAI->Notify_Type = 1; - break; - case NOTIFY_ALARM: - CurrentAI->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 - case PROP_OBJECT_IDENTIFIER: - case PROP_OBJECT_NAME: - case PROP_OBJECT_TYPE: - case PROP_STATUS_FLAGS: - case PROP_EVENT_STATE: - case PROP_DESCRIPTION: - case PROP_RELIABILITY: -#if defined(INTRINSIC_REPORTING) - case PROP_ACKED_TRANSITIONS: - case PROP_EVENT_TIME_STAMPS: -#endif - case 9997: - case 9998: - case 9999: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - break; - default: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; - break; - } - - return status; -} - -void Analog_Input_Intrinsic_Reporting(uint32_t object_instance) -{ -#if defined(INTRINSIC_REPORTING) - BACNET_EVENT_NOTIFICATION_DATA event_data = { 0 }; - BACNET_CHARACTER_STRING msgText = { 0 }; - ANALOG_INPUT_DESCR *CurrentAI = NULL; - unsigned int object_index = 0; - uint8_t FromState = 0; - uint8_t ToState = 0; - float ExceededLimit = 0.0f; - float PresentVal = 0.0f; - bool SendNotify = false; - - object_index = Analog_Input_Instance_To_Index(object_instance); - if (object_index < MAX_ANALOG_INPUTS) { - CurrentAI = &AI_Descr[object_index]; - } else { - return; - } - /* check limits */ - if (!CurrentAI->Limit_Enable) { - return; /* limits are not configured */ - } - - if (CurrentAI->Ack_notify_data.bSendAckNotify) { - /* clean bSendAckNotify flag */ - CurrentAI->Ack_notify_data.bSendAckNotify = false; - /* copy toState */ - ToState = CurrentAI->Ack_notify_data.EventState; - PRINTF("Analog-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 = Analog_Input_Present_Value(object_instance); - FromState = CurrentAI->Event_State; - switch (CurrentAI->Event_State) { - case EVENT_STATE_NORMAL: - /* A TO-OFFNORMAL event is generated under these conditions: - (a) the Present_Value must exceed the High_Limit for a - minimum period of time, specified in the Time_Delay property, - and (b) the HighLimitEnable flag must be set in the - Limit_Enable property, and - (c) the TO-OFFNORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal > CurrentAI->High_Limit) && - ((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) == - EVENT_HIGH_LIMIT_ENABLE) && - ((CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) == - EVENT_ENABLE_TO_OFFNORMAL)) { - if (!CurrentAI->Remaining_Time_Delay) - CurrentAI->Event_State = EVENT_STATE_HIGH_LIMIT; - else - CurrentAI->Remaining_Time_Delay--; - break; - } - - /* A TO-OFFNORMAL event is generated under these conditions: - (a) the Present_Value must exceed the Low_Limit plus the - Deadband for a minimum period of time, specified in the - Time_Delay property, and (b) the LowLimitEnable flag must be - set in the Limit_Enable property, and - (c) the TO-NORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal < CurrentAI->Low_Limit) && - ((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) == - EVENT_LOW_LIMIT_ENABLE) && - ((CurrentAI->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) == - EVENT_ENABLE_TO_OFFNORMAL)) { - if (!CurrentAI->Remaining_Time_Delay) - CurrentAI->Event_State = EVENT_STATE_LOW_LIMIT; - else - CurrentAI->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay; - break; - - case EVENT_STATE_HIGH_LIMIT: - /* Once exceeded, the Present_Value must fall below the - High_Limit minus the Deadband before a TO-NORMAL event is - generated under these conditions: (a) the Present_Value must - fall below the High_Limit minus the Deadband for a minimum - period of time, specified in the Time_Delay property, and (b) - the HighLimitEnable flag must be set in the Limit_Enable - property, and (c) the TO-NORMAL flag must be set in the - Event_Enable property. */ - if ((PresentVal < - CurrentAI->High_Limit - CurrentAI->Deadband) && - ((CurrentAI->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) == - EVENT_HIGH_LIMIT_ENABLE) && - ((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) == - EVENT_ENABLE_TO_NORMAL)) { - if (!CurrentAI->Remaining_Time_Delay) - CurrentAI->Event_State = EVENT_STATE_NORMAL; - else - CurrentAI->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay; - break; - - case EVENT_STATE_LOW_LIMIT: - /* Once the Present_Value has fallen below the Low_Limit, - the Present_Value must exceed the Low_Limit plus the Deadband - before a TO-NORMAL event is generated under these conditions: - (a) the Present_Value must exceed the Low_Limit plus the - Deadband for a minimum period of time, specified in the - Time_Delay property, and (b) the LowLimitEnable flag must be - set in the Limit_Enable property, and - (c) the TO-NORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal > CurrentAI->Low_Limit + CurrentAI->Deadband) && - ((CurrentAI->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) == - EVENT_LOW_LIMIT_ENABLE) && - ((CurrentAI->Event_Enable & EVENT_ENABLE_TO_NORMAL) == - EVENT_ENABLE_TO_NORMAL)) { - if (!CurrentAI->Remaining_Time_Delay) - CurrentAI->Event_State = EVENT_STATE_NORMAL; - else - CurrentAI->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAI->Remaining_Time_Delay = CurrentAI->Time_Delay; - break; - - default: - return; /* shouldn't happen */ - } /* switch (FromState) */ - - ToState = CurrentAI->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_HIGH_LIMIT: - ExceededLimit = CurrentAI->High_Limit; - characterstring_init_ansi(&msgText, "Goes to high limit"); - break; - - case EVENT_STATE_LOW_LIMIT: - ExceededLimit = CurrentAI->Low_Limit; - characterstring_init_ansi(&msgText, "Goes to low limit"); - break; - - case EVENT_STATE_NORMAL: - if (FromState == EVENT_STATE_HIGH_LIMIT) { - ExceededLimit = CurrentAI->High_Limit; - characterstring_init_ansi( - &msgText, "Back to normal state from high limit"); - } else { - ExceededLimit = CurrentAI->Low_Limit; - characterstring_init_ansi( - &msgText, "Back to normal state from low limit"); - } - break; - - default: - ExceededLimit = 0; - break; - } /* switch (ToState) */ - PRINTF("Analog-Input[%d]: Event_State goes from %s to %s.\n", - object_instance, - bactext_event_state_name(FromState), - bactext_event_state_name(ToState)); - /* Notify Type */ - event_data.notifyType = CurrentAI->Notify_Type; - - /* Send EventNotification. */ - SendNotify = true; - } - } - - if (SendNotify) { - /* Event Object Identifier */ - event_data.eventObjectIdentifier.type = OBJECT_ANALOG_INPUT; - event_data.eventObjectIdentifier.instance = object_instance; - - /* Time Stamp */ - event_data.timeStamp.tag = TIME_STAMP_DATETIME; - if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) { - Device_getCurrentDateTime(&event_data.timeStamp.value.dateTime); - /* fill Event_Time_Stamps */ - switch (ToState) { - case EVENT_STATE_HIGH_LIMIT: - case EVENT_STATE_LOW_LIMIT: - datetime_copy( - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL], - &event_data.timeStamp.value.dateTime); - break; - case EVENT_STATE_FAULT: - datetime_copy( - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_FAULT], - &event_data.timeStamp.value.dateTime); - break; - case EVENT_STATE_NORMAL: - datetime_copy( - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_NORMAL], - &event_data.timeStamp.value.dateTime); - break; - default: - break; - } - } else { - /* fill event_data timeStamp */ - switch (ToState) { - case EVENT_STATE_HIGH_LIMIT: - case EVENT_STATE_LOW_LIMIT: - datetime_copy( - &event_data.timeStamp.value.dateTime, - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL]); - break; - case EVENT_STATE_FAULT: - datetime_copy( - &event_data.timeStamp.value.dateTime, - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_FAULT]); - break; - case EVENT_STATE_NORMAL: - datetime_copy( - &event_data.timeStamp.value.dateTime, - &CurrentAI->Event_Time_Stamps[TRANSITION_TO_NORMAL]); - break; - default: - break; - } - } - - /* Notification Class */ - event_data.notificationClass = CurrentAI->Notification_Class; - - /* Event Type */ - event_data.eventType = EVENT_OUT_OF_RANGE; - - /* 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 = CurrentAI->Event_State; - - /* Event Values */ - if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) { - /* Value that exceeded a limit. */ - event_data.notificationParams.outOfRange.exceedingValue = - PresentVal; - /* Status_Flags of the referenced object. */ - bitstring_init( - &event_data.notificationParams.outOfRange.statusFlags); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_IN_ALARM, - CurrentAI->Event_State != EVENT_STATE_NORMAL); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_FAULT, false); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_OVERRIDDEN, false); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_OUT_OF_SERVICE, CurrentAI->Out_Of_Service); - /* Deadband used for limit checking. */ - event_data.notificationParams.outOfRange.deadband = - CurrentAI->Deadband; - /* Limit that was exceeded. */ - event_data.notificationParams.outOfRange.exceededLimit = - ExceededLimit; - } - - /* add data from notification class */ - PRINTF("Analog-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)) { - PRINTF("Analog-Input[%d]: Ack Required!\n", object_instance); - switch (event_data.toState) { - case EVENT_STATE_OFFNORMAL: - case EVENT_STATE_HIGH_LIMIT: - case EVENT_STATE_LOW_LIMIT: - CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked = false; - CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_FAULT: - CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = - false; - CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_NORMAL: - CurrentAI->Acked_Transitions[TRANSITION_TO_NORMAL] - .bIsAcked = false; - CurrentAI->Acked_Transitions[TRANSITION_TO_NORMAL] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - default: /* shouldn't happen */ - break; - } - } - } -#endif /* defined(INTRINSIC_REPORTING) */ -} - -#if defined(INTRINSIC_REPORTING) -int Analog_Input_Event_Information( - unsigned index, BACNET_GET_EVENT_INFORMATION_DATA *getevent_data) -{ - bool IsNotAckedTransitions; - bool IsActiveEvent; - int i; - - /* check index */ - if (index < MAX_ANALOG_INPUTS) { - /* Event_State not equal to NORMAL */ - IsActiveEvent = (AI_Descr[index].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 = - (AI_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked == false) | - (AI_Descr[index].Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked == - false) | - (AI_Descr[index].Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked == - false); - } else - return -1; /* end of list */ - - if ((IsActiveEvent) || (IsNotAckedTransitions)) { - /* Object Identifier */ - getevent_data->objectIdentifier.type = OBJECT_ANALOG_INPUT; - getevent_data->objectIdentifier.instance = - Analog_Input_Index_To_Instance(index); - /* Event State */ - getevent_data->eventState = AI_Descr[index].Event_State; - /* Acknowledged Transitions */ - bitstring_init(&getevent_data->acknowledgedTransitions); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_OFFNORMAL, - AI_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_FAULT, - AI_Descr[index].Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_NORMAL, - AI_Descr[index].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 = - AI_Descr[index].Event_Time_Stamps[i]; - } - /* Notify Type */ - getevent_data->notifyType = AI_Descr[index].Notify_Type; - /* Event Enable */ - bitstring_init(&getevent_data->eventEnable); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_OFFNORMAL, - (AI_Descr[index].Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true - : false); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_FAULT, - (AI_Descr[index].Event_Enable & EVENT_ENABLE_TO_FAULT) ? true - : false); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_NORMAL, - (AI_Descr[index].Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true - : false); - /* Event Priorities */ - Notification_Class_Get_Priorities( - AI_Descr[index].Notification_Class, getevent_data->eventPriorities); - - return 1; /* active event */ - } else - return 0; /* no active event at this index */ -} - -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; - } - /* Send ack notification */ - CurrentAI->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAI->Event_State) { - /* Send ack notification */ - } else { - *error_code = ERROR_CODE_INVALID_EVENT_STATE; - return -1; - } - break; - - case EVENT_STATE_FAULT: - 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; - } - /* Send ack notification */ - CurrentAI->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAI->Event_State) { - /* Send ack notification */ - } else { - *error_code = ERROR_CODE_INVALID_EVENT_STATE; - return -1; - } - break; - - case EVENT_STATE_NORMAL: - 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; - } - /* Send ack notification */ - CurrentAI->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAI->Event_State) { - /* Send ack notification */ - } else { - *error_code = ERROR_CODE_INVALID_EVENT_STATE; - return -1; - } - break; - - default: - return -2; - } - CurrentAI->Ack_notify_data.bSendAckNotify = true; - CurrentAI->Ack_notify_data.EventState = alarmack_data->eventStateAcked; - - return 1; -} - -int Analog_Input_Alarm_Summary( - unsigned index, BACNET_GET_ALARM_SUMMARY_DATA *getalarm_data) -{ - /* check index */ - if (index < MAX_ANALOG_INPUTS) { - /* Event_State is not equal to NORMAL and - Notify_Type property value is ALARM */ - if ((AI_Descr[index].Event_State != EVENT_STATE_NORMAL) && - (AI_Descr[index].Notify_Type == NOTIFY_ALARM)) { - /* Object Identifier */ - getalarm_data->objectIdentifier.type = OBJECT_ANALOG_INPUT; - getalarm_data->objectIdentifier.instance = - Analog_Input_Index_To_Instance(index); - /* Alarm State */ - getalarm_data->alarmState = AI_Descr[index].Event_State; - /* Acknowledged Transitions */ - bitstring_init(&getalarm_data->acknowledgedTransitions); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_OFFNORMAL, - AI_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_FAULT, - AI_Descr[index] - .Acked_Transitions[TRANSITION_TO_FAULT] - .bIsAcked); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_NORMAL, - AI_Descr[index] - .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 */ -} -#endif /* defined(INTRINSIC_REPORTING) */ diff --git a/ports/zephyr/av.c b/ports/zephyr/av.c deleted file mode 100644 index edcb1e50..00000000 --- a/ports/zephyr/av.c +++ /dev/null @@ -1,1451 +0,0 @@ -/************************************************************************** - * - * Copyright (C) 2006 Steve Karg - * Copyright (C) 2011 Krzysztof Malorny - * - * 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. - * - *********************************************************************/ - -/* Analog Value Objects - customize for your use */ - -#include -#include -#include -#include - -#include "bacnet/bacdef.h" -#include "bacnet/bacdcode.h" -#include "bacnet/bacenum.h" -#include "bacnet/bacapp.h" -#include "bacnet/bactext.h" -#include "bacnet/config.h" /* the custom stuff */ -#include "bacnet/basic/object/device.h" -#include "bacnet/basic/services.h" -#include "bacnet/basic/object/av.h" - -#ifndef MAX_ANALOG_VALUES -#define MAX_ANALOG_VALUES 4 -#endif - -static ANALOG_VALUE_DESCR AV_Descr[MAX_ANALOG_VALUES]; - -/* These three arrays are used by the ReadPropertyMultiple handler */ -static const int Analog_Value_Properties_Required[] = { PROP_OBJECT_IDENTIFIER, - PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, - PROP_EVENT_STATE, PROP_OUT_OF_SERVICE, PROP_UNITS, -1 }; - -static const int Analog_Value_Properties_Optional[] = { PROP_DESCRIPTION, - PROP_COV_INCREMENT, -#if defined(INTRINSIC_REPORTING) - PROP_TIME_DELAY, PROP_NOTIFICATION_CLASS, PROP_HIGH_LIMIT, PROP_LOW_LIMIT, - PROP_DEADBAND, PROP_LIMIT_ENABLE, PROP_EVENT_ENABLE, PROP_ACKED_TRANSITIONS, - PROP_NOTIFY_TYPE, PROP_EVENT_TIME_STAMPS, -#endif - -1 }; - -static const int Analog_Value_Properties_Proprietary[] = { -1 }; - -/** - * Initialize the pointers for the required, the optional and the properitary - * value properties. - * - * @param pRequired - Pointer to the pointer of required values. - * @param pOptional - Pointer to the pointer of optional values. - * @param pProprietary - Pointer to the pointer of properitary values. - */ -void Analog_Value_Property_Lists( - const int **pRequired, const int **pOptional, const int **pProprietary) -{ - if (pRequired) { - *pRequired = Analog_Value_Properties_Required; - } - if (pOptional) { - *pOptional = Analog_Value_Properties_Optional; - } - if (pProprietary) { - *pProprietary = Analog_Value_Properties_Proprietary; - } - - return; -} - -/** - * Initialize the analog values. - */ -void Analog_Value_Init(void) -{ - unsigned i; -#if defined(INTRINSIC_REPORTING) - unsigned j; -#endif - - for (i = 0; i < MAX_ANALOG_VALUES; i++) { - memset(&AV_Descr[i], 0x00, sizeof(ANALOG_VALUE_DESCR)); - AV_Descr[i].Present_Value = 0.0; - AV_Descr[i].Units = UNITS_NO_UNITS; - AV_Descr[i].Prior_Value = 0.0f; - AV_Descr[i].COV_Increment = 1.0f; - AV_Descr[i].Changed = false; -#if defined(INTRINSIC_REPORTING) - AV_Descr[i].Event_State = EVENT_STATE_NORMAL; - /* notification class not connected */ - AV_Descr[i].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(&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); - /* Set handler for GetAlarmSummary Service */ - handler_get_alarm_summary_set( - OBJECT_ANALOG_VALUE, Analog_Value_Alarm_Summary); -#endif - } -} - -/** - * We simply have 0-n object instances. Yours might be - * more complex, and then you need validate that the - * given instance exists. - * - * @param object_instance Object instance - * - * @return true/false - */ -bool Analog_Value_Valid_Instance(uint32_t object_instance) -{ - if (object_instance < MAX_ANALOG_VALUES) { - return true; - } - - return false; -} - -/** - * Return the count of analog values. - * - * @return Count of analog values. - */ -unsigned Analog_Value_Count(void) -{ - return MAX_ANALOG_VALUES; -} - -/** - * We simply have 0-n object instances. Yours might be - * more complex, and then you need to return the instance - * that correlates to the correct index. - * - * @param index Index - * - * @return Object instance - */ -uint32_t Analog_Value_Index_To_Instance(unsigned index) -{ - return index; -} - -/** - * We simply have 0-n object instances. Yours might be - * more complex, and then you need to return the index - * that correlates to the correct instance number - * - * @param object_instance Object instance - * - * @return Index in the object table. - */ -unsigned Analog_Value_Instance_To_Index(uint32_t object_instance) -{ - unsigned index = MAX_ANALOG_VALUES; - - if (object_instance < MAX_ANALOG_VALUES) { - index = object_instance; - } - - return index; -} - -/** - * This function is used to detect a value change, - * using the new value compared against the prior - * value, using a delta as threshold. - * - * This method will update the COV-changed attribute. - * - * @param index Object index - * @param value Given present value. - */ -static void Analog_Value_COV_Detect(unsigned int index, float value) -{ - float prior_value = 0.0; - float cov_increment = 0.0; - float cov_delta = 0.0; - - if (index < MAX_ANALOG_VALUES) { - prior_value = AV_Descr[index].Prior_Value; - cov_increment = AV_Descr[index].COV_Increment; - if (prior_value > value) { - cov_delta = prior_value - value; - } else { - cov_delta = value - prior_value; - } - if (cov_delta >= cov_increment) { - AV_Descr[index].Changed = true; - AV_Descr[index].Prior_Value = value; - } - } -} - -/** - * For a given object instance-number, sets the present-value at a given - * priority 1..16. - * - * @param object_instance - object-instance number of the object - * @param value - floating point analog value - * @param priority - priority 1..16 - * - * @return true if values are within range and present-value is set. - */ -bool Analog_Value_Present_Value_Set( - uint32_t object_instance, float value, uint8_t priority) -{ - unsigned index = 0; - bool status = false; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - Analog_Value_COV_Detect(index, value); - AV_Descr[index].Present_Value = value; - status = true; - } - return status; -} - -/** - * For a given object instance-number, return the present value. - * - * @param object_instance - object-instance number of the object - * - * @return Present value - */ -float Analog_Value_Present_Value(uint32_t object_instance) -{ - float value = 0; - unsigned index = 0; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - value = AV_Descr[index].Present_Value; - } - - return value; -} - -/** - * For a given object instance-number, return the name. - * - * Note: the object name must be unique within this device - * - * @param object_instance - object-instance number of the object - * @param object_name - object name/string pointer - * - * @return true/false - */ -bool Analog_Value_Object_Name( - uint32_t object_instance, BACNET_CHARACTER_STRING *object_name) -{ - static char text_string[32] = ""; /* okay for single thread */ - bool status = false; - - if (object_instance < MAX_ANALOG_VALUES) { - sprintf( - text_string, "ANALOG VALUE %lu", (unsigned long)object_instance); - status = characterstring_init_ansi(object_name, text_string); - } - - return status; -} - -/** - * 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 Analog_Value_Event_State(uint32_t object_instance) -{ - unsigned state = EVENT_STATE_NORMAL; - -#if defined(INTRINSIC_REPORTING) - unsigned index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - state = AV_Descr[index].Event_State; - } -#endif - - return state; -} - -/** - * For a given object instance-number, determines if the COV flag - * has been triggered. - * - * @param object_instance - object-instance number of the object - * - * @return true if the COV flag is set - */ -bool Analog_Value_Change_Of_Value(uint32_t object_instance) -{ - unsigned index = 0; - bool changed = false; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - changed = AV_Descr[index].Changed; - } - - return changed; -} - -/** - * For a given object instance-number, clears the COV flag - * - * @param object_instance - object-instance number of the object - */ -void Analog_Value_Change_Of_Value_Clear(uint32_t object_instance) -{ - unsigned index = 0; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - AV_Descr[index].Changed = false; - } -} - -/** - * For a given object instance-number, loads the value_list with the COV data. - * - * @param object_instance - object-instance number of the object - * @param value_list - list of COV data - * - * @return true if the value list is encoded - */ -bool Analog_Value_Encode_Value_List( - uint32_t object_instance, BACNET_PROPERTY_VALUE *value_list) -{ - bool status = false; - - if (value_list) { - value_list->propertyIdentifier = PROP_PRESENT_VALUE; - value_list->propertyArrayIndex = BACNET_ARRAY_ALL; - value_list->value.context_specific = false; - value_list->value.tag = BACNET_APPLICATION_TAG_REAL; - value_list->value.type.Real = - Analog_Value_Present_Value(object_instance); - value_list->value.next = NULL; - value_list->priority = BACNET_NO_PRIORITY; - value_list = value_list->next; - } - if (value_list) { - value_list->propertyIdentifier = PROP_STATUS_FLAGS; - value_list->propertyArrayIndex = BACNET_ARRAY_ALL; - value_list->value.context_specific = false; - value_list->value.tag = BACNET_APPLICATION_TAG_BIT_STRING; - bitstring_init(&value_list->value.type.Bit_String); - if (Analog_Value_Event_State(object_instance) == EVENT_STATE_NORMAL) { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_IN_ALARM, false); - } else { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_IN_ALARM, true); - } - bitstring_set_bit( - &value_list->value.type.Bit_String, STATUS_FLAG_FAULT, false); - bitstring_set_bit( - &value_list->value.type.Bit_String, STATUS_FLAG_OVERRIDDEN, false); - if (Analog_Value_Out_Of_Service(object_instance)) { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_OUT_OF_SERVICE, true); - } else { - bitstring_set_bit(&value_list->value.type.Bit_String, - STATUS_FLAG_OUT_OF_SERVICE, false); - } - value_list->value.next = NULL; - value_list->priority = BACNET_NO_PRIORITY; - value_list->next = NULL; - status = true; - } - - return status; -} - -float Analog_Value_COV_Increment(uint32_t object_instance) -{ - unsigned index = 0; - float value = 0; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - value = AV_Descr[index].COV_Increment; - } - - return value; -} - -void Analog_Value_COV_Increment_Set(uint32_t object_instance, float value) -{ - unsigned index = 0; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - AV_Descr[index].COV_Increment = value; - Analog_Value_COV_Detect(index, AV_Descr[index].Present_Value); - } -} - -bool Analog_Value_Out_Of_Service(uint32_t object_instance) -{ - unsigned index = 0; - bool value = false; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - value = AV_Descr[index].Out_Of_Service; - } - - return value; -} - -void Analog_Value_Out_Of_Service_Set(uint32_t object_instance, bool value) -{ - unsigned index = 0; - - index = Analog_Value_Instance_To_Index(object_instance); - if (index < MAX_ANALOG_VALUES) { - if (AV_Descr[index].Out_Of_Service != value) { - AV_Descr[index].Changed = true; - } - AV_Descr[index].Out_Of_Service = value; - } -} - -/** - * Return the requested property of the analog value. - * - * @param rpdata Property requested, see for BACNET_READ_PROPERTY_DATA details. - * - * @return apdu len, or BACNET_STATUS_ERROR on error - */ -int Analog_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata) -{ - int apdu_len = 0; /* return value */ - BACNET_BIT_STRING bit_string; - BACNET_CHARACTER_STRING char_string; - float real_value = (float)1.414; - unsigned object_index = 0; - bool state = false; - uint8_t *apdu = NULL; - ANALOG_VALUE_DESCR *CurrentAV; -#if defined(INTRINSIC_REPORTING) - int len = 0; - unsigned i = 0; -#endif - - /* Valid data? */ - if (rpdata == NULL) { - return 0; - } - if ((rpdata->application_data == NULL) || - (rpdata->application_data_len == 0)) { - return 0; - } - - apdu = rpdata->application_data; - - object_index = Analog_Value_Instance_To_Index(rpdata->object_instance); - if (object_index >= MAX_ANALOG_VALUES) { - rpdata->error_class = ERROR_CLASS_OBJECT; - rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; - return BACNET_STATUS_ERROR; - } - - CurrentAV = &AV_Descr[object_index]; - - switch (rpdata->object_property) { - case PROP_OBJECT_IDENTIFIER: - apdu_len = encode_application_object_id( - &apdu[0], OBJECT_ANALOG_VALUE, rpdata->object_instance); - break; - - case PROP_OBJECT_NAME: - case PROP_DESCRIPTION: - if (Analog_Value_Object_Name( - rpdata->object_instance, &char_string)) { - apdu_len = - encode_application_character_string(&apdu[0], &char_string); - } - break; - - case PROP_OBJECT_TYPE: - apdu_len = - encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE); - break; - - case PROP_PRESENT_VALUE: - real_value = Analog_Value_Present_Value(rpdata->object_instance); - apdu_len = encode_application_real(&apdu[0], real_value); - break; - - case PROP_STATUS_FLAGS: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, - Analog_Value_Event_State(rpdata->object_instance) != - EVENT_STATE_NORMAL); - bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false); - bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false); - bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, - CurrentAV->Out_Of_Service); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_EVENT_STATE: -#if defined(INTRINSIC_REPORTING) - apdu_len = - encode_application_enumerated(&apdu[0], CurrentAV->Event_State); -#else - apdu_len = - encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL); -#endif - break; - - case PROP_OUT_OF_SERVICE: - state = CurrentAV->Out_Of_Service; - apdu_len = encode_application_boolean(&apdu[0], state); - break; - - case PROP_UNITS: - apdu_len = - encode_application_enumerated(&apdu[0], CurrentAV->Units); - break; - - case PROP_COV_INCREMENT: - apdu_len = - encode_application_real(&apdu[0], CurrentAV->COV_Increment); - break; - -#if defined(INTRINSIC_REPORTING) - case PROP_TIME_DELAY: - apdu_len = - encode_application_unsigned(&apdu[0], CurrentAV->Time_Delay); - break; - - case PROP_NOTIFICATION_CLASS: - apdu_len = encode_application_unsigned( - &apdu[0], CurrentAV->Notification_Class); - break; - - case PROP_HIGH_LIMIT: - apdu_len = encode_application_real(&apdu[0], CurrentAV->High_Limit); - break; - - case PROP_LOW_LIMIT: - apdu_len = encode_application_real(&apdu[0], CurrentAV->Low_Limit); - break; - - case PROP_DEADBAND: - apdu_len = encode_application_real(&apdu[0], CurrentAV->Deadband); - break; - - case PROP_LIMIT_ENABLE: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, 0, - (CurrentAV->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) ? true - : false); - bitstring_set_bit(&bit_string, 1, - (CurrentAV->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) ? true - : false); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_EVENT_ENABLE: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, - (CurrentAV->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true - : false); - bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, - (CurrentAV->Event_Enable & EVENT_ENABLE_TO_FAULT) ? true - : false); - bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, - (CurrentAV->Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true - : false); - - apdu_len = encode_application_bitstring(&apdu[0], &bit_string); - break; - - case PROP_ACKED_TRANSITIONS: - bitstring_init(&bit_string); - bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL, - CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked); - bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT, - CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked); - bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL, - CurrentAV->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], CurrentAV->Notify_Type ? NOTIFY_EVENT : NOTIFY_ALARM); - break; - - case PROP_EVENT_TIME_STAMPS: - /* Array element zero is the number of elements in the array */ - if (rpdata->array_index == 0) - apdu_len = encode_application_unsigned( - &apdu[0], MAX_BACNET_EVENT_TRANSITION); - /* if no index was specified, then try to encode the entire list */ - /* into one packet. */ - else if (rpdata->array_index == BACNET_ARRAY_ALL) { - for (i = 0; i < MAX_BACNET_EVENT_TRANSITION; i++) { - len = encode_opening_tag( - &apdu[apdu_len], TIME_STAMP_DATETIME); - len += encode_application_date(&apdu[apdu_len + len], - &CurrentAV->Event_Time_Stamps[i].date); - len += encode_application_time(&apdu[apdu_len + len], - &CurrentAV->Event_Time_Stamps[i].time); - len += encode_closing_tag( - &apdu[apdu_len + len], TIME_STAMP_DATETIME); - - /* add it if we have room */ - if ((apdu_len + len) < MAX_APDU) - apdu_len += len; - else { - rpdata->error_code = - ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED; - apdu_len = BACNET_STATUS_ABORT; - break; - } - } - } else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) { - apdu_len = - encode_opening_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); - apdu_len += encode_application_date(&apdu[apdu_len], - &CurrentAV->Event_Time_Stamps[rpdata->array_index].date); - apdu_len += encode_application_time(&apdu[apdu_len], - &CurrentAV->Event_Time_Stamps[rpdata->array_index].time); - apdu_len += - encode_closing_tag(&apdu[apdu_len], TIME_STAMP_DATETIME); - } else { - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; - apdu_len = BACNET_STATUS_ERROR; - } - break; -#endif - - default: - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; - apdu_len = BACNET_STATUS_ERROR; - break; - } - /* only array properties can have array options */ - if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) && - (rpdata->object_property != PROP_EVENT_TIME_STAMPS) && - (rpdata->array_index != BACNET_ARRAY_ALL)) { - rpdata->error_class = ERROR_CLASS_PROPERTY; - rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; - apdu_len = BACNET_STATUS_ERROR; - } - - return apdu_len; -} - -/** - * Set the requested property of the analog value. - * - * @param wp_data Property requested, see for BACNET_WRITE_PROPERTY_DATA - * details. - * - * @return true if successful - */ -bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) -{ - bool status = false; /* return value */ - unsigned int object_index = 0; - int len = 0; - BACNET_APPLICATION_DATA_VALUE value; - ANALOG_VALUE_DESCR *CurrentAV; - - /* Valid data? */ - if (wp_data == NULL) { - return false; - } - if (wp_data->application_data_len == 0) { - return false; - } - - /* decode the some of the request */ - len = bacapp_decode_application_data( - wp_data->application_data, wp_data->application_data_len, &value); - /* FIXME: len < application_data_len: more data? */ - if (len < 0) { - /* error while decoding - a value larger than we can handle */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - return false; - } - if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && - (wp_data->object_property != PROP_EVENT_TIME_STAMPS) && - (wp_data->array_index != BACNET_ARRAY_ALL)) { - /* only array properties can have array options */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; - return false; - } - - /* Valid object? */ - object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); - if (object_index >= MAX_ANALOG_VALUES) { - wp_data->error_class = ERROR_CLASS_OBJECT; - wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; - return false; - } - - CurrentAV = &AV_Descr[object_index]; - - switch (wp_data->object_property) { - case PROP_PRESENT_VALUE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - /* Command priority 6 is reserved for use by Minimum On/Off - algorithm and may not be used for other purposes in any - object. */ - if (Analog_Value_Present_Value_Set(wp_data->object_instance, - value.type.Real, wp_data->priority)) { - status = true; - } else if (wp_data->priority == 6) { - /* Command priority 6 is reserved for use by Minimum On/Off - algorithm and may not be used for other purposes in any - object. */ - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - } else { - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - } - } else { - status = false; - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - } - break; - - case PROP_OUT_OF_SERVICE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_BOOLEAN); - if (status) { - CurrentAV->Out_Of_Service = value.type.Boolean; - } - break; - - case PROP_UNITS: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_ENUMERATED); - if (status) { - CurrentAV->Units = value.type.Enumerated; - } - break; - - case PROP_COV_INCREMENT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - if (value.type.Real >= 0.0) { - Analog_Value_COV_Increment_Set( - wp_data->object_instance, value.type.Real); - } else { - status = false; - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - } - } - break; - -#if defined(INTRINSIC_REPORTING) - case PROP_TIME_DELAY: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_UNSIGNED_INT); - if (status) { - CurrentAV->Time_Delay = value.type.Unsigned_Int; - CurrentAV->Remaining_Time_Delay = CurrentAV->Time_Delay; - } - break; - - case PROP_NOTIFICATION_CLASS: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_UNSIGNED_INT); - if (status) { - CurrentAV->Notification_Class = value.type.Unsigned_Int; - } - break; - - case PROP_HIGH_LIMIT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAV->High_Limit = value.type.Real; - } - break; - - case PROP_LOW_LIMIT: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAV->Low_Limit = value.type.Real; - } - break; - - case PROP_DEADBAND: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_REAL); - if (status) { - CurrentAV->Deadband = value.type.Real; - } - break; - - case PROP_LIMIT_ENABLE: - status = write_property_type_valid(wp_data, &value, - BACNET_APPLICATION_TAG_BIT_STRING); - if (status) { - if (value.type.Bit_String.bits_used == 2) { - CurrentAV->Limit_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_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) { - CurrentAV->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: - CurrentAV->Notify_Type = 1; - break; - case NOTIFY_ALARM: - CurrentAV->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 - case PROP_OBJECT_IDENTIFIER: - case PROP_OBJECT_NAME: - case PROP_OBJECT_TYPE: - case PROP_STATUS_FLAGS: - case PROP_EVENT_STATE: - case PROP_DESCRIPTION: -#if defined(INTRINSIC_REPORTING) - case PROP_ACKED_TRANSITIONS: - case PROP_EVENT_TIME_STAMPS: -#endif - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - break; - case PROP_RELINQUISH_DEFAULT: - case PROP_PRIORITY_ARRAY: - default: - wp_data->error_class = ERROR_CLASS_PROPERTY; - wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; - break; - } - - return status; -} - -void Analog_Value_Intrinsic_Reporting(uint32_t object_instance) -{ -#if defined(INTRINSIC_REPORTING) - BACNET_EVENT_NOTIFICATION_DATA event_data; - BACNET_CHARACTER_STRING msgText; - ANALOG_VALUE_DESCR *CurrentAV; - unsigned int object_index; - uint8_t FromState = 0; - uint8_t ToState; - float ExceededLimit = 0.0f; - float PresentVal = 0.0f; - bool SendNotify = false; - - object_index = Analog_Value_Instance_To_Index(object_instance); - if (object_index < MAX_ANALOG_VALUES) - CurrentAV = &AV_Descr[object_index]; - else - return; - - /* check limits */ - if (!CurrentAV->Limit_Enable) - return; /* limits are not configured */ - - if (CurrentAV->Ack_notify_data.bSendAckNotify) { - /* clean bSendAckNotify flag */ - CurrentAV->Ack_notify_data.bSendAckNotify = false; - /* copy toState */ - ToState = CurrentAV->Ack_notify_data.EventState; - -#if PRINT_ENABLED - fprintf(stderr, "Send Acknotification for (%s,%d).\n", - bactext_object_type_name(OBJECT_ANALOG_VALUE), object_instance); -#endif /* PRINT_ENABLED */ - - characterstring_init_ansi(&msgText, "AckNotification"); - - /* Notify Type */ - event_data.notifyType = NOTIFY_ACK_NOTIFICATION; - - /* Send EventNotification. */ - SendNotify = true; - } else { - /* actual Present_Value */ - PresentVal = Analog_Value_Present_Value(object_instance); - FromState = CurrentAV->Event_State; - switch (CurrentAV->Event_State) { - case EVENT_STATE_NORMAL: - /* A TO-OFFNORMAL event is generated under these conditions: - (a) the Present_Value must exceed the High_Limit for a - minimum period of time, specified in the Time_Delay property, - and (b) the HighLimitEnable flag must be set in the - Limit_Enable property, and - (c) the TO-OFFNORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal > CurrentAV->High_Limit) && - ((CurrentAV->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) == - EVENT_HIGH_LIMIT_ENABLE) && - ((CurrentAV->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) == - EVENT_ENABLE_TO_OFFNORMAL)) { - if (!CurrentAV->Remaining_Time_Delay) - CurrentAV->Event_State = EVENT_STATE_HIGH_LIMIT; - else - CurrentAV->Remaining_Time_Delay--; - break; - } - - /* A TO-OFFNORMAL event is generated under these conditions: - (a) the Present_Value must exceed the Low_Limit plus the - Deadband for a minimum period of time, specified in the - Time_Delay property, and (b) the LowLimitEnable flag must be - set in the Limit_Enable property, and - (c) the TO-NORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal < CurrentAV->Low_Limit) && - ((CurrentAV->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) == - EVENT_LOW_LIMIT_ENABLE) && - ((CurrentAV->Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) == - EVENT_ENABLE_TO_OFFNORMAL)) { - if (!CurrentAV->Remaining_Time_Delay) - CurrentAV->Event_State = EVENT_STATE_LOW_LIMIT; - else - CurrentAV->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAV->Remaining_Time_Delay = CurrentAV->Time_Delay; - break; - - case EVENT_STATE_HIGH_LIMIT: - /* Once exceeded, the Present_Value must fall below the - High_Limit minus the Deadband before a TO-NORMAL event is - generated under these conditions: (a) the Present_Value must - fall below the High_Limit minus the Deadband for a minimum - period of time, specified in the Time_Delay property, and (b) - the HighLimitEnable flag must be set in the Limit_Enable - property, and (c) the TO-NORMAL flag must be set in the - Event_Enable property. */ - if ((PresentVal < - CurrentAV->High_Limit - CurrentAV->Deadband) && - ((CurrentAV->Limit_Enable & EVENT_HIGH_LIMIT_ENABLE) == - EVENT_HIGH_LIMIT_ENABLE) && - ((CurrentAV->Event_Enable & EVENT_ENABLE_TO_NORMAL) == - EVENT_ENABLE_TO_NORMAL)) { - if (!CurrentAV->Remaining_Time_Delay) - CurrentAV->Event_State = EVENT_STATE_NORMAL; - else - CurrentAV->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAV->Remaining_Time_Delay = CurrentAV->Time_Delay; - break; - - case EVENT_STATE_LOW_LIMIT: - /* Once the Present_Value has fallen below the Low_Limit, - the Present_Value must exceed the Low_Limit plus the Deadband - before a TO-NORMAL event is generated under these conditions: - (a) the Present_Value must exceed the Low_Limit plus the - Deadband for a minimum period of time, specified in the - Time_Delay property, and (b) the LowLimitEnable flag must be - set in the Limit_Enable property, and - (c) the TO-NORMAL flag must be set in the Event_Enable - property. */ - if ((PresentVal > CurrentAV->Low_Limit + CurrentAV->Deadband) && - ((CurrentAV->Limit_Enable & EVENT_LOW_LIMIT_ENABLE) == - EVENT_LOW_LIMIT_ENABLE) && - ((CurrentAV->Event_Enable & EVENT_ENABLE_TO_NORMAL) == - EVENT_ENABLE_TO_NORMAL)) { - if (!CurrentAV->Remaining_Time_Delay) - CurrentAV->Event_State = EVENT_STATE_NORMAL; - else - CurrentAV->Remaining_Time_Delay--; - break; - } - /* value of the object is still in the same event state */ - CurrentAV->Remaining_Time_Delay = CurrentAV->Time_Delay; - break; - - default: - return; /* shouldn't happen */ - } /* switch (FromState) */ - - ToState = CurrentAV->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_HIGH_LIMIT: - ExceededLimit = CurrentAV->High_Limit; - characterstring_init_ansi(&msgText, "Goes to high limit"); - break; - - case EVENT_STATE_LOW_LIMIT: - ExceededLimit = CurrentAV->Low_Limit; - characterstring_init_ansi(&msgText, "Goes to low limit"); - break; - - case EVENT_STATE_NORMAL: - if (FromState == EVENT_STATE_HIGH_LIMIT) { - ExceededLimit = CurrentAV->High_Limit; - characterstring_init_ansi( - &msgText, "Back to normal state from high limit"); - } else { - ExceededLimit = CurrentAV->Low_Limit; - characterstring_init_ansi( - &msgText, "Back to normal state from low limit"); - } - break; - - default: - ExceededLimit = 0; - break; - } /* switch (ToState) */ - -#if PRINT_ENABLED - fprintf(stderr, "Event_State for (%s,%d) goes from %s to %s.\n", - bactext_object_type_name(OBJECT_ANALOG_VALUE), object_instance, - bactext_event_state_name(FromState), - bactext_event_state_name(ToState)); -#endif /* PRINT_ENABLED */ - - /* Notify Type */ - event_data.notifyType = CurrentAV->Notify_Type; - - /* Send EventNotification. */ - SendNotify = true; - } - } - - if (SendNotify) { - /* Event Object Identifier */ - event_data.eventObjectIdentifier.type = OBJECT_ANALOG_VALUE; - event_data.eventObjectIdentifier.instance = object_instance; - - /* Time Stamp */ - event_data.timeStamp.tag = TIME_STAMP_DATETIME; - Device_getCurrentDateTime(&event_data.timeStamp.value.dateTime); - - if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) { - /* fill Event_Time_Stamps */ - switch (ToState) { - case EVENT_STATE_HIGH_LIMIT: - case EVENT_STATE_LOW_LIMIT: - CurrentAV->Event_Time_Stamps[TRANSITION_TO_OFFNORMAL] = - event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_FAULT: - CurrentAV->Event_Time_Stamps[TRANSITION_TO_FAULT] = - event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_NORMAL: - CurrentAV->Event_Time_Stamps[TRANSITION_TO_NORMAL] = - event_data.timeStamp.value.dateTime; - break; - } - } - - /* Notification Class */ - event_data.notificationClass = CurrentAV->Notification_Class; - - /* Event Type */ - event_data.eventType = EVENT_OUT_OF_RANGE; - - /* 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 = CurrentAV->Event_State; - - /* Event Values */ - if (event_data.notifyType != NOTIFY_ACK_NOTIFICATION) { - /* Value that exceeded a limit. */ - event_data.notificationParams.outOfRange.exceedingValue = - PresentVal; - /* Status_Flags of the referenced object. */ - bitstring_init( - &event_data.notificationParams.outOfRange.statusFlags); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_IN_ALARM, - CurrentAV->Event_State != EVENT_STATE_NORMAL); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_FAULT, false); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_OVERRIDDEN, false); - bitstring_set_bit( - &event_data.notificationParams.outOfRange.statusFlags, - STATUS_FLAG_OUT_OF_SERVICE, CurrentAV->Out_Of_Service); - /* Deadband used for limit checking. */ - event_data.notificationParams.outOfRange.deadband = - CurrentAV->Deadband; - /* Limit that was exceeded. */ - event_data.notificationParams.outOfRange.exceededLimit = - ExceededLimit; - } - - /* add data from notification class */ - Notification_Class_common_reporting_function(&event_data); - - /* Ack required */ - if ((event_data.notifyType != NOTIFY_ACK_NOTIFICATION) && - (event_data.ackRequired == true)) { - switch (event_data.toState) { - case EVENT_STATE_OFFNORMAL: - case EVENT_STATE_HIGH_LIMIT: - case EVENT_STATE_LOW_LIMIT: - CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked = false; - CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_FAULT: - CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = - false; - CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - case EVENT_STATE_NORMAL: - CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL] - .bIsAcked = false; - CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL] - .Time_Stamp = event_data.timeStamp.value.dateTime; - break; - - default: /* shouldn't happen */ - break; - } - } - } -#endif /* defined(INTRINSIC_REPORTING) */ -} - -#if defined(INTRINSIC_REPORTING) -int Analog_Value_Event_Information( - unsigned index, BACNET_GET_EVENT_INFORMATION_DATA *getevent_data) -{ - bool IsNotAckedTransitions; - bool IsActiveEvent; - int i; - - /* check index */ - if (index < MAX_ANALOG_VALUES) { - /* Event_State not equal to NORMAL */ - IsActiveEvent = (AV_Descr[index].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 = - (AV_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked == false) | - (AV_Descr[index].Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked == - false) | - (AV_Descr[index].Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked == - false); - } else - return -1; /* end of list */ - - if ((IsActiveEvent) || (IsNotAckedTransitions)) { - /* Object Identifier */ - getevent_data->objectIdentifier.type = OBJECT_ANALOG_VALUE; - getevent_data->objectIdentifier.instance = - Analog_Value_Index_To_Instance(index); - /* Event State */ - getevent_data->eventState = AV_Descr[index].Event_State; - /* Acknowledged Transitions */ - bitstring_init(&getevent_data->acknowledgedTransitions); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_OFFNORMAL, - AV_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_FAULT, - AV_Descr[index].Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked); - bitstring_set_bit(&getevent_data->acknowledgedTransitions, - TRANSITION_TO_NORMAL, - AV_Descr[index].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 = - AV_Descr[index].Event_Time_Stamps[i]; - } - /* Notify Type */ - getevent_data->notifyType = AV_Descr[index].Notify_Type; - /* Event Enable */ - bitstring_init(&getevent_data->eventEnable); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_OFFNORMAL, - (AV_Descr[index].Event_Enable & EVENT_ENABLE_TO_OFFNORMAL) ? true - : false); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_FAULT, - (AV_Descr[index].Event_Enable & EVENT_ENABLE_TO_FAULT) ? true - : false); - bitstring_set_bit(&getevent_data->eventEnable, TRANSITION_TO_NORMAL, - (AV_Descr[index].Event_Enable & EVENT_ENABLE_TO_NORMAL) ? true - : false); - /* Event Priorities */ - Notification_Class_Get_Priorities( - AV_Descr[index].Notification_Class, getevent_data->eventPriorities); - - return 1; /* active event */ - } else - return 0; /* no active event at this index */ -} - -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; - } - - /* Clean transitions flag. */ - CurrentAV->Acked_Transitions[TRANSITION_TO_OFFNORMAL].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAV->Event_State) { - /* Send ack notification */ - } 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; - } - - /* Clean transitions flag. */ - CurrentAV->Acked_Transitions[TRANSITION_TO_FAULT].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAV->Event_State) { - /* Send ack notification */ - } 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; - } - - /* Clean transitions flag. */ - CurrentAV->Acked_Transitions[TRANSITION_TO_NORMAL].bIsAcked = - true; - } else if (alarmack_data->eventStateAcked == - CurrentAV->Event_State) { - /* Send ack notification */ - } else { - *error_code = ERROR_CODE_INVALID_EVENT_STATE; - return -1; - } - break; - - default: - return -2; - } - - /* Need to send AckNotification. */ - CurrentAV->Ack_notify_data.bSendAckNotify = true; - CurrentAV->Ack_notify_data.EventState = alarmack_data->eventStateAcked; - - /* Return OK */ - return 1; -} - -int Analog_Value_Alarm_Summary( - unsigned index, BACNET_GET_ALARM_SUMMARY_DATA *getalarm_data) -{ - /* check index */ - if (index < MAX_ANALOG_VALUES) { - /* Event_State is not equal to NORMAL and - Notify_Type property value is ALARM */ - if ((AV_Descr[index].Event_State != EVENT_STATE_NORMAL) && - (AV_Descr[index].Notify_Type == NOTIFY_ALARM)) { - /* Object Identifier */ - getalarm_data->objectIdentifier.type = OBJECT_ANALOG_VALUE; - getalarm_data->objectIdentifier.instance = - Analog_Value_Index_To_Instance(index); - /* Alarm State */ - getalarm_data->alarmState = AV_Descr[index].Event_State; - /* Acknowledged Transitions */ - bitstring_init(&getalarm_data->acknowledgedTransitions); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_OFFNORMAL, - AV_Descr[index] - .Acked_Transitions[TRANSITION_TO_OFFNORMAL] - .bIsAcked); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_FAULT, - AV_Descr[index] - .Acked_Transitions[TRANSITION_TO_FAULT] - .bIsAcked); - bitstring_set_bit(&getalarm_data->acknowledgedTransitions, - TRANSITION_TO_NORMAL, - AV_Descr[index] - .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 */ -} -#endif /* defined(INTRINSIC_REPORTING) */ diff --git a/ports/zephyr/bacnet-config.h b/ports/zephyr/bacnet-config.h index d8b3b29f..c3655457 100644 --- a/ports/zephyr/bacnet-config.h +++ b/ports/zephyr/bacnet-config.h @@ -1,28 +1,14 @@ -/************************************************************************** -* -* Copyright (c) 2024 Legrand North America, LLC. -* -* 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. -* -*********************************************************************/ - +/** + * @file + * @brief Port specific configuration for BACnet Stack for Zephyr OS + * @author Steve Karg + * @date 2024 + * @section LICENSE + * + * Copyright (C) 2024 Steve Karg + * + * SPDX-License-Identifier: MIT + */ #ifndef BACNET_PORTS_ZEPHYR_BACNET_CONFIG_H #define BACNET_PORTS_ZEPHYR_BACNET_CONFIG_H @@ -30,6 +16,29 @@ #error bacnet-config.h included outside of BACNET_CONFIG_H control #endif -#include // Provides platform-specific defn of ARRAY_SIZE() +/* provides platform specific define for ARRAY_SIZE */ +#include -#endif // BACNET_PORTS_ZEPHYR_BACNET_CONFIG_H +/* some smaller defaults for microcontrollers */ +#if !defined(MAX_TSM_TRANSACTIONS) +#define MAX_TSM_TRANSACTIONS 1 +#endif +#if !defined(MAX_ADDRESS_CACHE) +#define MAX_ADDRESS_CACHE 1 +#endif +#if !defined(MAX_CHARACTER_STRING_BYTES) +#define MAX_CHARACTER_STRING_BYTES 64 +#endif +#if !defined(MAX_OCTET_STRING_BYTES) +#define MAX_OCTET_STRING_BYTES 64 +#endif + +/* K.6.6 BIBB - Network Management-BBMD Configuration-B (NM-BBMDC-B)*/ +#if !defined(MAX_BBMD_ENTRIES) +#define MAX_BBMD_ENTRIES 5 +#endif +#if !defined(MAX_FD_ENTRIES) +#define MAX_FD_ENTRIES 5 +#endif + +#endif diff --git a/ports/zephyr/bip-init.c b/ports/zephyr/bip-init.c index 3df640e7..f80955c7 100644 --- a/ports/zephyr/bip-init.c +++ b/ports/zephyr/bip-init.c @@ -71,22 +71,21 @@ static struct in_addr BIP_Broadcast_Addr; /* Used by inet_ntoa */ #if CONFIG_BACNETSTACK_LOG_LEVEL -static char ipv4_addr_str[16]={0}; +static char ipv4_addr_str[16] = { 0 }; #else -static char ipv4_addr_str[]=""; +static char ipv4_addr_str[] = ""; #endif /** -* @brief Return a string representation of an IPv4 address -* @param a - IPv4 address -* @return Pointer to global string -*/ -char* inet_ntoa(struct in_addr *a) + * @brief Return a string representation of an IPv4 address + * @param a - IPv4 address + * @return Pointer to global string + */ +char *inet_ntoa(struct in_addr *a) { if (IS_ENABLED(CONFIG_BACNETSTACK_LOG_LEVEL)) { - snprintf(ipv4_addr_str, sizeof(ipv4_addr_str), "%d.%d.%d.%d", - a->s4_addr[0],a->s4_addr[1],a->s4_addr[2],a->s4_addr[3]); + a->s4_addr[0], a->s4_addr[1], a->s4_addr[2], a->s4_addr[3]); } return &ipv4_addr_str[0]; @@ -97,14 +96,15 @@ char* inet_ntoa(struct in_addr *a) * @param str - debug info string * @param addr - IPv4 address */ -static void debug_print_ipv4(const char *str, const struct in_addr *addr, - const unsigned int port, const unsigned int count) +static void debug_print_ipv4(const char *str, + const struct in_addr *addr, + const unsigned int port, + const unsigned int count) { - LOG_DBG("%s %s:%hu (%u bytes)", log_strdup(str), log_strdup(inet_ntoa((struct in_addr*) &addr)), + LOG_DBG("%s %s:%hu (%u bytes)", str, inet_ntoa((struct in_addr *)&addr), ntohs(port), count); } - /** * @brief Set the BACnet IPv4 UDP port number * @param port - IPv4 UDP port number - in host byte order @@ -169,7 +169,6 @@ void bip_get_broadcast_address(BACNET_ADDRESS *dest) return; } - /** * Set the BACnet/IP address * @@ -257,7 +256,7 @@ uint8_t bip_get_subnet_prefix(void) if ((address | mask) == broadcast) { break; } - mask = mask<<1; + mask = mask << 1; } return prefix; @@ -290,8 +289,8 @@ int bip_send_mpdu(BACNET_IP_ADDRESS *dest, uint8_t *mtu, uint16_t mtu_len) bip_dest.sin_port = htons(dest->port); /* Send the packet */ - debug_print_ipv4("Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port, - mtu_len); + debug_print_ipv4( + "Sending MPDU->", &bip_dest.sin_addr, bip_dest.sin_port, mtu_len); return zsock_sendto(BIP_Socket, (char *)mtu, mtu_len, 0, (struct sockaddr *)&bip_dest, sizeof(struct sockaddr)); } @@ -345,19 +344,18 @@ uint16_t bip_receive( /* see if there is a packet for us */ if (zsock_select(max + 1, &read_fds, NULL, NULL, &select_timeout) > 0) { - socket = FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket : - BIP_Broadcast_Socket; - received_bytes = zsock_recvfrom(socket, (char *)&npdu[0], max_npdu, - 0, (struct sockaddr *)&sin, &sin_len); - } - else - { + socket = + FD_ISSET(BIP_Socket, &read_fds) ? BIP_Socket : BIP_Broadcast_Socket; + received_bytes = zsock_recvfrom(socket, (char *)&npdu[0], max_npdu, 0, + (struct sockaddr *)&sin, &sin_len); + } else { return 0; } /* See if there is a problem */ if (received_bytes < 0) { - LOG_WRN("%s:%d - RX zsock_recvfrom() error: %d", THIS_FILE, __LINE__, received_bytes); + LOG_WRN("%s:%d - RX zsock_recvfrom() error: %d", THIS_FILE, __LINE__, + received_bytes); return 0; } /* no problem, just no bytes */ @@ -379,16 +377,16 @@ uint16_t bip_receive( memcpy(&addr.address[0], &sin.sin_addr.s_addr, IP_ADDRESS_MAX); addr.port = ntohs(sin.sin_port); - debug_print_ipv4("Received MPDU->", &sin.sin_addr, sin.sin_port, - received_bytes); + debug_print_ipv4( + "Received MPDU->", &sin.sin_addr, sin.sin_port, received_bytes); /* pass the packet into the BBMD handler */ - offset = socket == BIP_Socket ? - bvlc_handler(&addr, src, npdu, received_bytes) : - bvlc_broadcast_handler(&addr, src, npdu, received_bytes); + offset = socket == BIP_Socket + ? bvlc_handler(&addr, src, npdu, received_bytes) + : bvlc_broadcast_handler(&addr, src, npdu, received_bytes); if (offset > 0) { npdu_len = received_bytes - offset; - debug_print_ipv4("Received NPDU->", &sin.sin_addr, sin.sin_port, - npdu_len); + debug_print_ipv4( + "Received NPDU->", &sin.sin_addr, sin.sin_port, npdu_len); if (npdu_len <= max_npdu) { /* shift the buffer to return a valid NPDU */ for (i = 0; i < npdu_len; i++) { @@ -432,81 +430,89 @@ int bip_send_pdu(BACNET_ADDRESS *dest, */ void bip_set_interface(char *ifname) { - struct net_if *interface = 0; + struct net_if *iface = 0; int index = -1; - uint8_t x=0; - - BACNET_IP_ADDRESS unicast = {0}; - BACNET_IP_ADDRESS broadcast = {0}; + uint8_t x = 0; + BACNET_IP_ADDRESS unicast = { 0 }; + BACNET_IP_ADDRESS broadcast = { 0 }; /* Network byte order */ unicast.port = BIP_Port; broadcast.port = BIP_Port; - LOG_INF("bip_set_interface()"); LOG_INF("UDP port: %d", ntohs(BIP_Port)); - if(ifname) - { + if (ifname) { index = atoi(ifname); - /* if index is zero, discern between "0" and a parse error */ - if(!index && strcmp(ifname,"0")) - { - LOG_ERR("%s:%d - Argument must parse to an integer", THIS_FILE, __LINE__); - } - else - { - interface = net_if_get_by_index(index); - if(interface) - { - LOG_INF("Using interface %d", index); - } - else - { - LOG_ERR("%s:%d - No interface at index %d", THIS_FILE, __LINE__, index); + if (!index && strcmp(ifname, "0")) { + LOG_ERR("%s:%d - Argument must parse to an integer", THIS_FILE, + __LINE__); + } else { + iface = net_if_get_by_index(index); + if (iface) { + LOG_INF("Using iface %d", index); + } else { + LOG_ERR( + "%s:%d - No iface at index %d", THIS_FILE, __LINE__, index); } } } - - if(index == -1) - { - LOG_WRN("%s:%d - No valid interface specified - using default ",THIS_FILE, __LINE__); - interface = net_if_get_default(); + if (index == -1) { + LOG_WRN("%s:%d - No valid interface specified - using default ", + THIS_FILE, __LINE__); + iface = net_if_get_default(); } + if (iface) { + LOG_INF("Interface set."); +#if defined(CONFIG_BACDL_BIP_ADDRESS_INDEX) + LOG_INF("Config unicast address %d/%d", + CONFIG_BACDL_BIP_ADDRESS_INDEX, NET_IF_MAX_IPV4_ADDR); + index = CONFIG_BACDL_BIP_ADDRESS_INDEX; +#else + int i; + char hr_addr[NET_IPV4_ADDR_LEN]; + index = 0; + for (i = 0; i < NET_IF_MAX_IPV4_ADDR; i++) { + struct net_if_addr *if_addr = &iface->config.ip.ipv4->unicast[i]; - if(interface) - { - LOG_INF("Interface set"); - - if(CONFIG_BACDL_BIP_ADDRESS_INDEX >= NET_IF_MAX_IPV4_ADDR) - { - LOG_ERR("%s:%d - IPv4 address index of %d is out of range (0-%d)",THIS_FILE, __LINE__, CONFIG_BACDL_BIP_ADDRESS_INDEX, NET_IF_MAX_IPV4_ADDR-1); + if (!if_addr->is_used) { + continue; + } + index = i; + LOG_INF("IPv4 address: %s", + net_addr_ntop(AF_INET, &if_addr->address.in_addr, hr_addr, + NET_IPV4_ADDR_LEN)); + LOG_INF("Subnet: %s", + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->netmask, hr_addr, + NET_IPV4_ADDR_LEN)); + LOG_INF("Router: %s", + net_addr_ntop(AF_INET, &iface->config.ip.ipv4->gw, hr_addr, + NET_IPV4_ADDR_LEN)); + break; + } +#endif + if (index >= NET_IF_MAX_IPV4_ADDR) { + LOG_ERR("%s:%d - IPv4 address index of %d is out of range (0-%d)", + THIS_FILE, __LINE__, index, NET_IF_MAX_IPV4_ADDR - 1); return; } - - LOG_INF("Using IPv4 address at index %d", CONFIG_BACDL_BIP_ADDRESS_INDEX); - + LOG_INF("Using IPv4 address at index %d", index); /* Build the broadcast address from the unicast and netmask */ - for(x=0; xconfig.ip.ipv4->unicast[CONFIG_BACDL_BIP_ADDRESS_INDEX].address.in_addr.s4_addr[x] | - ~interface->config.ip.ipv4->netmask.s4_addr[x]; - - unicast.address[x] = interface->config.ip.ipv4->unicast[CONFIG_BACDL_BIP_ADDRESS_INDEX].address.in_addr.s4_addr[x]; + struct net_if_addr *if_addr = &iface->config.ip.ipv4->unicast[index]; + for (x = 0; x < IP_ADDRESS_MAX; x++) { + unicast.address[x] = if_addr->address.in_addr.s4_addr[x]; + broadcast.address[x] = if_addr->address.in_addr.s4_addr[x] | + ~iface->config.ip.ipv4->netmask.s4_addr[x]; } - bip_set_addr(&unicast); bip_set_broadcast_addr(&broadcast); - - /* net_if -> net_if_config . net_if_ip . net_if_ipv4 -> net_if_addr . net_addr . in_addr . s4_addr[4] */ - LOG_INF(" Unicast: %s", log_strdup(inet_ntoa(&interface->config.ip.ipv4->unicast->address.in_addr))); - LOG_INF(" Broadcast: %s", log_strdup(inet_ntoa(&BIP_Broadcast_Addr))); - LOG_INF(" Netmask: %s", log_strdup(inet_ntoa(&interface->config.ip.ipv4->netmask)) ); - } - else - { - LOG_ERR("%s:%d - Failed to set interface", THIS_FILE, __LINE__); + LOG_INF("BACnet/IP Unicast: %u.%u.%u.%u", unicast.address[0], + unicast.address[1], unicast.address[2], unicast.address[3]); + LOG_INF("BACnet/IP Broadcast: %u.%u.%u.%u", broadcast.address[0], + broadcast.address[1], broadcast.address[2], broadcast.address[3]); + } else { + LOG_ERR("%s:%d - Failed to set iface", THIS_FILE, __LINE__); } } @@ -521,9 +527,7 @@ static int createSocket(struct sockaddr_in *sin) if (sock_fd < 0) { LOG_ERR("%s:%d - Failed to create socket", THIS_FILE, __LINE__); return sock_fd; - } - else - { + } else { LOG_DBG("Socket created"); } @@ -537,15 +541,13 @@ static int createSocket(struct sockaddr_in *sin) } /* bind the socket to the local port number and IP address */ - status = - zsock_bind(sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr)); + status = zsock_bind( + sock_fd, (const struct sockaddr *)sin, sizeof(struct sockaddr)); if (status < 0) { zsock_close(sock_fd); LOG_ERR("%s:%d - zsock_bind() failure", THIS_FILE, __LINE__); return status; - } - else - { + } else { LOG_DBG("Socket bound"); } @@ -577,7 +579,8 @@ bool bip_init(char *ifname) bip_set_interface(ifname); if (BIP_Address.s_addr == 0) { - LOG_ERR("%s:%d - Failed to get an IP address on interface: %s\n", THIS_FILE, __LINE__, log_strdup(ifname ? ifname : "[default]")); + LOG_ERR("%s:%d - Failed to get an IP address on interface: %s\n", + THIS_FILE, __LINE__, ifname ? ifname : "[default]"); return false; } diff --git a/ports/zephyr/datetime-init.c b/ports/zephyr/datetime-init.c index 0d253ab3..1882e1d7 100644 --- a/ports/zephyr/datetime-init.c +++ b/ports/zephyr/datetime-init.c @@ -12,14 +12,8 @@ #include #include #include -#if CONFIG_NATIVE_APPLICATION -#include -#elif defined(__ZEPHYR__) -#include -#else -#include -#endif #include +#include #include "bacnet/datetime.h" diff --git a/ports/zephyr/event.c b/ports/zephyr/event.c deleted file mode 100644 index f10cd373..00000000 --- a/ports/zephyr/event.c +++ /dev/null @@ -1,1138 +0,0 @@ -/*####COPYRIGHTBEGIN#### - ------------------------------------------- - Copyright (C) 2008 John Minack - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License - as published by the Free Software Foundation; either version 2 - of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to: - The Free Software Foundation, Inc. - 59 Temple Place - Suite 330 - Boston, MA 02111-1307, USA. - - As a special exception, if other files instantiate templates or - use macros or inline functions from this file, or you compile - this file and link it with other works to produce a work based - on this file, this file does not by itself cause the resulting - work to be covered by the GNU General Public License. However - the source code for this file must still be made available in - accordance with section (3) of the GNU General Public License. - - This exception does not invalidate any other reasons why a work - based on this file might be covered by the GNU General Public - License. - ------------------------------------------- -####COPYRIGHTEND####*/ -#include -#include "bacnet/event.h" -#include "bacnet/bacdcode.h" -#include "bacnet/npdu.h" -#include "bacnet/timestamp.h" -#include "bacnet/authentication_factor.h" - -/** @file event.c Encode/Decode Event Notifications */ - -int uevent_notify_encode_apdu( - uint8_t *apdu, BACNET_EVENT_NOTIFICATION_DATA *data) -{ - int len = 0; /* length of each encoding */ - int apdu_len = 0; /* total length of the apdu, return value */ - - if (apdu) { - apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST; - apdu[1] = SERVICE_UNCONFIRMED_EVENT_NOTIFICATION; /* service choice */ - apdu_len = 2; - - len += event_notify_encode_service_request(&apdu[apdu_len], data); - - if (len > 0) { - apdu_len += len; - } else { - apdu_len = 0; - } - } - - return apdu_len; -} - -int cevent_notify_encode_apdu( - uint8_t *apdu, uint8_t invoke_id, BACNET_EVENT_NOTIFICATION_DATA *data) -{ - int len = 0; /* length of each encoding */ - int apdu_len = 0; /* total length of the apdu, return value */ - - if (apdu) { - apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST; - apdu[1] = encode_max_segs_max_apdu(0, MAX_APDU); - apdu[2] = invoke_id; - apdu[3] = SERVICE_CONFIRMED_EVENT_NOTIFICATION; /* service choice */ - apdu_len = 4; - - len += event_notify_encode_service_request(&apdu[apdu_len], data); - - if (len > 0) { - apdu_len += len; - } else { - apdu_len = 0; - } - } - - return apdu_len; -} - -int event_notify_encode_service_request( - uint8_t *apdu, BACNET_EVENT_NOTIFICATION_DATA *data) -{ - int len = 0; /* length of each encoding */ - int apdu_len = 0; /* total length of the apdu, return value */ - - if (apdu) { - /* tag 0 - processIdentifier */ - len = encode_context_unsigned( - &apdu[apdu_len], 0, data->processIdentifier); - apdu_len += len; - /* tag 1 - initiatingObjectIdentifier */ - len = encode_context_object_id(&apdu[apdu_len], 1, - data->initiatingObjectIdentifier.type, - data->initiatingObjectIdentifier.instance); - apdu_len += len; - - /* tag 2 - eventObjectIdentifier */ - len = encode_context_object_id(&apdu[apdu_len], 2, - data->eventObjectIdentifier.type, - data->eventObjectIdentifier.instance); - apdu_len += len; - - /* tag 3 - timeStamp */ - - len = bacapp_encode_context_timestamp( - &apdu[apdu_len], 3, &data->timeStamp); - apdu_len += len; - - /* tag 4 - noticicationClass */ - - len = encode_context_unsigned( - &apdu[apdu_len], 4, data->notificationClass); - apdu_len += len; - - /* tag 5 - priority */ - - len = encode_context_unsigned(&apdu[apdu_len], 5, data->priority); - apdu_len += len; - - /* tag 6 - eventType */ - len = encode_context_enumerated(&apdu[apdu_len], 6, data->eventType); - apdu_len += len; - - /* tag 7 - messageText */ - if (data->messageText) { - len = encode_context_character_string( - &apdu[apdu_len], 7, data->messageText); - apdu_len += len; - } - /* tag 8 - notifyType */ - len = encode_context_enumerated(&apdu[apdu_len], 8, data->notifyType); - apdu_len += len; - - switch (data->notifyType) { - case NOTIFY_ALARM: - case NOTIFY_EVENT: - /* tag 9 - ackRequired */ - - len = encode_context_boolean( - &apdu[apdu_len], 9, data->ackRequired); - apdu_len += len; - - /* tag 10 - fromState */ - len = encode_context_enumerated( - &apdu[apdu_len], 10, data->fromState); - apdu_len += len; - break; - - default: - break; - } - - /* tag 11 - toState */ - len = encode_context_enumerated(&apdu[apdu_len], 11, data->toState); - apdu_len += len; - - switch (data->notifyType) { - case NOTIFY_ALARM: - case NOTIFY_EVENT: - /* tag 12 - event values */ - len = encode_opening_tag(&apdu[apdu_len], 12); - apdu_len += len; - - switch (data->eventType) { - case EVENT_CHANGE_OF_BITSTRING: - len = encode_opening_tag(&apdu[apdu_len], 0); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 0, - &data->notificationParams.changeOfBitstring - .referencedBitString); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.changeOfBitstring - .statusFlags); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 0); - apdu_len += len; - break; - - case EVENT_CHANGE_OF_STATE: - len = encode_opening_tag(&apdu[apdu_len], 1); - apdu_len += len; - - len = encode_opening_tag(&apdu[apdu_len], 0); - apdu_len += len; - - len = bacapp_encode_property_state(&apdu[apdu_len], - &data->notificationParams.changeOfState.newState); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 0); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.changeOfState - .statusFlags); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 1); - apdu_len += len; - break; - - case EVENT_CHANGE_OF_VALUE: - len = encode_opening_tag(&apdu[apdu_len], 2); - apdu_len += len; - - len = encode_opening_tag(&apdu[apdu_len], 0); - apdu_len += len; - - switch (data->notificationParams.changeOfValue.tag) { - case CHANGE_OF_VALUE_REAL: - len = encode_context_real(&apdu[apdu_len], 1, - data->notificationParams.changeOfValue - .newValue.changeValue); - apdu_len += len; - break; - - case CHANGE_OF_VALUE_BITS: - len = - encode_context_bitstring(&apdu[apdu_len], 0, - &data->notificationParams.changeOfValue - .newValue.changedBits); - apdu_len += len; - break; - - default: - return 0; - } - - len = encode_closing_tag(&apdu[apdu_len], 0); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.changeOfValue - .statusFlags); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 2); - apdu_len += len; - break; - - case EVENT_COMMAND_FAILURE: - - len = encode_opening_tag(&apdu[apdu_len], 3); - apdu_len += len; - - len = encode_opening_tag(&apdu[apdu_len], 0); - apdu_len += len; - - switch (data->notificationParams.commandFailure.tag) { - case COMMAND_FAILURE_BINARY_PV: - len = - encode_application_enumerated(&apdu - [apdu_len], - data->notificationParams.commandFailure. - commandValue.binaryValue); - apdu_len += len; - break; - - case COMMAND_FAILURE_UNSIGNED: - len = - encode_application_unsigned(&apdu - [apdu_len], - data->notificationParams.commandFailure. - commandValue.unsignedValue); - apdu_len += len; - break; - - default: - return 0; - } - - len = encode_closing_tag(&apdu[apdu_len], 0); - apdu_len += len; - - len = - encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.commandFailure. - statusFlags); - apdu_len += len; - - len = encode_opening_tag(&apdu[apdu_len], 2); - apdu_len += len; - - switch (data->notificationParams.commandFailure.tag) { - case COMMAND_FAILURE_BINARY_PV: - len = - encode_application_enumerated(&apdu - [apdu_len], - data->notificationParams.commandFailure. - feedbackValue.binaryValue); - apdu_len += len; - break; - - case COMMAND_FAILURE_UNSIGNED: - len = - encode_application_unsigned(&apdu - [apdu_len], - data->notificationParams.commandFailure. - feedbackValue.unsignedValue); - apdu_len += len; - break; - - default: - return 0; - } - - len = encode_closing_tag(&apdu[apdu_len], 2); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 3); - apdu_len += len; - break; - - case EVENT_FLOATING_LIMIT: - len = encode_opening_tag(&apdu[apdu_len], 4); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 0, - data->notificationParams.floatingLimit - .referenceValue); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.floatingLimit - .statusFlags); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 2, - data->notificationParams.floatingLimit - .setPointValue); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 3, - data->notificationParams.floatingLimit.errorLimit); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 4); - apdu_len += len; - break; - - case EVENT_OUT_OF_RANGE: - len = encode_opening_tag(&apdu[apdu_len], 5); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 0, - data->notificationParams.outOfRange.exceedingValue); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.outOfRange.statusFlags); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 2, - data->notificationParams.outOfRange.deadband); - apdu_len += len; - - len = encode_context_real(&apdu[apdu_len], 3, - data->notificationParams.outOfRange.exceededLimit); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 5); - apdu_len += len; - break; - - case EVENT_CHANGE_OF_LIFE_SAFETY: - len = encode_opening_tag(&apdu[apdu_len], 8); - apdu_len += len; - - len = encode_context_enumerated(&apdu[apdu_len], 0, - data->notificationParams.changeOfLifeSafety - .newState); - apdu_len += len; - - len = encode_context_enumerated(&apdu[apdu_len], 1, - data->notificationParams.changeOfLifeSafety - .newMode); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 2, - &data->notificationParams.changeOfLifeSafety - .statusFlags); - apdu_len += len; - - len = encode_context_enumerated(&apdu[apdu_len], 3, - data->notificationParams.changeOfLifeSafety - .operationExpected); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 8); - apdu_len += len; - break; - - case EVENT_BUFFER_READY: - len = encode_opening_tag(&apdu[apdu_len], 10); - apdu_len += len; - - len = bacapp_encode_context_device_obj_property_ref( - &apdu[apdu_len], 0, - &data->notificationParams.bufferReady - .bufferProperty); - apdu_len += len; - - len = encode_context_unsigned(&apdu[apdu_len], 1, - data->notificationParams.bufferReady - .previousNotification); - apdu_len += len; - - len = encode_context_unsigned(&apdu[apdu_len], 2, - data->notificationParams.bufferReady - .currentNotification); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 10); - apdu_len += len; - break; - case EVENT_UNSIGNED_RANGE: - len = encode_opening_tag(&apdu[apdu_len], 11); - apdu_len += len; - - len = encode_context_unsigned(&apdu[apdu_len], 0, - data->notificationParams.unsignedRange - .exceedingValue); - apdu_len += len; - - len = encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.unsignedRange - .statusFlags); - apdu_len += len; - - len = encode_context_unsigned(&apdu[apdu_len], 2, - data->notificationParams.unsignedRange - .exceededLimit); - apdu_len += len; - - len = encode_closing_tag(&apdu[apdu_len], 11); - apdu_len += len; - break; - case EVENT_ACCESS_EVENT: - len = encode_opening_tag(&apdu[apdu_len], 13); - apdu_len += len; - - len = - encode_context_enumerated(&apdu[apdu_len], 0, - data->notificationParams.accessEvent.accessEvent); - apdu_len += len; - - len = - encode_context_bitstring(&apdu[apdu_len], 1, - &data->notificationParams.accessEvent.statusFlags); - apdu_len += len; - - len = - encode_context_unsigned(&apdu[apdu_len], 2, - data->notificationParams. - accessEvent.accessEventTag); - apdu_len += len; - - len = - bacapp_encode_context_timestamp(&apdu[apdu_len], 3, - &data->notificationParams. - accessEvent.accessEventTime); - apdu_len += len; - - len = - bacapp_encode_context_device_obj_ref(&apdu - [apdu_len], 4, - &data->notificationParams. - accessEvent.accessCredential); - apdu_len += len; - - if (data->notificationParams. - accessEvent.authenticationFactor.format_type < - AUTHENTICATION_FACTOR_MAX) { - len = - bacapp_encode_context_authentication_factor - (&apdu[apdu_len], 5, - &data->notificationParams. - accessEvent.authenticationFactor); - apdu_len += len; - } - - len = encode_closing_tag(&apdu[apdu_len], 13); - apdu_len += len; - break; - case EVENT_EXTENDED: - default: - assert(0); - break; - } - len = encode_closing_tag(&apdu[apdu_len], 12); - apdu_len += len; - break; - case NOTIFY_ACK_NOTIFICATION: - /* FIXME: handle this case */ - default: - break; - } - } - return apdu_len; -} - -int event_notify_decode_service_request( - uint8_t *apdu, unsigned apdu_len, BACNET_EVENT_NOTIFICATION_DATA *data) -{ - int len = 0; /* return value */ - int section_length = 0; - BACNET_UNSIGNED_INTEGER unsigned_value = 0; - uint32_t enum_value = 0; - uint32_t len_value = 0; - uint8_t tag_number = 0; - - if (apdu_len && data) { - /* tag 0 - processIdentifier */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 0, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->processIdentifier = (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - /* tag 1 - initiatingObjectIdentifier */ - if ((section_length = decode_context_object_id(&apdu[len], 1, - &data->initiatingObjectIdentifier.type, - &data->initiatingObjectIdentifier.instance)) == -1) { - return -1; - } else { - len += section_length; - } - /* tag 2 - eventObjectIdentifier */ - if ((section_length = decode_context_object_id(&apdu[len], 2, - &data->eventObjectIdentifier.type, - &data->eventObjectIdentifier.instance)) == -1) { - return -1; - } else { - len += section_length; - } - /* tag 3 - timeStamp */ - if ((section_length = bacapp_decode_context_timestamp( - &apdu[len], 3, &data->timeStamp)) == -1) { - return -1; - } else { - len += section_length; - } - /* tag 4 - noticicationClass */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 4, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->notificationClass = (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - /* tag 5 - priority */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 5, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT8_MAX) { - data->priority = (uint8_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - /* tag 6 - eventType */ - if ((section_length = decode_context_enumerated( - &apdu[len], 6, &enum_value)) == -1) { - return -1; - } else { - data->eventType = (BACNET_EVENT_TYPE)enum_value; - len += section_length; - } - /* tag 7 - messageText */ - - if (decode_is_context_tag(&apdu[len], 7)) { - if (data->messageText != NULL) { - if ((section_length = decode_context_character_string( - &apdu[len], 7, data->messageText)) == -1) { - /*FIXME This is an optional parameter */ - return -1; - } else { - len += section_length; - } - } else { - return -1; - } - } else { - if (data->messageText != NULL) { - characterstring_init_ansi(data->messageText, ""); - } - } - - /* tag 8 - notifyType */ - if ((section_length = decode_context_enumerated( - &apdu[len], 8, &enum_value)) == -1) { - return -1; - } else { - data->notifyType = (BACNET_NOTIFY_TYPE)enum_value; - len += section_length; - } - switch (data->notifyType) { - case NOTIFY_ALARM: - case NOTIFY_EVENT: - /* tag 9 - ackRequired */ - section_length = - decode_context_boolean2(&apdu[len], 9, &data->ackRequired); - if (section_length == BACNET_STATUS_ERROR) { - return -1; - } - len += section_length; - - /* tag 10 - fromState */ - if ((section_length = decode_context_enumerated( - &apdu[len], 10, &enum_value)) == -1) { - return -1; - } else { - data->fromState = (BACNET_EVENT_STATE)enum_value; - len += section_length; - } - break; - /* In cases other than alarm and event - there's no data, so do not return an error - but continue normally */ - case NOTIFY_ACK_NOTIFICATION: - default: - break; - } - /* tag 11 - toState */ - if ((section_length = decode_context_enumerated( - &apdu[len], 11, &enum_value)) == -1) { - return -1; - } else { - data->toState = (BACNET_EVENT_STATE)enum_value; - len += section_length; - } - /* tag 12 - eventValues */ - switch (data->notifyType) { - case NOTIFY_ALARM: - case NOTIFY_EVENT: - if (decode_is_opening_tag_number(&apdu[len], 12)) { - len++; - } else { - return -1; - } - if (decode_is_opening_tag_number( - &apdu[len], (uint8_t)data->eventType)) { - len++; - } else { - return -1; - } - - switch (data->eventType) { - case EVENT_CHANGE_OF_BITSTRING: - if (-1 == - (section_length = decode_context_bitstring( - &apdu[len], 0, - &data->notificationParams.changeOfBitstring - .referencedBitString))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams - .changeOfBitstring.statusFlags))) { - return -1; - } - len += section_length; - - break; - - case EVENT_CHANGE_OF_STATE: - if (-1 == - (section_length = - bacapp_decode_context_property_state( - &apdu[len], 0, - &data->notificationParams.changeOfState - .newState))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.changeOfState - .statusFlags))) { - return -1; - } - len += section_length; - - break; - - case EVENT_CHANGE_OF_VALUE: - if (!decode_is_opening_tag_number(&apdu[len], 0)) { - return -1; - } - len++; - - if (decode_is_context_tag( - &apdu[len], CHANGE_OF_VALUE_BITS)) { - if (-1 == - (section_length = decode_context_bitstring( - &apdu[len], 0, - &data->notificationParams.changeOfValue - .newValue.changedBits))) { - return -1; - } - - len += section_length; - data->notificationParams.changeOfValue.tag = - CHANGE_OF_VALUE_BITS; - } else if (decode_is_context_tag( - &apdu[len], CHANGE_OF_VALUE_REAL)) { - if (-1 == - (section_length = decode_context_real( - &apdu[len], 1, - &data->notificationParams.changeOfValue - .newValue.changeValue))) { - return -1; - } - - len += section_length; - data->notificationParams.changeOfValue.tag = - CHANGE_OF_VALUE_REAL; - } else { - return -1; - } - if (!decode_is_closing_tag_number(&apdu[len], 0)) { - return -1; - } - len++; - - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.changeOfValue - .statusFlags))) { - return -1; - } - len += section_length; - break; - - case EVENT_COMMAND_FAILURE: - if (!decode_is_opening_tag_number(&apdu[len], 0)) { - return -1; - } - len++; - - if (-1 == (section_length = - decode_tag_number_and_value(&apdu[len], - &tag_number, &len_value))) { - return -1; - } - len += section_length; - - switch (tag_number) { - case BACNET_APPLICATION_TAG_ENUMERATED: - if (-1 == - (section_length = decode_enumerated( - &apdu[len], len_value, &enum_value))) { - return -1; - } - data->notificationParams.commandFailure - .commandValue.binaryValue = enum_value; - break; - - case BACNET_APPLICATION_TAG_UNSIGNED_INT: - if (-1 == (section_length = - decode_unsigned(&apdu[len], len_value, - &data-> - notificationParams.commandFailure. - commandValue.unsignedValue))) { - return -1; - } - break; - - default: - return 0; - } - len += section_length; - - if (!decode_is_closing_tag_number(&apdu[len], 0)) { - return -1; - } - len++; - - if (-1 == (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.commandFailure. - statusFlags))) { - return -1; - } - len += section_length; - - if (!decode_is_opening_tag_number(&apdu[len], 2)) { - return -1; - } - len++; - - if (-1 == (section_length = - decode_tag_number_and_value(&apdu[len], - &tag_number, &len_value))) { - return -1; - } - len += section_length; - - switch (tag_number) { - case BACNET_APPLICATION_TAG_ENUMERATED: - if (-1 == - (section_length = decode_enumerated( - &apdu[len], len_value, &enum_value))) { - return -1; - } - data->notificationParams.commandFailure - .feedbackValue.binaryValue = enum_value; - break; - - case BACNET_APPLICATION_TAG_UNSIGNED_INT: - if (-1 == (section_length = - decode_unsigned(&apdu[len], len_value, - &data-> - notificationParams.commandFailure. - feedbackValue.unsignedValue))) { - return -1; - } - break; - - default: - return 0; - } - len += section_length; - - if (!decode_is_closing_tag_number(&apdu[len], 2)) { - return -1; - } - len++; - - break; - - case EVENT_FLOATING_LIMIT: - if (-1 == - (section_length = decode_context_real(&apdu[len], 0, - &data->notificationParams.floatingLimit - .referenceValue))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.floatingLimit - .statusFlags))) { - return -1; - } - len += section_length; - if (-1 == - (section_length = decode_context_real(&apdu[len], 2, - &data->notificationParams.floatingLimit - .setPointValue))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = decode_context_real(&apdu[len], 3, - &data->notificationParams.floatingLimit - .errorLimit))) { - return -1; - } - len += section_length; - break; - - case EVENT_OUT_OF_RANGE: - if (-1 == - (section_length = decode_context_real(&apdu[len], 0, - &data->notificationParams.outOfRange - .exceedingValue))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.outOfRange - .statusFlags))) { - return -1; - } - len += section_length; - if (-1 == - (section_length = decode_context_real(&apdu[len], 2, - &data->notificationParams.outOfRange - .deadband))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = decode_context_real(&apdu[len], 3, - &data->notificationParams.outOfRange - .exceededLimit))) { - return -1; - } - len += section_length; - break; - - case EVENT_CHANGE_OF_LIFE_SAFETY: - if (-1 == - (section_length = decode_context_enumerated( - &apdu[len], 0, &enum_value))) { - return -1; - } - data->notificationParams.changeOfLifeSafety.newState = - (BACNET_LIFE_SAFETY_STATE)enum_value; - len += section_length; - - if (-1 == - (section_length = decode_context_enumerated( - &apdu[len], 1, &enum_value))) { - return -1; - } - data->notificationParams.changeOfLifeSafety.newMode = - (BACNET_LIFE_SAFETY_MODE)enum_value; - len += section_length; - - if (-1 == - (section_length = decode_context_bitstring( - &apdu[len], 2, - &data->notificationParams.changeOfLifeSafety - .statusFlags))) { - return -1; - } - len += section_length; - - if (-1 == - (section_length = decode_context_enumerated( - &apdu[len], 3, &enum_value))) { - return -1; - } - data->notificationParams.changeOfLifeSafety - .operationExpected = - (BACNET_LIFE_SAFETY_OPERATION)enum_value; - len += section_length; - break; - - case EVENT_BUFFER_READY: - /* Tag 0 - bufferProperty */ - if (-1 == - (section_length = - bacapp_decode_context_device_obj_property_ref( - &apdu[len], 0, - &data->notificationParams.bufferReady - .bufferProperty))) { - return -1; - } - len += section_length; - /* Tag 1 - PreviousNotification */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 1, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->notificationParams.bufferReady - .previousNotification = - (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - /* Tag 2 - currentNotification */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 2, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->notificationParams.bufferReady - .currentNotification = - (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - break; - - case EVENT_UNSIGNED_RANGE: - /* Tag 0 - PreviousNotification */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 0, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->notificationParams.unsignedRange - .exceedingValue = (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - /* Tag 1 - statusFlags */ - if (-1 == - (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams.unsignedRange - .statusFlags))) { - return -1; - } - len += section_length; - /* Tag 2 - exceededLimit */ - section_length = bacnet_unsigned_context_decode( - &apdu[len], apdu_len - len, 2, &unsigned_value); - if (section_length > 0) { - len += section_length; - if (unsigned_value <= UINT32_MAX) { - data->notificationParams.unsignedRange - .exceededLimit = (uint32_t)unsigned_value; - } else { - return BACNET_STATUS_ERROR; - } - } else { - return BACNET_STATUS_ERROR; - } - break; - - case EVENT_ACCESS_EVENT: - if (-1 == - (section_length = decode_context_enumerated( - &apdu[len], 0, &enum_value))) { - return -1; - } - data->notificationParams.accessEvent.accessEvent = - enum_value; - len += section_length; - - if (-1 == (section_length = - decode_context_bitstring(&apdu[len], 1, - &data->notificationParams. - accessEvent.statusFlags))) { - return -1; - } - len += section_length; - - if (-1 == (section_length = - decode_context_unsigned(&apdu[len], 2, - &data->notificationParams. - accessEvent.accessEventTag))) { - return -1; - } - len += section_length; - - if (-1 == (section_length = - bacapp_decode_context_timestamp(&apdu[len], 3, - &data->notificationParams. - accessEvent.accessEventTime))) { - return -1; - } - len += section_length; - - if (-1 == (section_length = - bacapp_decode_context_device_obj_ref(&apdu - [len], 4, - &data->notificationParams. - accessEvent.accessCredential))) { - return -1; - } - len += section_length; - - if (!decode_is_closing_tag(&apdu[len])) { - if (-1 == (section_length = - bacapp_decode_context_authentication_factor - (&apdu[len], 5, - &data->notificationParams. - accessEvent.authenticationFactor))) { - return -1; - } - len += section_length; - } - break; - - default: - return -1; - } - if (decode_is_closing_tag_number( - &apdu[len], (uint8_t)data->eventType)) { - len++; - } else { - return -1; - } - if (decode_is_closing_tag_number(&apdu[len], 12)) { - len++; - } else { - return -1; - } - break; - /* In cases other than alarm and event - there's no data, so do not return an error - but continue normally */ - case NOTIFY_ACK_NOTIFICATION: - default: - break; - } - } - - return len; -} diff --git a/src/bacnet/config.h b/src/bacnet/config.h index 469f06b7..ab3e73ba 100644 --- a/src/bacnet/config.h +++ b/src/bacnet/config.h @@ -1,27 +1,14 @@ -/************************************************************************** -* -* Copyright (C) 2004 Steve Karg -* -* 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. -* -*********************************************************************/ +/** + * @file + * @brief Default configuration for BACnet Stack library + * @author Steve Karg + * @date 2004 + * @section LICENSE + * + * Copyright (C) 2004 Steve Karg + * + * SPDX-License-Identifier: MIT + */ #ifndef CONFIG_H #define CONFIG_H diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 6e346abb..42bb4906 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -332,43 +332,43 @@ set(BACNETSTACK_BASIC_SRCS $<$:${BACNETSTACK_SRC}/bacnet/basic/bbmd6/h_bbmd6.c> $<$:${BACNETSTACK_SRC}/bacnet/basic/bbmd6/vmac.c> ${BACNETSTACK_SRC}/bacnet/basic/npdu/s_router.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_credential.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_door.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_point.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_rights.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_user.c - ${BACNETSTACK_SRC}/bacnet/basic/object/access_zone.c - ${BACNETSTACK_SRC}/bacnet/basic/object/acc.c - ${BACNETSTACK_SRC}/bacnet/basic/object/ao.c - ${BACNETSTACK_SRC}/bacnet/basic/object/bacfile.c - ${BACNETSTACK_SRC}/bacnet/basic/object/bi.c - ${BACNETSTACK_SRC}/bacnet/basic/object/bo.c - ${BACNETSTACK_SRC}/bacnet/basic/object/bv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/calendar.c - ${BACNETSTACK_SRC}/bacnet/basic/object/channel.c - #${BACNETSTACK_SRC}/bacnet/basic/object/client/device-client.c - ${BACNETSTACK_SRC}/bacnet/basic/object/command.c - ${BACNETSTACK_SRC}/bacnet/basic/object/color_object.c - ${BACNETSTACK_SRC}/bacnet/basic/object/color_temperature.c - ${BACNETSTACK_SRC}/bacnet/basic/object/credential_data_input.c - ${BACNETSTACK_SRC}/bacnet/basic/object/csv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/device.c + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_credential.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_door.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_point.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_rights.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_user.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/access_zone.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/acc.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/ao.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/bacfile.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/bi.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/bo.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/bv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/calendar.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/channel.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/command.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/color_object.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/color_temperature.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/credential_data_input.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/csv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/client/device-client.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/device.c> $<$:${BACNETSTACK_SRC}/bacnet/basic/object/gateway/gw_device.c> - ${BACNETSTACK_SRC}/bacnet/basic/object/iv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/lc.c - ${BACNETSTACK_SRC}/bacnet/basic/object/lo.c - ${BACNETSTACK_SRC}/bacnet/basic/object/lsp.c - ${BACNETSTACK_SRC}/bacnet/basic/object/ms-input.c - ${BACNETSTACK_SRC}/bacnet/basic/object/mso.c - ${BACNETSTACK_SRC}/bacnet/basic/object/msv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/nc.c - $<$:${BACNETSTACK_SRC}/bacnet/basic/object/netport.c> - ${BACNETSTACK_SRC}/bacnet/basic/object/objects.c - ${BACNETSTACK_SRC}/bacnet/basic/object/osv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/piv.c - ${BACNETSTACK_SRC}/bacnet/basic/object/schedule.c - ${BACNETSTACK_SRC}/bacnet/basic/object/time_value.c - ${BACNETSTACK_SRC}/bacnet/basic/object/trendlog.c + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/iv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/lc.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/lo.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/lsp.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/ms-input.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/mso.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/msv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/nc.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/netport.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/objects.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/osv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/piv.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/schedule.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/time_value.c> + $<$:${BACNETSTACK_SRC}/bacnet/basic/object/trendlog.c> ${BACNETSTACK_SRC}/bacnet/basic/service/h_alarm_ack.c ${BACNETSTACK_SRC}/bacnet/basic/service/h_arf_a.c ${BACNETSTACK_SRC}/bacnet/basic/service/h_arf.c @@ -428,9 +428,6 @@ list( $<$:${BACNETSTACK_PORT}/ethernet.c> ${BACNETSTACK_PORT}/main.c ${BACNETSTACK_PORT}/mstimer-init.c - ${BACNETSTACK_PORT}/ai.c - ${BACNETSTACK_PORT}/av.c - ${BACNETSTACK_PORT}/event.c ) @@ -450,6 +447,7 @@ zephyr_library_compile_definitions( $<$:BACDL_MSTP> $<$:BACDL_ETHERNET> $<$:BACDL_NONE> + $<$:BACNET_BASIC_OBJECTS> $<$:BACNET_PROPERTY_LISTS=1> $<$:BACNET_ROUTING> $<$:BACAPP_PRINT_ENABLED=1> diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 173aac49..93d28fac 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -112,6 +112,192 @@ config BACNET_USE_SECTION_ITERABLE_OBJECT_TABLE help Use the Section Iterable for the Object Table +config BACNET_BASIC_OBJECTS_ACCESS + bool "Use the BACnet basic access control objects" + default false + help + Use the BACnet basic access control objects + +config BACNET_BASIC_OBJECT_ACCUMULATOR + bool "Use the BACnet basic accumulator object" + default false + help + Use the BACnet basic accumulator object + +config BACNET_BASIC_OBJECT_ANALOG_INPUT + bool "Use the BACnet basic analog input object" + default false + help + Use the BACnet basic analog input object + +config BACNET_BASIC_OBJECT_ANALOG_OUTPUT + bool "Use the BACnet basic analog output object" + default false + help + Use the BACnet basic analog output object + +config BACNET_BASIC_OBJECT_ANALOG_VALUE + bool "Use the BACnet basic analog value object" + default false + help + Use the BACnet basic analog value object + +config BACNET_BASIC_OBJECT_FILE + bool "Use the BACnet basic file object" + default false + help + Use the BACnet basic file object + +config BACNET_BASIC_OBJECT_BINARY_INPUT + bool "Use the BACnet basic binary input object" + default false + help + Use the BACnet basic binary input object + +config BACNET_BASIC_OBJECT_BINARY_OUTPUT + bool "Use the BACnet basic binary output object" + default false + help + Use the BACnet basic binary output object + +config BACNET_BASIC_OBJECT_BINARY_VALUE + bool "Use the BACnet basic binary value object" + default false + help + Use the BACnet basic binary value object + +config BACNET_BASIC_OBJECT_CALENDAR + bool "Use the BACnet basic calendar object" + default false + help + Use the BACnet basic calendar object + +config BACNET_BASIC_OBJECT_CHANNEL + bool "Use the BACnet basic channel object" + default false + help + Use the BACnet basic channel object + +config BACNET_BASIC_OBJECT_COMMAND + bool "Use the BACnet basic command object" + default false + help + Use the BACnet basic command object + +config BACNET_BASIC_OBJECT_COLOR + bool "Use the BACnet basic color object" + default false + help + Use the BACnet basic color object + +config BACNET_BASIC_OBJECT_COLOR_TEMPERATURE + bool "Use the BACnet basic color temperature object" + default false + help + Use the BACnet basic color temperature object + +config BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE + bool "Use the BACnet basic character-string value object" + default false + help + Use the BACnet basic character-string value object + +config BACNET_BASIC_OBJECT_DEVICE_SERVER + bool "Use the BACnet basic device-server object" + default false + help + Use the BACnet basic device-server object + +config BACNET_BASIC_OBJECT_DEVICE_CLIENT + bool "Use the BACnet basic device-client object" + default false + help + Use the BACnet basic device-server object + +config BACNET_BASIC_OBJECT_INTEGER_VALUE + bool "Use the BACnet basic integer value object" + default false + help + Use the BACnet basic integer value object + +config BACNET_BASIC_OBJECT_LOAD_CONTROL + bool "Use the BACnet basic load control object" + default false + help + Use the BACnet basic load control object + +config BACNET_BASIC_OBJECT_LIGHTING_OUTPUT + bool "Use the BACnet basic lighting output object" + default false + help + Use the BACnet basic lighting output object + +config BACNET_BASIC_OBJECT_LIFE_SAFETY_POINT + bool "Use the BACnet basic life-safety point object" + default false + help + Use the BACnet basic life-safety point object + +config BACNET_BASIC_OBJECT_MULTISTATE_INPUT + bool "Use the BACnet basic multistate input object" + default false + help + Use the BACnet basic multistate input object + +config BACNET_BASIC_OBJECT_MULTISTATE_OUTPUT + bool "Use the BACnet basic multistate output object" + default false + help + Use the BACnet basic multistate output object + +config BACNET_BASIC_OBJECT_MULTISTATE_VALUE + bool "Use the BACnet basic multistate value object" + default false + help + Use the BACnet basic multistate value object + +config BACNET_BASIC_OBJECT_NOTIFICATION_CLASS + bool "Use the BACnet basic notification class object" + default false + help + Use the BACnet basic notification class object + +config BACNET_BASIC_OBJECT_NETWORK_PORT + bool "Use the BACnet basic network port object" + default false + help + Use the BACnet basic network port object + +config BACNET_BASIC_OBJECT_OCTET_STRING_VALUE + bool "Use the BACnet basic octet-string value object" + default false + help + Use the BACnet basic octet-string value object + +config BACNET_BASIC_OBJECT_POSITIVE_INTEGER_VALUE + bool "Use the BACnet basic positive-integer value object" + default false + help + Use the BACnet basic positive-integer value object + +config CONFIG_BACNET_BASIC_OBJECT_SCHEDULE + bool "Use the BACnet basic schedule object" + default false + help + Use the BACnet basic schedule object + +config CONFIG_BACNET_BASIC_OBJECT_TIME_VALUE + bool "Use the BACnet basic time value object" + default false + help + Use the BACnet basic time value object + +config CONFIG_BACNET_BASIC_OBJECT_TRENDLOG + bool "Use the BACnet basic trendlog object" + default false + help + Use the BACnet basic trendlog object + rsource "subsys/Kconfig" endif # BACNETSTACK