diff --git a/bacnet-stack/ao.c b/bacnet-stack/ao.c index 01442fec..2f6dc881 100644 --- a/bacnet-stack/ao.c +++ b/bacnet-stack/ao.c @@ -258,13 +258,6 @@ bool Analog_Output_Write_Property( BACNET_ERROR_CODE *error_code) { bool status = false; // return value - uint8_t *apdu = NULL; - int len = 0; - int tag_len = 0; - int apdu_len = 0; - uint8_t tag_number = 0; - uint32_t len_value_type = 0; - float real_value = 0.0; unsigned int object_index = 0; unsigned int priority = 0; uint8_t level = AO_LEVEL_NULL; @@ -281,61 +274,27 @@ bool Analog_Output_Write_Property( switch (wp_data->object_property) { case PROP_PRESENT_VALUE: - apdu = wp_data->property_value; - tag_len = decode_tag_number_and_value(&apdu[0], - &tag_number, &len_value_type); - if (tag_len) + if (wp_data->value.tag == BACNET_APPLICATION_TAG_REAL) { - if (tag_number == BACNET_APPLICATION_TAG_REAL) - { - len = decode_real(&apdu[tag_len],&real_value); - if (len && (real_value >= 0.0) && (real_value <= 100.0)) - level = real_value; - else - { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - return false; - } - object_index = Analog_Output_Instance_To_Index( - wp_data->object_instance); - apdu_len = tag_len + len; - if (decode_is_closing_tag_number(&apdu[apdu_len], 3)) - { - // decode the optional priority - apdu_len++; - if (apdu_len <= wp_data->property_value_len) - priority = BACNET_MAX_PRIORITIES; - else - { - tag_len = decode_tag_number_and_value(&apdu[0], - &tag_number, &len_value_type); - if (tag_number == 4) - { - apdu_len += tag_len; - len = decode_unsigned(&apdu[len], len_value_type, - &priority); - } - } - priority--; - if (priority < BACNET_MAX_PRIORITIES) - { - Analog_Output_Level[object_index][priority] = level; - status = true; - } - else - { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; - return false; - } - } - else - { - *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_INCONSISTENT_PARAMETERS; - return false; - } + fprintf(stderr, "Real=%f\n",wp_data->value.type.Real); + if ((wp_data->value.type.Real >= 0.0) && + (wp_data->value.type.Real <= 100.0)) + level = wp_data->value.type.Real; + else + { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; + return false; + } + object_index = Analog_Output_Instance_To_Index( + wp_data->object_instance); + priority = wp_data->priority; + fprintf(stderr, "Priority=%u\n",wp_data->priority); + if (priority && (priority <= BACNET_MAX_PRIORITIES)) + { + priority--; + Analog_Output_Level[object_index][priority] = level; + status = true; } else { diff --git a/bacnet-stack/device.c b/bacnet-stack/device.c index c5ba5b7b..968798a1 100644 --- a/bacnet-stack/device.c +++ b/bacnet-stack/device.c @@ -454,13 +454,6 @@ bool Device_Write_Property( BACNET_ERROR_CODE *error_code) { bool status = false; // return value - uint8_t *apdu = NULL; - int len = 0; - int tag_len = 0; - uint8_t tag_number = 0; - uint32_t len_value_type = 0; - int object_type = 0; - uint32_t instance = 0; if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { @@ -470,23 +463,16 @@ bool Device_Write_Property( } // decode the some of the request - apdu = wp_data->property_value; - tag_len = decode_tag_number_and_value(&apdu[0], - &tag_number, &len_value_type); switch (wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: - if (tag_len && (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID)) + if (wp_data->value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { - // FIXME: are we exceeding the property_value_len? - len = decode_object_id(&apdu[tag_len], - &object_type, - &instance); - if (len && - (object_type == OBJECT_DEVICE) && - (instance <= BACNET_MAX_INSTANCE)) + if ((wp_data->value.type.Object_ID.type == OBJECT_DEVICE) && + (wp_data->value.type.Object_ID.instance <= BACNET_MAX_INSTANCE)) { - Device_Set_Object_Instance_Number(instance); + Device_Set_Object_Instance_Number( + wp_data->value.type.Object_ID.instance); I_Am_Request = true; status = true; } diff --git a/bacnet-stack/wp.c b/bacnet-stack/wp.c index 1993b510..92afebd4 100644 --- a/bacnet-stack/wp.c +++ b/bacnet-stack/wp.c @@ -44,7 +44,6 @@ int wp_encode_apdu( uint8_t invoke_id, BACNET_WRITE_PROPERTY_DATA *data) { - int len = 0; // length of each encoding int apdu_len = 0; // total length of the apdu, return value if (apdu) @@ -64,10 +63,38 @@ int wp_encode_apdu( data->array_index); // propertyValue apdu_len += encode_opening_tag(&apdu[apdu_len], 3); - for (len = 0; len < data->property_value_len; len++) - { - apdu[apdu_len++] = data->property_value[len]; - } + if (data->value.tag == BACNET_APPLICATION_TAG_NULL) + apdu[apdu_len++] = data->value.tag; + else if (data->value.tag == BACNET_APPLICATION_TAG_BOOLEAN) + apdu_len += encode_tagged_boolean(&apdu[apdu_len], + data->value.type.Boolean); + else if (data->value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) + apdu_len += encode_tagged_unsigned(&apdu[apdu_len], + data->value.type.Unsigned_Int); + else if (data->value.tag == BACNET_APPLICATION_TAG_SIGNED_INT) + apdu_len += encode_tagged_signed(&apdu[apdu_len], + data->value.type.Signed_Int); + else if (data->value.tag == BACNET_APPLICATION_TAG_REAL) + apdu_len += encode_tagged_real(&apdu[apdu_len], + data->value.type.Real); + else if (data->value.tag == BACNET_APPLICATION_TAG_ENUMERATED) + apdu_len += encode_tagged_enumerated(&apdu[apdu_len], + data->value.type.Enumerated); + else if (data->value.tag == BACNET_APPLICATION_TAG_DATE) + apdu_len += encode_tagged_date(&apdu[apdu_len], + data->value.type.Date.year, + data->value.type.Date.month, + data->value.type.Date.day, + data->value.type.Date.wday); + else if (data->value.tag == BACNET_APPLICATION_TAG_TIME) + apdu_len += encode_tagged_time(&apdu[apdu_len], + data->value.type.Time.hour, + data->value.type.Time.min, + data->value.type.Time.sec, + data->value.type.Time.hundredths); + else if (data->value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) + apdu_len += encode_tagged_object_id(&apdu[apdu_len], + data->value.type.Object_ID.type,data->value.type.Object_ID.instance); apdu_len += encode_closing_tag(&apdu[apdu_len], 3); // optional priority - 0 if not set, 1..16 if set if (data->priority) @@ -91,6 +118,10 @@ int wp_decode_service_request( int type = 0; // for decoding int property = 0; // for decoding unsigned unsigned_value = 0; + int hour, min, sec, hundredths; + int year, month, day, wday; + int object_type = 0; + uint32_t instance = 0; // check for value pointers if (apdu_len && data) @@ -121,20 +152,99 @@ int wp_decode_service_request( else data->array_index = BACNET_ARRAY_ALL; // Tag 3: opening context tag */ - if (decode_is_opening_tag_number(&apdu[len], 3)) + if (!decode_is_opening_tag_number(&apdu[len], 3)) + return -1; + // a tag number of 3 is not extended so only one octet + len++; + tag_len = decode_tag_number_and_value(&apdu[len], + &tag_number, &len_value_type); + if (tag_len) { - // a tag number of 3 is not extended so only one octet - len++; - // don't decode the property value here - data->property_value = &apdu[len]; - data->property_value_len = apdu_len - len; + len += tag_len; + if (tag_number == BACNET_APPLICATION_TAG_NULL) + { + data->value.tag = tag_number; + } + else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN) + { + data->value.tag = tag_number; + data->value.type.Boolean = decode_boolean(len_value_type); + } + else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) + { + data->value.tag = tag_number; + len += decode_unsigned(&apdu[len], + len_value_type, + &data->value.type.Unsigned_Int); + } + else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) + { + data->value.tag = tag_number; + len += decode_unsigned(&apdu[len], + len_value_type, + &data->value.type.Signed_Int); + } + else if (tag_number == BACNET_APPLICATION_TAG_REAL) + { + data->value.tag = tag_number; + len += decode_real(&apdu[len],&(data->value.type.Real)); + } + else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED) + { + data->value.tag = tag_number; + len += decode_enumerated(&apdu[len], + len_value_type, + &data->value.type.Enumerated); + } + else if (tag_number == BACNET_APPLICATION_TAG_DATE) + { + data->value.tag = tag_number; + len += decode_date(&apdu[len], &year, &month, &day, &wday); + data->value.type.Date.year = year; + data->value.type.Date.month = month; + data->value.type.Date.day = day; + data->value.type.Date.wday = wday; + } + else if (tag_number == BACNET_APPLICATION_TAG_TIME) + { + data->value.tag = tag_number; + len += decode_bacnet_time(&apdu[len], &hour, &min, &sec, &hundredths); + data->value.type.Time.hour = hour; + data->value.type.Time.min = min; + data->value.type.Time.sec = sec; + data->value.type.Time.hundredths = hundredths; + } + else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) + { + data->value.tag = tag_number; + len += decode_object_id(&apdu[tag_len], + &object_type, + &instance); + data->value.type.Object_ID.type = object_type; + data->value.type.Object_ID.instance = instance; + } + else + return -1; } else return -1; + if (!decode_is_closing_tag_number(&apdu[len], 3)) + return -1; + // a tag number of 3 is not extended so only one octet + len++; // Tag 4: optional Priority - // FIXME: if the property value is not easily sized here, - // then just have the application decode the property value - // and the priority + data->priority = BACNET_MAX_PRIORITIES; + if (len < apdu_len) + { + tag_len = decode_tag_number_and_value(&apdu[len], + &tag_number, &len_value_type); + if (tag_number == 4) + { + len += tag_len; + len = decode_unsigned(&apdu[len], len_value_type, &unsigned_value); + data->priority = unsigned_value; + } + } } return len; diff --git a/bacnet-stack/wp.h b/bacnet-stack/wp.h index c68e604e..799ff0c5 100644 --- a/bacnet-stack/wp.h +++ b/bacnet-stack/wp.h @@ -41,7 +41,7 @@ typedef struct BACnet_Write_Property_Value { uint8_t tag; - union tag_value + union { // NULL - not needed as it is encoded in the tag alone bool Boolean; @@ -57,8 +57,13 @@ typedef struct BACnet_Write_Property_Value unsigned int Enumerated; BACNET_DATE Date; BACNET_TIME Time; + struct + { + uint16_t type; + uint32_t instance; + } Object_ID; uint32_t Object_Identifier; - } + } type; } BACNET_WRITE_PROPERTY_VALUE; typedef struct BACnet_Write_Property_Data @@ -67,8 +72,7 @@ typedef struct BACnet_Write_Property_Data uint32_t object_instance; BACNET_PROPERTY_ID object_property; int32_t array_index; // use BACNET_ARRAY_ALL when not setting - uint8_t *property_value; - int property_value_len; + BACNET_WRITE_PROPERTY_VALUE value; uint8_t priority; // use 0 if not setting the priority } BACNET_WRITE_PROPERTY_DATA;