Implemented ReadRange functionality for the device "Device Address Binding" property and modified the ReadRange test app to use this real property for its target.

Implemented a framework for allowing the ReadRange handler determine which properties support ReadRange and which varients of ReadRange they support.
This commit is contained in:
petermcs
2009-11-10 15:37:11 +00:00
parent eb370fa972
commit b8251f314f
12 changed files with 499 additions and 147 deletions
+43 -20
View File
@@ -39,6 +39,16 @@
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
static rr_info_function get_rr_info[MAX_BACNET_OBJECT_TYPE];
void handler_rr_object_set(
BACNET_OBJECT_TYPE object_type,
rr_info_function pFunction1)
{
if (object_type < MAX_BACNET_OBJECT_TYPE)
get_rr_info[object_type] = pFunction1;
}
/* Encodes the property APDU and returns the length,
or sets the error, and returns -1 */
int Encode_RR_payload(
@@ -48,26 +58,39 @@ int Encode_RR_payload(
BACNET_ERROR_CODE * error_code)
{
int apdu_len = -1;
rr_info_function info_fn_ptr = NULL;
rr_handler_function rr_fn_ptr = NULL;
RR_PROP_INFO PropInfo;
/* FIXME: Stub function at the moment which just returns something
* for the sake of testing things out. Need to look at existing objects
* and see how we can do this for real.
*/
pRequest->ItemCount = 6;
bitstring_init(&pRequest->ResultFlags);
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_FIRST_ITEM, true);
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_LAST_ITEM, true);
bitstring_set_bit(&pRequest->ResultFlags, RESULT_FLAG_MORE_ITEMS, false);
pRequest->FirstSequence = 0;
apdu_len = 0;
apdu_len += encode_application_unsigned(&apdu[apdu_len], 1);
apdu_len += encode_application_unsigned(&apdu[apdu_len], 2);
apdu_len += encode_application_unsigned(&apdu[apdu_len], 3);
apdu_len += encode_application_unsigned(&apdu[apdu_len], 4);
apdu_len += encode_application_unsigned(&apdu[apdu_len], 5);
apdu_len += encode_application_unsigned(&apdu[apdu_len], 6);
/* initialize the default return values */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
/* handle each object type */
if (pRequest->object_type < MAX_BACNET_OBJECT_TYPE)
info_fn_ptr = get_rr_info[pRequest->object_type];
if ((info_fn_ptr != NULL) && (info_fn_ptr(pRequest->object_instance, pRequest->object_property, &PropInfo, error_class, error_code) != false)) {
/* We try and do some of the more generic error checking here to cut down on duplication of effort */
if(((PropInfo.RequestTypes & RR_ARRAY_OF_LISTS) == 0) && (pRequest->array_index != 0)) {
/* Array access attempted on a non array property */
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
}
else if((pRequest->RequestType != RR_READ_ALL) && ((PropInfo.RequestTypes & pRequest->RequestType) == 0)) {
/* By Time or By Sequence not supported */
*error_code = ERROR_CODE_OTHER; /* I couldn't see anything more appropriate so... */
}
else if(pRequest->Count == 0) { /* Count cannot be zero */
*error_code = ERROR_CODE_OTHER; /* I couldn't see anything more appropriate so... */
}
else if(PropInfo.Handler != NULL) {
apdu_len = PropInfo.Handler(apdu, pRequest, error_class, error_code);
}
} else {
/* Either we don't support RR for this property yet or it is not a list or array of lists */
*error_code = ERROR_CODE_PROPERTY_IS_NOT_A_LIST;
}
return apdu_len;
}
@@ -151,7 +174,7 @@ void handler_read_range(
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
service_data->invoke_id, SERVICE_CONFIRMED_READ_RANGE,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "RR: Sending Error!\n");
+40
View File
@@ -870,6 +870,46 @@ void Device_Init(
{
}
bool DeviceGetRRInfo(
uint32_t Object, /* Which particular object - obviously not important for device object */
BACNET_PROPERTY_ID Property, /* Which property */
RR_PROP_INFO *pInfo, /* Where to put the information */
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_A_LIST;
switch(Property) {
case PROP_VT_CLASSES_SUPPORTED:
case PROP_ACTIVE_VT_SESSIONS:
case PROP_LIST_OF_SESSION_KEYS:
case PROP_TIME_SYNCHRONIZATION_RECIPIENTS:
case PROP_MANUAL_SLAVE_ADDRESS_BINDING:
case PROP_SLAVE_ADDRESS_BINDING:
case PROP_RESTART_NOTIFICATION_RECIPIENTS:
case PROP_UTC_TIME_SYNCHRONIZATION_RECIPIENTS:
pInfo->RequestTypes = RR_BY_POSITION;
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
case PROP_DEVICE_ADDRESS_BINDING:
pInfo->RequestTypes = RR_BY_POSITION;
pInfo->Handler = &rr_address_list_encode;
return(true);
break;
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
pInfo->RequestTypes = RR_BY_POSITION;
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
break;
}
return(false);
}
#ifdef TEST
#include <assert.h>
#include <string.h>
+137 -114
View File
@@ -143,7 +143,8 @@ static void Init_Object(
write_property_function wp_function,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function)
object_name_function name_function,
rr_info_function rr_inf_function)
{
handler_read_property_object_set(object_type, rp_function,
object_valid_function);
@@ -151,6 +152,7 @@ static void Init_Object(
handler_read_property_multiple_list_set(object_type, rpm_list_function);
Device_Object_Function_Set(object_type, count_function, index_function,
name_function);
handler_rr_object_set(object_type, rr_inf_function);
}
static void Init_Objects(
@@ -159,68 +161,68 @@ static void Init_Objects(
Device_Init();
Init_Object(OBJECT_DEVICE, Device_Property_Lists,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number,
Device_Write_Property, NULL, NULL, NULL);
Device_Write_Property, NULL, NULL, NULL, DeviceGetRRInfo);
Analog_Input_Init();
Init_Object(OBJECT_ANALOG_INPUT, Analog_Input_Property_Lists,
Analog_Input_Encode_Property_APDU, Analog_Input_Valid_Instance, NULL,
Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Name);
Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Name, NULL);
Analog_Output_Init();
Init_Object(OBJECT_ANALOG_OUTPUT, Analog_Output_Property_Lists,
Analog_Output_Encode_Property_APDU, Analog_Output_Valid_Instance,
Analog_Output_Write_Property, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Name);
Analog_Output_Index_To_Instance, Analog_Output_Name, NULL);
Analog_Value_Init();
Init_Object(OBJECT_ANALOG_VALUE, Analog_Value_Property_Lists,
Analog_Value_Encode_Property_APDU, Analog_Value_Valid_Instance,
Analog_Value_Write_Property, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Name);
Analog_Value_Index_To_Instance, Analog_Value_Name, NULL);
Binary_Input_Init();
Init_Object(OBJECT_BINARY_INPUT, Binary_Input_Property_Lists,
Binary_Input_Encode_Property_APDU, Binary_Input_Valid_Instance, NULL,
Binary_Input_Count, Binary_Input_Index_To_Instance, Binary_Input_Name);
Binary_Input_Count, Binary_Input_Index_To_Instance, Binary_Input_Name, NULL);
Binary_Output_Init();
Init_Object(OBJECT_BINARY_OUTPUT, Binary_Output_Property_Lists,
Binary_Output_Encode_Property_APDU, Binary_Output_Valid_Instance,
Binary_Output_Write_Property, Binary_Output_Count,
Binary_Output_Index_To_Instance, Binary_Output_Name);
Binary_Output_Index_To_Instance, Binary_Output_Name, NULL);
Binary_Value_Init();
Init_Object(OBJECT_BINARY_VALUE, Binary_Value_Property_Lists,
Binary_Value_Encode_Property_APDU, Binary_Value_Valid_Instance,
Binary_Value_Write_Property, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Name);
Binary_Value_Index_To_Instance, Binary_Value_Name, NULL);
Life_Safety_Point_Init();
Init_Object(OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Property_Lists,
Life_Safety_Point_Encode_Property_APDU,
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Write_Property,
Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Name);
Life_Safety_Point_Name, NULL);
Load_Control_Init();
Init_Object(OBJECT_LOAD_CONTROL, Load_Control_Property_Lists,
Load_Control_Encode_Property_APDU, Load_Control_Valid_Instance,
Load_Control_Write_Property, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Name);
Load_Control_Index_To_Instance, Load_Control_Name, NULL);
Multistate_Output_Init();
Init_Object(OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Property_Lists,
Multistate_Output_Encode_Property_APDU,
Multistate_Output_Valid_Instance, Multistate_Output_Write_Property,
Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Name);
Multistate_Output_Name, NULL);
#if defined(BACFILE)
bacfile_init();
Init_Object(OBJECT_FILE, BACfile_Property_Lists,
bacfile_encode_property_apdu, bacfile_valid_instance,
bacfile_write_property, bacfile_count, bacfile_index_to_instance,
bacfile_name);
bacfile_name, NULL);
#endif
}
@@ -405,123 +407,144 @@ int main(
if (found) {
if (invoke_id == 0) { /* Safe to send a new request */
switch (iCount) {
case 0:
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 20;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = 1;
break;
case 0: /* Pass - should read up to 1st 10 */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 1;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 1:
Request.RequestType = RR_BY_SEQUENCE;
Request.Range.RefSeqNum = 20;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = 2;
break;
case 1: /* Pass - should read entries 2 and 3 */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefSeqNum = 3;
Request.Count = -2;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 2:
Request.RequestType = RR_BY_TIME;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
case 2: /* Fail - By Time not supported */
Request.RequestType = RR_BY_TIME;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF;
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = 3;
break;
case 3:
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 20;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = BACNET_ARRAY_ALL;
break;
case 3: /* Fail - array not supported */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 1;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 1;
break;
case 4:
Request.RequestType = RR_BY_SEQUENCE;
Request.Range.RefSeqNum = 20;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = BACNET_ARRAY_ALL;
break;
case 4: /* Fail - By Sequence not supported */
Request.RequestType = RR_BY_SEQUENCE;
Request.Range.RefSeqNum = 1;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 5:
Request.RequestType = RR_BY_TIME;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
case 5: /* Fail Bytime not supported and array not supported */
Request.RequestType = RR_BY_TIME;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 1;
break;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = BACNET_ARRAY_ALL;
break;
case 6: /* Pass - should try to return all entries */
Request.RequestType = RR_READ_ALL;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 6:
Request.RequestType = RR_READ_ALL;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
case 7: /* Fail - array not supported */
Request.RequestType = RR_READ_ALL;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 1;
break;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = BACNET_ARRAY_ALL;
break;
case 8: /* Pass - should read 1st 1 */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 1;
Request.Count = 1;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 7:
Request.RequestType = RR_READ_ALL;
Request.Range.RefTime.date.year = 2009;
Request.Range.RefTime.date.month = 9;
Request.Range.RefTime.date.day = 23;
Request.Range.RefTime.date.wday = 0xFF; /* Day of week unspecified */
Request.Range.RefTime.time.hour = 22;
Request.Range.RefTime.time.min = 23;
Request.Range.RefTime.time.sec = 24;
Request.Range.RefTime.time.hundredths = 0;
case 9: /* Pass - should read 1st 2 */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 1;
Request.Count = 2;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
Request.Count = 30;
Request.object_type = OBJECT_ANALOG_INPUT;
Request.object_instance = 0;
Request.object_property = PROP_PRESENT_VALUE;
Request.array_index = 7;
break;
}
case 10: /* Pass - should read 2nd and 3rd */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 2;
Request.Count = 2;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
case 11: /* Pass - should read 2nd up to 11th */
Request.RequestType = RR_BY_POSITION;
Request.Range.RefIndex = 2;
Request.Count = 10;
Request.object_type = OBJECT_DEVICE;
Request.object_instance = Target_Device_Object_Instance;
Request.object_property = PROP_DEVICE_ADDRESS_BINDING;
Request.array_index = 0;
break;
}
invoke_id =
Send_ReadRange_Request(Target_Device_Object_Instance,
&Request);
} else if (tsm_invoke_id_free(invoke_id)) {
if (iCount != MY_MAX_BLOCK) {
if (iCount != 11) {
iCount++;
invoke_id = 0;
} else {