diff --git a/bacnet-stack/include/rp.h b/bacnet-stack/include/rp.h index ea9f006b..2c583291 100644 --- a/bacnet-stack/include/rp.h +++ b/bacnet-stack/include/rp.h @@ -62,6 +62,16 @@ extern "C" { unsigned apdu_len, BACNET_READ_PROPERTY_DATA * rpdata); + /* method to encode the ack without extra buffer */ + int rp_ack_encode_apdu_init( + uint8_t * apdu, + uint8_t invoke_id, + BACNET_READ_PROPERTY_DATA * rpdata); + + int rp_ack_encode_apdu_object_property_end( + uint8_t * apdu); + + /* method to encode the ack using extra buffer */ int rp_ack_encode_apdu( uint8_t * apdu, uint8_t invoke_id, diff --git a/bacnet-stack/ports/atmega168/h_rp.c b/bacnet-stack/ports/atmega168/h_rp.c index e9dc533c..d9910b1b 100644 --- a/bacnet-stack/ports/atmega168/h_rp.c +++ b/bacnet-stack/ports/atmega168/h_rp.c @@ -45,8 +45,6 @@ #include "bv.h" #endif -static uint8_t Temp_Buf[MAX_APDU] = { 0 }; - /* Encodes the property APDU and returns the length, or sets the error, and returns -1 */ int Encode_Property_APDU( @@ -97,6 +95,7 @@ void handler_read_property( { BACNET_READ_PROPERTY_DATA data; int len = 0; + int ack_len = 0; int pdu_len = 0; BACNET_NPDU_DATA npdu_data; bool error = false; @@ -126,18 +125,19 @@ void handler_read_property( } else { /* most cases will be error */ error = true; - len = - Encode_Property_APDU(&Temp_Buf[0], data.object_type, + ack_len = rp_ack_encode_apdu_init( + &Handler_Transmit_Buffer[pdu_len], + service_data->invoke_id, &data); + /* FIXME: add buffer len as passed into function or use smart buffer */ + len = Encode_Property_APDU( + &Handler_Transmit_Buffer[pdu_len + ack_len], data.object_type, data.object_instance, data.object_property, data.array_index, &error_class, &error_code); if (len >= 0) { - /* encode the APDU portion of the packet */ - data.application_data = &Temp_Buf[0]; - data.application_data_len = len; - /* FIXME: probably need a length limitation sent with encode */ - len = - rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len], - service_data->invoke_id, &data); + pdu_len = pdu_len + len + ack_len; + len = rp_ack_encode_apdu_object_property_end( + &Handler_Transmit_Buffer[pdu_len]); + pdu_len += len; error = false; } } diff --git a/bacnet-stack/src/rp.c b/bacnet-stack/src/rp.c index 8e0a8ce9..6aa36ecf 100644 --- a/bacnet-stack/src/rp.c +++ b/bacnet-stack/src/rp.c @@ -118,6 +118,52 @@ int rp_decode_service_request( return (int) len; } +/* alternate method to encode the ack without extra buffer */ +int rp_ack_encode_apdu_init( + uint8_t * apdu, + uint8_t invoke_id, + BACNET_READ_PROPERTY_DATA * rpdata) +{ + int len = 0; /* length of each encoding */ + int apdu_len = 0; /* total length of the apdu, return value */ + + if (apdu) { + apdu[0] = PDU_TYPE_COMPLEX_ACK; /* complex ACK service */ + apdu[1] = invoke_id; /* original invoke id from request */ + apdu[2] = SERVICE_CONFIRMED_READ_PROPERTY; /* service choice */ + apdu_len = 3; + /* service ack follows */ + apdu_len += + encode_context_object_id(&apdu[apdu_len], 0, + rpdata->object_type, rpdata->object_instance); + apdu_len += + encode_context_enumerated(&apdu[apdu_len], 1, + rpdata->object_property); + /* context 2 array index is optional */ + if (rpdata->array_index != BACNET_ARRAY_ALL) { + apdu_len += + encode_context_unsigned(&apdu[apdu_len], 2, + rpdata->array_index); + } + apdu_len += encode_opening_tag(&apdu[apdu_len], 3); + } + + return apdu_len; +} + +/* note: encode the application tagged data yourself */ +int rp_ack_encode_apdu_object_property_end( + uint8_t * apdu) +{ + int apdu_len = 0; /* total length of the apdu, return value */ + + if (apdu) { + apdu_len = encode_closing_tag(&apdu[0], 3); + } + + return apdu_len; +} + int rp_ack_encode_apdu( uint8_t * apdu, uint8_t invoke_id,