From 70b5d45ce2d697cc8842771df20d28ef5a572cd2 Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 11 Feb 2010 04:31:43 +0000 Subject: [PATCH] Updated ports/bdk-atxx4-mstp to use demo handlers for RP,RPM,WP. --- bacnet-stack/include/ai.h | 2 +- bacnet-stack/include/bi.h | 2 + bacnet-stack/include/bo.h | 3 +- bacnet-stack/ports/bdk-atxx4-mstp/Makefile | 9 +- bacnet-stack/ports/bdk-atxx4-mstp/ai.c | 43 +- bacnet-stack/ports/bdk-atxx4-mstp/av.c | 126 +++-- bacnet-stack/ports/bdk-atxx4-mstp/bi.c | 48 +- bacnet-stack/ports/bdk-atxx4-mstp/bo.c | 165 +++--- bacnet-stack/ports/bdk-atxx4-mstp/device.c | 596 +++++++++++++++------ bacnet-stack/ports/bdk-atxx4-mstp/main.c | 37 +- 10 files changed, 652 insertions(+), 379 deletions(-) diff --git a/bacnet-stack/include/ai.h b/bacnet-stack/include/ai.h index 670424ad..84854a86 100644 --- a/bacnet-stack/include/ai.h +++ b/bacnet-stack/include/ai.h @@ -31,7 +31,7 @@ #include "rp.h" #ifndef MAX_ANALOG_INPUTS -#define MAX_ANALOG_INPUTS 7 +#define MAX_ANALOG_INPUTS 4 #endif #ifdef __cplusplus diff --git a/bacnet-stack/include/bi.h b/bacnet-stack/include/bi.h index 83a44fd3..7e1190b3 100644 --- a/bacnet-stack/include/bi.h +++ b/bacnet-stack/include/bi.h @@ -29,6 +29,8 @@ #include #include "bacdef.h" #include "cov.h" +#include "rp.h" +#include "wp.h" #ifndef MAX_BINARY_INPUTS #define MAX_BINARY_INPUTS 5 diff --git a/bacnet-stack/include/bo.h b/bacnet-stack/include/bo.h index 1b476c9b..eca98226 100644 --- a/bacnet-stack/include/bo.h +++ b/bacnet-stack/include/bo.h @@ -29,10 +29,11 @@ #include #include "bacdef.h" #include "bacerror.h" +#include "rp.h" #include "wp.h" #ifndef MAX_BINARY_OUTPUTS -#define MAX_BINARY_OUTPUTS 6 +#define MAX_BINARY_OUTPUTS 4 #endif #ifdef __cplusplus diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile index 62b23581..e0590db7 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/Makefile +++ b/bacnet-stack/ports/bdk-atxx4-mstp/Makefile @@ -18,6 +18,7 @@ SIZE = avr-size AVRDUDE = avrdude LINT = splint +SIZE_OPTIONS = -C --mcu=${MCU} # programmer id--check the avrdude for complete list # of available opts. These should include stk500, # avr910, avrisp, bsd, pony and more. Set this to @@ -58,9 +59,6 @@ CSRC = main.c \ eeprom.c \ seeprom.c \ dlmstp.c \ - h_wp.c \ - h_rp.c \ - h_rpm.c \ h_rd.c \ device.c \ ai.c \ @@ -73,6 +71,9 @@ DEMOSRC = $(BACNET_DEMO)/handler/txbuf.c \ $(BACNET_DEMO)/handler/h_npdu.c \ $(BACNET_DEMO)/handler/h_whois.c \ $(BACNET_DEMO)/handler/h_dcc.c \ + $(BACNET_DEMO)/handler/h_wp.c \ + $(BACNET_DEMO)/handler/h_rp.c \ + $(BACNET_DEMO)/handler/h_rpm.c \ $(BACNET_DEMO)/handler/s_iam.c \ $(BACNET_DEMO)/handler/noserv.c @@ -298,7 +299,7 @@ $(LIBRARY): $(COREOBJ) Makefile size: ${TARGET_ELF} @echo - @${SIZE} ${TARGET_ELF} + @${SIZE} ${SIZE_OPTIONS} ${TARGET_ELF} lint: $(LINT) $(BFLAGS) $(CSRC) diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c index a6d78e4c..6d721bf8 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/ai.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/ai.c @@ -32,11 +32,8 @@ #include "bacdcode.h" #include "bacenum.h" #include "config.h" - -/* Analog Input */ -#ifndef MAX_ANALOG_INPUTS -#define MAX_ANALOG_INPUTS 2 -#endif +#include "ai.h" +#include "handlers.h" static uint8_t Present_Value[MAX_ANALOG_INPUTS]; @@ -144,31 +141,33 @@ void Analog_Input_Present_Value_Set( } /* return apdu length, or -1 on error */ -/* assumption - object has already exists */ -int Analog_Input_Encode_Property_APDU( - uint8_t * apdu, - uint32_t object_instance, - BACNET_PROPERTY_ID property, - int32_t array_index, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) +/* 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; + uint8_t *apdu = NULL; - switch (property) { + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT, - object_instance); + rpdata->object_instance); break; /* note: Name and Description don't have to be the same. You could make Description writable and different */ case PROP_OBJECT_NAME: case PROP_DESCRIPTION: characterstring_init_ansi(&char_string, - Analog_Input_Name(object_instance)); + Analog_Input_Name(rpdata->object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -179,7 +178,7 @@ int Analog_Input_Encode_Property_APDU( case PROP_PRESENT_VALUE: apdu_len = encode_application_real(&apdu[0], - Analog_Input_Present_Value(object_instance)); + Analog_Input_Present_Value(rpdata->object_instance)); break; case PROP_STATUS_FLAGS: bitstring_init(&bit_string); @@ -200,16 +199,16 @@ int Analog_Input_Encode_Property_APDU( apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT); break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_UNKNOWN_PROPERTY; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && - (array_index != BACNET_ARRAY_ALL)) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + (rpdata->array_index != BACNET_ARRAY_ALL)) { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = -1; } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/av.c b/bacnet-stack/ports/bdk-atxx4-mstp/av.c index 75af4734..778ab27f 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/av.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/av.c @@ -40,10 +40,8 @@ #include "bacapp.h" #include "config.h" /* the custom stuff */ #include "wp.h" - -#ifndef MAX_ANALOG_VALUES -#define MAX_ANALOG_VALUES 4 -#endif +#include "av.h" +#include "handlers.h" static float Present_Value[MAX_ANALOG_VALUES]; @@ -194,13 +192,8 @@ char *Analog_Value_Name( } /* return apdu len, or -1 on error */ -int Analog_Value_Encode_Property_APDU( - uint8_t * apdu, - uint32_t object_instance, - BACNET_PROPERTY_ID property, - int32_t array_index, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) +int Analog_Value_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) { int apdu_len = 0; /* return value */ BACNET_BIT_STRING bit_string; @@ -211,17 +204,24 @@ int Analog_Value_Encode_Property_APDU( unsigned i = 0; bool state = false; #endif + uint8_t *apdu = NULL; - switch (property) { + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE, - object_instance); + rpdata->object_instance); break; case PROP_OBJECT_NAME: case PROP_DESCRIPTION: characterstring_init_ansi(&char_string, - Analog_Value_Name(object_instance)); + Analog_Value_Name(rpdata->object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -230,7 +230,7 @@ int Analog_Value_Encode_Property_APDU( encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE); break; case PROP_PRESENT_VALUE: - real_value = Analog_Value_Present_Value(object_instance); + real_value = Analog_Value_Present_Value(rpdata->object_instance); apdu_len = encode_application_real(&apdu[0], real_value); break; case PROP_STATUS_FLAGS: @@ -247,7 +247,7 @@ int Analog_Value_Encode_Property_APDU( break; case PROP_OUT_OF_SERVICE: #if 0 - object_index = Analog_Value_Instance_To_Index(object_instance); + object_index = Analog_Value_Instance_To_Index(rpdata->object_instance); state = Analog_Value_Out_Of_Service[object_index]; #endif apdu_len = encode_application_boolean(&apdu[0], false); @@ -258,12 +258,12 @@ int Analog_Value_Encode_Property_APDU( #if 0 case PROP_PRIORITY_ARRAY: /* Array element zero is the number of elements in the array */ - if (array_index == 0) + if (rpdata->array_index == 0) apdu_len = encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY); /* if no index was specified, then try to encode the entire list */ /* into one packet. */ - else if (array_index == BACNET_ARRAY_ALL) { + else if (rpdata->array_index == BACNET_ARRAY_ALL) { object_index = Analog_Value_Instance_To_Index(object_instance); for (i = 0; i < BACNET_MAX_PRIORITY; i++) { /* FIXME: check if we have room before adding it to APDU */ @@ -279,27 +279,27 @@ int Analog_Value_Encode_Property_APDU( if ((apdu_len + len) < MAX_APDU) apdu_len += len; else { - *error_class = ERROR_CLASS_SERVICES; - *error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; apdu_len = -1; break; } } } else { - object_index = Analog_Value_Instance_To_Index(object_instance); - if (array_index <= BACNET_MAX_PRIORITY) { - if (Present_Value[object_index][array_index - 1] == + object_index = Analog_Value_Instance_To_Index(rpdata->object_instance); + if (rpdata->array_index <= BACNET_MAX_PRIORITY) { + if (Present_Value[object_index][rpdata->array_index - 1] == ANALOG_LEVEL_NULL) apdu_len = encode_application_null(&apdu[0]); else { real_value = - Present_Value[object_index][array_index - 1]; + Present_Value[object_index][rpdata->array_index - 1]; apdu_len = encode_application_real(&apdu[0], real_value); } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_ARRAY_INDEX; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = -1; } } @@ -311,19 +311,19 @@ int Analog_Value_Encode_Property_APDU( break; #endif default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_UNKNOWN_PROPERTY; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && #if 0 - (property != PROP_PRIORITY_ARRAY) && + (rpdata->object_property != PROP_PRIORITY_ARRAY) && #endif - (array_index != BACNET_ARRAY_ALL)) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + (rpdata->array_index != BACNET_ARRAY_ALL)) { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = -1; } @@ -332,9 +332,7 @@ int Analog_Value_Encode_Property_APDU( /* returns true if successful */ bool Analog_Value_Write_Property( - BACNET_WRITE_PROPERTY_DATA * wp_data, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) + BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ #if 0 @@ -344,11 +342,6 @@ bool Analog_Value_Write_Property( int len = 0; BACNET_APPLICATION_DATA_VALUE value; - if (!Analog_Value_Valid_Instance(wp_data->object_instance)) { - *error_class = ERROR_CLASS_OBJECT; - *error_code = ERROR_CODE_UNKNOWN_OBJECT; - return false; - } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, @@ -357,19 +350,25 @@ bool Analog_Value_Write_Property( /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_PRESENT_VALUE: - if (value.tag == BACNET_APPLICATION_TAG_REAL) { - 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. */ - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_REAL, + &wp_data->error_class, + &wp_data->error_code); + if (status) { + status = Analog_Value_Present_Value_Set( + wp_data->object_instance, + value.type.Real, wp_data->priority); + if (!status) { + 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; + } } #if 0 } else if (value.tag == BACNET_APPLICATION_TAG_NULL) { @@ -377,31 +376,28 @@ bool Analog_Value_Write_Property( NAN, wp_data->priority)) { status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } #endif - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #if 0 case PROP_OUT_OF_SERVICE: - if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) { + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_BOOLEAN, + &wp_data->error_class, + &wp_data->error_code); + if (status) { object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); Analog_Value_Out_Of_Service[object_index] = value.type.Boolean; - status = true; - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #endif default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bi.c b/bacnet-stack/ports/bdk-atxx4-mstp/bi.c index 6f521a13..3d4b0d7a 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/bi.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/bi.c @@ -32,10 +32,8 @@ #include "bacdcode.h" #include "bacenum.h" #include "config.h" - -#ifndef MAX_BINARY_INPUTS -#define MAX_BINARY_INPUTS 8 -#endif +#include "bi.h" +#include "handlers.h" static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS]; @@ -143,17 +141,13 @@ BACNET_BINARY_PV Binary_Input_Present_Value( bool Binary_Input_Present_Value_Set( uint32_t object_instance, - bool value) + BACNET_BINARY_PV value) { unsigned index = 0; index = Binary_Input_Instance_To_Index(object_instance); if (index < MAX_BINARY_INPUTS) { - if (value) { - Present_Value[index] = BINARY_ACTIVE; - } else { - Present_Value[index] = BINARY_INACTIVE; - } + Present_Value[index] = value; return true; } @@ -175,31 +169,33 @@ char *Binary_Input_Name( /* return apdu length, or -1 on error */ /* assumption - object already exists, and has been bounds checked */ -int Binary_Input_Encode_Property_APDU( - uint8_t * apdu, - uint32_t object_instance, - BACNET_PROPERTY_ID property, - int32_t array_index, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) +int Binary_Input_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) { int apdu_len = 0; /* return value */ BACNET_BIT_STRING bit_string; BACNET_CHARACTER_STRING char_string; BACNET_POLARITY polarity = POLARITY_NORMAL; BACNET_BINARY_PV value = BINARY_INACTIVE; + uint8_t *apdu = NULL; - switch (property) { + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT, - object_instance); + rpdata->object_instance); break; case PROP_OBJECT_NAME: case PROP_DESCRIPTION: /* note: object name must be unique in our device */ characterstring_init_ansi(&char_string, - Binary_Input_Name(object_instance)); + Binary_Input_Name(rpdata->object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -208,7 +204,7 @@ int Binary_Input_Encode_Property_APDU( encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT); break; case PROP_PRESENT_VALUE: - value = Binary_Input_Present_Value(object_instance); + value = Binary_Input_Present_Value(rpdata->object_instance); apdu_len = encode_application_enumerated(&apdu[0], value); break; case PROP_STATUS_FLAGS: @@ -232,16 +228,16 @@ int Binary_Input_Encode_Property_APDU( apdu_len = encode_application_enumerated(&apdu[0], polarity); break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_UNKNOWN_PROPERTY; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && - (array_index != BACNET_ARRAY_ALL)) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + (rpdata->array_index != BACNET_ARRAY_ALL)) { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = -1; } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c index 151ed94b..703b9a94 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/bo.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/bo.c @@ -35,10 +35,8 @@ #include "wp.h" #include "led.h" #include "nvdata.h" - -#ifndef MAX_BINARY_OUTPUTS -#define MAX_BINARY_OUTPUTS 2 -#endif +#include "bo.h" +#include "handlers.h" /* When all the priorities are level null, the present value returns */ /* the Relinquish Default value */ @@ -251,13 +249,8 @@ char *Binary_Output_Name( } /* return apdu len, or -1 on error */ -int Binary_Output_Encode_Property_APDU( - uint8_t * apdu, - uint32_t object_instance, - BACNET_PROPERTY_ID property, - int32_t array_index, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) +int Binary_Output_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) { int len = 0; int apdu_len = 0; /* return value */ @@ -267,19 +260,26 @@ int Binary_Output_Encode_Property_APDU( unsigned object_index = 0; unsigned i = 0; bool state = false; + uint8_t *apdu = NULL; - switch (property) { + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT, - object_instance); + rpdata->object_instance); break; /* note: Name and Description don't have to be the same. You could make Description writable and different */ case PROP_OBJECT_NAME: case PROP_DESCRIPTION: characterstring_init_ansi(&char_string, - Binary_Output_Name(object_instance)); + Binary_Output_Name(rpdata->object_instance)); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -288,7 +288,7 @@ int Binary_Output_Encode_Property_APDU( encode_application_enumerated(&apdu[0], OBJECT_BINARY_OUTPUT); break; case PROP_PRESENT_VALUE: - present_value = Binary_Output_Present_Value(object_instance); + present_value = Binary_Output_Present_Value(rpdata->object_instance); apdu_len = encode_application_enumerated(&apdu[0], present_value); break; case PROP_STATUS_FLAGS: @@ -306,25 +306,26 @@ int Binary_Output_Encode_Property_APDU( encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL); break; case PROP_OUT_OF_SERVICE: - object_index = Binary_Output_Instance_To_Index(object_instance); + object_index = Binary_Output_Instance_To_Index(rpdata->object_instance); state = Out_Of_Service[object_index]; apdu_len = encode_application_boolean(&apdu[0], state); break; case PROP_POLARITY: + object_index = Binary_Output_Instance_To_Index(rpdata->object_instance); apdu_len = encode_application_enumerated(&apdu[0], Polarity[object_index]); break; case PROP_PRIORITY_ARRAY: /* Array element zero is the number of elements in the array */ - if (array_index == 0) + if (rpdata->array_index == 0) apdu_len = encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY); /* if no index was specified, then try to encode the entire list */ /* into one packet. */ - else if (array_index == BACNET_ARRAY_ALL) { + else if (rpdata->array_index == BACNET_ARRAY_ALL) { object_index = - Binary_Output_Instance_To_Index(object_instance); + Binary_Output_Instance_To_Index(rpdata->object_instance); for (i = 0; i < BACNET_MAX_PRIORITY; i++) { /* FIXME: check if we have room before adding it to APDU */ present_value = Binary_Output_Level[object_index][i]; @@ -339,18 +340,18 @@ int Binary_Output_Encode_Property_APDU( if ((apdu_len + len) < MAX_APDU) apdu_len += len; else { - *error_class = ERROR_CLASS_SERVICES; - *error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; apdu_len = -1; break; } } } else { object_index = - Binary_Output_Instance_To_Index(object_instance); - if (array_index <= BACNET_MAX_PRIORITY) { + Binary_Output_Instance_To_Index(rpdata->object_instance); + if (rpdata->array_index <= BACNET_MAX_PRIORITY) { present_value = - Binary_Output_Level[object_index][array_index - 1]; + Binary_Output_Level[object_index][rpdata->array_index - 1]; if (present_value == BINARY_NULL) { apdu_len = encode_application_null(&apdu[apdu_len]); } else { @@ -359,8 +360,8 @@ int Binary_Output_Encode_Property_APDU( present_value); } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_ARRAY_INDEX; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = -1; } } @@ -380,17 +381,17 @@ int Binary_Output_Encode_Property_APDU( encode_application_character_string(&apdu[0], &char_string); break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_UNKNOWN_PROPERTY; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && - (property != PROP_PRIORITY_ARRAY) && - (array_index != BACNET_ARRAY_ALL)) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + (rpdata->object_property != PROP_PRIORITY_ARRAY) && + (rpdata->array_index != BACNET_ARRAY_ALL)) { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = -1; } @@ -399,9 +400,7 @@ int Binary_Output_Encode_Property_APDU( /* returns true if successful */ bool Binary_Output_Write_Property( - BACNET_WRITE_PROPERTY_DATA * wp_data, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) + BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int object_index = 0; @@ -410,12 +409,6 @@ bool Binary_Output_Write_Property( int len = 0; BACNET_APPLICATION_DATA_VALUE value; - object_index = Binary_Output_Instance_To_Index(wp_data->object_instance); - if (object_index >= MAX_BINARY_OUTPUTS) { - *error_class = ERROR_CLASS_OBJECT; - *error_code = ERROR_CODE_UNKNOWN_OBJECT; - return false; - } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, @@ -424,7 +417,11 @@ bool Binary_Output_Write_Property( /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_PRESENT_VALUE: - if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_ENUMERATED, + &wp_data->error_class, + &wp_data->error_code); + if (status) { priority = wp_data->priority; /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any @@ -436,70 +433,76 @@ bool Binary_Output_Write_Property( priority--; Binary_Output_Level_Set(object_index, priority, level); Binary_Output_Level_Sync(object_index); - status = true; } else if (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. */ - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + status = false; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - } - } else if (value.tag == BACNET_APPLICATION_TAG_NULL) { - level = BINARY_NULL; - priority = wp_data->priority; - if (priority && (priority <= BACNET_MAX_PRIORITY)) { - priority--; - Binary_Output_Level_Set(object_index, priority, level); - Binary_Output_Level_Sync(object_index); - status = true; - } else if (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. */ - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + status = false; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_NULL, + &wp_data->error_class, + &wp_data->error_code); + if (status) { + level = BINARY_NULL; + priority = wp_data->priority; + if (priority && (priority <= BACNET_MAX_PRIORITY)) { + priority--; + Binary_Output_Level_Set(object_index, priority, level); + Binary_Output_Level_Sync(object_index); + } else if (priority == 6) { + status = false; + /* 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 { + 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: - if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) { + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_BOOLEAN, + &wp_data->error_class, + &wp_data->error_code); + if (status) { Binary_Output_Out_Of_Service_Set(object_index, value.type.Boolean); Binary_Output_Level_Sync(object_index); - status = true; - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_POLARITY: - if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { + status = WPValidateArgType(&value, + BACNET_APPLICATION_TAG_ENUMERATED, + &wp_data->error_class, + &wp_data->error_code); + if (status) { if (value.type.Enumerated < MAX_POLARITY) { Binary_Output_Polarity_Set(object_index, value.type.Enumerated); Binary_Output_Level_Sync(object_index); - status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + status = false; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } - } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/device.c b/bacnet-stack/ports/bdk-atxx4-mstp/device.c index 0f4f0186..520d67d1 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/device.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/device.c @@ -38,6 +38,7 @@ #include "version.h" #include "nvdata.h" #include "stack.h" +#include "handlers.h" /* objects */ #include "device.h" #include "ai.h" @@ -45,14 +46,225 @@ #include "bi.h" #include "bo.h" + +static struct object_functions { + BACNET_OBJECT_TYPE Object_Type; + object_init_function Object_Init; + object_count_function Object_Count; + object_index_to_instance_function Object_Index_To_Instance; + object_valid_instance_function Object_Valid_Instance; + object_name_function Object_Name; + read_property_function Object_Read_Property; + write_property_function Object_Write_Property; + rpm_property_lists_function Object_RPM_List; +} Object_Table[] = +{ + {OBJECT_DEVICE, + NULL,/* don't init - recursive! */ + Device_Count, + Device_Index_To_Instance, + Device_Valid_Object_Instance_Number, + Device_Name, + Device_Read_Property, + Device_Write_Property, + Device_Property_Lists}, + {OBJECT_ANALOG_INPUT, + Analog_Input_Init, + Analog_Input_Count, + Analog_Input_Index_To_Instance, + Analog_Input_Valid_Instance, + Analog_Input_Name, + Analog_Input_Read_Property, + NULL, + Analog_Input_Property_Lists}, + {OBJECT_ANALOG_VALUE, + Analog_Value_Init, + Analog_Value_Count, + Analog_Value_Index_To_Instance, + Analog_Value_Valid_Instance, + Analog_Value_Name, + Analog_Value_Read_Property, + Analog_Value_Write_Property, + Analog_Value_Property_Lists}, + {OBJECT_BINARY_INPUT, + Binary_Input_Init, + Binary_Input_Count, + Binary_Input_Index_To_Instance, + Binary_Input_Valid_Instance, + Binary_Input_Name, + Binary_Input_Read_Property, + NULL, + Binary_Input_Property_Lists}, + {OBJECT_BINARY_OUTPUT, + Binary_Output_Init, + Binary_Output_Count, + Binary_Output_Index_To_Instance, + Binary_Output_Valid_Instance, + Binary_Output_Name, + Binary_Output_Read_Property, + Binary_Output_Write_Property, + Binary_Output_Property_Lists}, + + {MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL} +}; + +/* Encodes the property APDU and returns the length, + or sets the error, and returns -1 */ +int Device_Objects_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) +{ + int apdu_len = -1; + unsigned index = 0; + struct object_functions *pObject = NULL; + bool found = false; + + /* initialize the default return values */ + rpdata->error_class = ERROR_CLASS_OBJECT; + rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + /* handle each object type */ + if (pObject->Object_Type == rpdata->object_type) { + found = true; + if (pObject->Object_Valid_Instance && + pObject->Object_Valid_Instance(rpdata->object_instance)) { + if (pObject->Object_Read_Property) { + apdu_len = pObject->Object_Read_Property(rpdata); + } + } else { + rpdata->error_class = ERROR_CLASS_OBJECT; + rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT; + } + break; + } + index++; + pObject = &Object_Table[index]; + } + if (!found) { + rpdata->error_class = ERROR_CLASS_OBJECT; + rpdata->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE; + } + + return apdu_len; +} + +bool Device_Objects_Write_Property( + BACNET_WRITE_PROPERTY_DATA * wp_data) +{ + int apdu_len = -1; + unsigned index = 0; + struct object_functions *pObject = NULL; + bool found = false; + + /* initialize the default return values */ + wp_data->error_class = ERROR_CLASS_OBJECT; + wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + /* handle each object type */ + if (pObject->Object_Type == wp_data->object_type) { + found = true; + if (pObject->Object_Valid_Instance && + pObject->Object_Valid_Instance(wp_data->object_instance)) { + if (pObject->Object_Write_Property) { + apdu_len = pObject->Object_Write_Property(wp_data); + } else { + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + } + } else { + wp_data->error_class = ERROR_CLASS_OBJECT; + wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; + } + break; + } + index++; + pObject = &Object_Table[index]; + } + if (!found) { + wp_data->error_class = ERROR_CLASS_OBJECT; + wp_data->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE; + } + + return apdu_len; +} + +static unsigned property_list_count( + const int *pList) +{ + unsigned property_count = 0; + + if (pList) { + while (*pList != -1) { + property_count++; + pList++; + } + } + + return property_count; +} + +/* for a given object type, returns the special property list */ +static void Device_Objects_Property_List( + BACNET_OBJECT_TYPE object_type, + struct special_property_list_t *pPropertyList) +{ + rpm_property_lists_function object_property_list = NULL; + unsigned index = 0; + struct object_functions *pObject = NULL; + bool found = false; + + pPropertyList->Required.pList = NULL; + pPropertyList->Optional.pList = NULL; + pPropertyList->Proprietary.pList = NULL; + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + /* handle each object type */ + if (pObject->Object_Type == object_type) { + found = true; + object_property_list = pObject->Object_RPM_List; + break; + } + index++; + pObject = &Object_Table[index]; + } + if (found && object_property_list) { + object_property_list( + &pPropertyList->Required.pList, + &pPropertyList->Optional.pList, + &pPropertyList->Proprietary.pList); + } + /* fill the count */ + if (pPropertyList->Required.pList) { + pPropertyList->Required.count = + property_list_count(pPropertyList->Required.pList); + } else { + pPropertyList->Required.count = 0; + } + if (pPropertyList->Optional.pList) { + pPropertyList->Optional.count = + property_list_count(pPropertyList->Optional.pList); + } else { + pPropertyList->Optional.count = 0; + } + if (pPropertyList->Proprietary.pList) { + pPropertyList->Proprietary.count = + property_list_count(pPropertyList->Proprietary.pList); + } else { + pPropertyList->Proprietary.count = 0; + } + + return; +} + /* note: you really only need to define variables for properties that are writable or that may change. The properties that are constant can be hard coded into the read-property encoding. */ static uint32_t Object_Instance_Number; -static char Object_Name[NV_EEPROM_DEVICE_NAME_SIZE]; -static uint8_t Object_Name_Encoding; -static uint8_t Object_Name_Length; +static char My_Object_Name[NV_EEPROM_DEVICE_NAME_SIZE]; +static uint8_t My_Object_Name_Encoding; +static uint8_t My_Object_Name_Length; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State = @@ -110,6 +322,27 @@ void Device_Property_Lists( return; } +unsigned Device_Count(void) +{ + return 1; +} + +uint32_t Device_Index_To_Instance( + unsigned index) +{ + return Object_Instance_Number; +} + +char *Device_Name( + uint32_t object_instance) +{ + if (object_instance == Object_Instance_Number) { + return My_Object_Name; + } + + return NULL; +} + void Device_Reinit( void) { @@ -120,6 +353,23 @@ void Device_Reinit( void Device_Init( void) { + unsigned index = 0; /* loop counter */ + struct object_functions *pObject = NULL; + + handler_read_property_function_set(Device_Objects_Read_Property); + handler_rpm_function_set(Device_Objects_Read_Property); + handler_rpm_list_set(Device_Objects_Property_List); + handler_write_property_function_set(Device_Objects_Write_Property); + + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + if (pObject->Object_Init) { + pObject->Object_Init(); + } + index++; + pObject = &Object_Table[index]; + } + Reinitialize_State = REINITIALIZED_STATE_IDLE; dcc_set_status_duration(COMMUNICATION_ENABLE, 0); @@ -132,22 +382,22 @@ void Device_Init( (uint8_t *) & Object_Instance_Number, sizeof(Object_Instance_Number)); } - eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_ENCODING, &Object_Name_Encoding, + eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_ENCODING, &My_Object_Name_Encoding, 1); - eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_LENGTH, &Object_Name_Length, 1); - eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_0, (uint8_t *) & Object_Name[0], + eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_LENGTH, &My_Object_Name_Length, 1); + eeprom_bytes_read(NV_EEPROM_DEVICE_NAME_0, (uint8_t *) & My_Object_Name[0], NV_EEPROM_DEVICE_NAME_SIZE); - if ((Object_Name_Encoding >= MAX_CHARACTER_STRING_ENCODING) || - (Object_Name_Length > NV_EEPROM_DEVICE_NAME_SIZE) || - (Object_Name_Length < 1)) { - Object_Name_Encoding = CHARACTER_ANSI_X34; + if ((My_Object_Name_Encoding >= MAX_CHARACTER_STRING_ENCODING) || + (My_Object_Name_Length > NV_EEPROM_DEVICE_NAME_SIZE) || + (My_Object_Name_Length < 1)) { + My_Object_Name_Encoding = CHARACTER_ANSI_X34; eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_ENCODING, - &Object_Name_Encoding, 1); - sprintf(Object_Name, "DEVICE-%lu", Object_Instance_Number); + &My_Object_Name_Encoding, 1); + sprintf(My_Object_Name, "DEVICE-%lu", Object_Instance_Number); eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_0, - (uint8_t *) & Object_Name[0], NV_EEPROM_DEVICE_NAME_SIZE); - Object_Name_Length = strlen(Object_Name); - eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_LENGTH, &Object_Name_Length, + (uint8_t *) & My_Object_Name[0], NV_EEPROM_DEVICE_NAME_SIZE); + My_Object_Name_Length = strlen(My_Object_Name); + eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_LENGTH, &My_Object_Name_Length, 1); } } @@ -189,11 +439,19 @@ BACNET_DEVICE_STATUS Device_System_Status( return System_Status; } -void Device_Set_System_Status( - BACNET_DEVICE_STATUS status) +int Device_Set_System_Status( + BACNET_DEVICE_STATUS status, + bool local) { - if (status < MAX_DEVICE_STATUS) + /*return value - 0 = ok, -1 = bad value, -2 = not allowed */ + int result = -1; + + if (status < MAX_DEVICE_STATUS) { System_Status = status; + result = 0; + } + + return result; } uint16_t Device_Vendor_Identifier( @@ -220,22 +478,30 @@ BACNET_SEGMENTATION Device_Segmentation_Supported( return SEGMENTATION_NONE; } -uint8_t Device_Database_Revision( +uint32_t Device_Database_Revision( void) { return 0; } +/* Since many network clients depend on the object list */ +/* for discovery, it must be consistent! */ unsigned Device_Object_List_Count( void) { - unsigned count = 1; /* at least 1 for device object */ + unsigned count = 0; /* number of objects */ + unsigned index = 0; /* loop counter */ + struct object_functions *pObject = NULL; - /* FIXME: add objects as needed */ - count += Binary_Input_Count(); - count += Binary_Output_Count(); - count += Analog_Input_Count(); - count += Analog_Value_Count(); + /* initialize the default return values */ + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + if (pObject->Object_Count) { + count += pObject->Object_Count(); + } + index++; + pObject = &Object_Table[index]; + } return count; } @@ -246,80 +512,96 @@ bool Device_Object_List_Identifier( uint32_t * instance) { bool status = false; + unsigned count = 0; unsigned object_index = 0; - unsigned object_count = 0; + unsigned index = 0; /* loop counter */ + struct object_functions *pObject = NULL; - /* device object */ - if (array_index == 1) { - *object_type = OBJECT_DEVICE; - *instance = Object_Instance_Number; - status = true; + /* array index zero is length - so invalid */ + if (array_index == 0) { + return status; } - /* normalize the index since - we know it is not the previous objects */ - /* array index starts at 1 */ object_index = array_index - 1; - /* 1 for the device object */ - object_count = 1; - /* FIXME: add objects as needed */ - /* binary value objects */ - if (!status) { - object_index -= object_count; - object_count = Binary_Output_Count(); - /* is it a valid index for this object? */ - if (object_index < object_count) { - *object_type = OBJECT_BINARY_OUTPUT; - *instance = Binary_Output_Index_To_Instance(object_index); - status = true; - } - } - /* analog input objects */ - if (!status) { - /* array index starts at 1, and 1 for the device object */ - object_index -= object_count; - object_count = Analog_Input_Count(); - if (object_index < object_count) { - *object_type = OBJECT_ANALOG_INPUT; - *instance = Analog_Input_Index_To_Instance(object_index); - status = true; - } - } - /* binary input objects */ - if (!status) { - /* normalize the index since - we know it is not the previous objects */ - object_index -= object_count; - object_count = Binary_Input_Count(); - /* is it a valid index for this object? */ - if (object_index < object_count) { - *object_type = OBJECT_BINARY_INPUT; - *instance = Binary_Input_Index_To_Instance(object_index); - status = true; - } - } - /* analog value objects */ - if (!status) { - /* array index starts at 1, and 1 for the device object */ - object_index -= object_count; - object_count = Analog_Value_Count(); - if (object_index < object_count) { - *object_type = OBJECT_ANALOG_VALUE; - *instance = Analog_Value_Index_To_Instance(object_index); - status = true; + /* initialize the default return values */ + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + if (pObject->Object_Count && + pObject->Object_Index_To_Instance) { + object_index -= count; + count = pObject->Object_Count(); + if (object_index < count) { + *object_type = pObject->Object_Type; + *instance = pObject->Object_Index_To_Instance(object_index); + status = true; + break; + } } + index++; + pObject = &Object_Table[index]; } return status; } +bool Device_Valid_Object_Name( + const char *object_name, + int *object_type, + uint32_t * object_instance) +{ + bool found = false; + int type = 0; + uint32_t instance; + unsigned max_objects = 0, i = 0; + bool check_id = false; + char *name = NULL; + + max_objects = Device_Object_List_Count(); + for (i = 0; i < max_objects; i++) { + check_id = Device_Object_List_Identifier(i, &type, &instance); + if (check_id) { + name = Device_Valid_Object_Id(type, instance); + if (strcmp(name, object_name) == 0) { + found = true; + if (object_type) { + *object_type = type; + } + if (object_instance) { + *object_instance = instance; + } + break; + } + } + } + + return found; +} + +/* returns the name or NULL if not found */ +char *Device_Valid_Object_Id( + int object_type, + uint32_t object_instance) +{ + char *name = NULL; /* return value */ + unsigned index = 0; /* loop counter */ + struct object_functions *pObject = NULL; + + pObject = &Object_Table[0]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + if ((pObject->Object_Type == object_type) && + (pObject->Object_Name)) { + name = pObject->Object_Name(object_instance); + break; + } + index++; + pObject = &Object_Table[index]; + } + + return name; +} + /* return the length of the apdu encoded or -1 for error */ -int Device_Encode_Property_APDU( - uint8_t * apdu, - uint32_t object_instance, - BACNET_PROPERTY_ID property, - int32_t array_index, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) +int Device_Read_Property( + BACNET_READ_PROPERTY_DATA *rpdata) { int apdu_len = 0; /* return value */ int len = 0; /* apdu len intermediate value */ @@ -329,18 +611,24 @@ int Device_Encode_Property_APDU( int object_type = 0; uint32_t instance = 0; unsigned count = 0; + uint8_t *apdu = NULL; + struct object_functions *pObject = NULL; - object_instance = object_instance; - /* FIXME: change the hardcoded names to suit your application */ - switch (property) { + if ((rpdata == NULL) || + (rpdata->application_data == NULL) || + (rpdata->application_data_len == 0)) { + return 0; + } + apdu = rpdata->application_data; + switch (rpdata->object_property) { case PROP_OBJECT_IDENTIFIER: apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE, Object_Instance_Number); break; case PROP_OBJECT_NAME: - characterstring_init(&char_string, Object_Name_Encoding, - (char *) &Object_Name[0], Object_Name_Length); + characterstring_init(&char_string, My_Object_Name_Encoding, + (char *) &My_Object_Name[0], My_Object_Name_Length); apdu_len = encode_application_character_string(&apdu[0], &char_string); break; @@ -415,24 +703,29 @@ int Device_Encode_Property_APDU( /* initialize all the object types to not-supported */ bitstring_set_bit(&bit_string, (uint8_t) i, false); } - /* FIXME: indicate the objects that YOU support */ - bitstring_set_bit(&bit_string, OBJECT_DEVICE, true); - bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true); - bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true); - bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true); - bitstring_set_bit(&bit_string, OBJECT_BINARY_OUTPUT, true); + /* set the object types with objects to supported */ + i = 0; + pObject = &Object_Table[i]; + while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) { + if ((pObject->Object_Count) && + (pObject->Object_Count() > 0)) { + bitstring_set_bit(&bit_string, pObject->Object_Type, true); + } + i++; + pObject = &Object_Table[i]; + } apdu_len = encode_application_bitstring(&apdu[0], &bit_string); break; case PROP_OBJECT_LIST: count = Device_Object_List_Count(); /* Array element zero is the number of objects in the list */ - if (array_index == 0) + if (rpdata->array_index == 0) apdu_len = encode_application_unsigned(&apdu[0], count); /* if no index was specified, then try to encode the entire list */ /* into one packet. Note that more than likely you will have */ /* to return an error if the number of encoded objects exceeds */ /* your maximum APDU size. */ - else if (array_index == BACNET_ARRAY_ALL) { + else if (rpdata->array_index == BACNET_ARRAY_ALL) { for (i = 1; i <= count; i++) { if (Device_Object_List_Identifier(i, &object_type, &instance)) { @@ -443,28 +736,28 @@ int Device_Encode_Property_APDU( /* assume next one is the same size as this one */ /* can we all fit into the APDU? */ if ((apdu_len + len) >= MAX_APDU) { - *error_class = ERROR_CLASS_SERVICES; - *error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT; apdu_len = -1; break; } } else { /* error: internal error? */ - *error_class = ERROR_CLASS_SERVICES; - *error_code = ERROR_CODE_OTHER; + rpdata->error_class = ERROR_CLASS_SERVICES; + rpdata->error_code = ERROR_CODE_OTHER; apdu_len = -1; break; } } } else { - if (Device_Object_List_Identifier(array_index, &object_type, + if (Device_Object_List_Identifier(rpdata->array_index, &object_type, &instance)) apdu_len = encode_application_object_id(&apdu[0], object_type, instance); else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_ARRAY_INDEX; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; apdu_len = -1; } } @@ -511,17 +804,17 @@ int Device_Encode_Property_APDU( encode_application_unsigned(&apdu[0], rs485_baud_rate()); break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_UNKNOWN_PROPERTY; + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY; apdu_len = -1; break; } /* only array properties can have array options */ if ((apdu_len >= 0) && - (property != PROP_OBJECT_LIST) && - (array_index != BACNET_ARRAY_ALL)) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; + (rpdata->object_property != PROP_OBJECT_LIST) && + (rpdata->array_index != BACNET_ARRAY_ALL)) { + rpdata->error_class = ERROR_CLASS_PROPERTY; + rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; apdu_len = -1; } @@ -529,19 +822,12 @@ int Device_Encode_Property_APDU( } bool Device_Write_Property( - BACNET_WRITE_PROPERTY_DATA * wp_data, - BACNET_ERROR_CLASS * error_class, - BACNET_ERROR_CODE * error_code) + BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; - if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { - *error_class = ERROR_CLASS_OBJECT; - *error_code = ERROR_CODE_UNKNOWN_OBJECT; - return false; - } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, @@ -557,12 +843,12 @@ bool Device_Write_Property( /* we could send an I-Am broadcast to let the world know */ status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: @@ -571,12 +857,12 @@ bool Device_Write_Property( dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: @@ -586,12 +872,12 @@ bool Device_Write_Property( dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: @@ -599,40 +885,40 @@ bool Device_Write_Property( size_t length = characterstring_length(&value.type.Character_String); if (length < 1) { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } else if (length < NV_EEPROM_DEVICE_NAME_SIZE) { uint8_t encoding = characterstring_encoding(&value.type.Character_String); if (encoding < MAX_CHARACTER_STRING_ENCODING) { uint8_t i; char *pCharString; - Object_Name_Encoding = encoding; - Object_Name_Length = length; + My_Object_Name_Encoding = encoding; + My_Object_Name_Length = length; eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_ENCODING, - &Object_Name_Encoding, 1); + &My_Object_Name_Encoding, 1); eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_LENGTH, - &Object_Name_Length, 1); + &My_Object_Name_Length, 1); pCharString = characterstring_value(&value. type.Character_String); - for (i = 0; i < Object_Name_Length; i++) { - Object_Name[i] = pCharString[i]; + for (i = 0; i < My_Object_Name_Length; i++) { + My_Object_Name[i] = pCharString[i]; } eeprom_bytes_write(NV_EEPROM_DEVICE_NAME_0, - (uint8_t *) & Object_Name[0], length); + (uint8_t *) & My_Object_Name[0], length); status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: @@ -641,17 +927,17 @@ bool Device_Write_Property( (rs485_baud_rate_set(value.type.Unsigned_Int))) { status = true; } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INVALID_DATA_TYPE; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; default: - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; + wp_data->error_class = ERROR_CLASS_PROPERTY; + wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } diff --git a/bacnet-stack/ports/bdk-atxx4-mstp/main.c b/bacnet-stack/ports/bdk-atxx4-mstp/main.c index 341e8855..bce382ac 100644 --- a/bacnet-stack/ports/bdk-atxx4-mstp/main.c +++ b/bacnet-stack/ports/bdk-atxx4-mstp/main.c @@ -92,10 +92,6 @@ static void bacnet_init( } /* initialize objects */ Device_Init(); - Binary_Output_Init(); - Analog_Input_Init(); - Binary_Input_Init(); - Analog_Value_Init(); /* set up our confirmed service unrecognized service handler - required! */ apdu_set_unrecognized_service_handler_handler @@ -123,12 +119,14 @@ static uint8_t PDUBuffer[MAX_MPDU]; static void bacnet_task( void) { - uint8_t mstp_mac_address = 0; - uint16_t pdu_len = 0; + uint8_t mstp_mac_address; + uint16_t pdu_len; BACNET_ADDRESS src; /* source address */ - uint8_t value = 0; - bool button_value = false; - uint8_t i = 0; + uint8_t value; + bool button_value; + uint8_t i; + BACNET_BINARY_PV binary_value = BINARY_INACTIVE; + mstp_mac_address = input_address(); if (MSTP_MAC_Address != mstp_mac_address) { @@ -140,12 +138,16 @@ static void bacnet_task( /* handle the inputs */ value = adc_result(7); Analog_Input_Present_Value_Set(0, value); - for (i = 0; i < 5; i++) { + for (i = 0; i < MAX_BINARY_INPUTS; i++) { button_value = input_button_value(i); - Binary_Input_Present_Value_Set(i, button_value); + if (button_value) { + binary_value = BINARY_ACTIVE; + } + Binary_Input_Present_Value_Set(i, binary_value); } /* handle the communication timer */ if (timer_elapsed_seconds(TIMER_DCC, 1)) { + timer_reset(TIMER_DCC); dcc_timer_seconds(1); } /* handle the messaging */ @@ -155,17 +157,6 @@ static void bacnet_task( } } -void idle_init( - void) -{ -} - -void idle_task( - void) -{ - /* do nothing */ -} - void test_init( void) { @@ -252,7 +243,6 @@ int main( rs485_init(); serial_init(); bacnet_init(); - idle_init(); test_init(); /* Enable global interrupts */ __enable_interrupt(); @@ -261,7 +251,6 @@ int main( input_task(); bacnet_task(); led_task(); - idle_task(); test_task(); } }