Final fixes (I believe, for now) for EPICS generation.

Now has proper support for State Text and Subordinate Annotations text arrays, even very large ones.
Now has 3 ways, of descending throughput, for all Objects and all their properties:
a) Get all object properties with RPM for ALL
b) Get individual properties with RP for Array_Index = ALL
c) Walk through a too-large array one index step at a time.
This commit is contained in:
tbrennan3
2010-04-26 20:09:41 +00:00
parent 15c5375196
commit 1c8a58f158
+97 -36
View File
@@ -106,10 +106,15 @@ static int32_t Property_List[MAX_PROPS + 2];
static const int *pPropList = NULL; static const int *pPropList = NULL;
/* When we have to walk through an array of things, like ObjectIDs or /* When we have to walk through an array of things, like ObjectIDs or
* Subordinate_Annotations, one RP call at a time, use these for indexing. */ * Subordinate_Annotations, one RP call at a time, use these for indexing.
*/
static uint32_t Walked_List_Length = 0; static uint32_t Walked_List_Length = 0;
static uint32_t Walked_List_Index = 0; static uint32_t Walked_List_Index = 0;
/* TODO: Probably should have done this as additional EPICS_STATES */
static bool Using_Walked_List = false; static bool Using_Walked_List = false;
/* When requesting RP for BACNET_ARRAY_ALL of what we know can be a long
* array, then set this true in case it aborts and we need Using_Walked_List */
static bool IsLongArray = false;
static bool ShowValues = false; /* Show value instead of '?' */ static bool ShowValues = false; /* Show value instead of '?' */
@@ -127,7 +132,7 @@ static void MyErrorHandler(
(void) src; (void) src;
(void) invoke_id; (void) invoke_id;
#if PRINT_ERRORS #if PRINT_ERRORS
printf("BACnet Error: %s: %s\r\n", bactext_error_class_name(error_class), printf("-- BACnet Error: %s: %s\r\n", bactext_error_class_name(error_class),
bactext_error_code_name(error_code)); bactext_error_code_name(error_code));
#else #else
(void) error_class; (void) error_class;
@@ -148,8 +153,8 @@ void MyAbortHandler(
(void) server; (void) server;
#if PRINT_ERRORS #if PRINT_ERRORS
/* It is normal for this to fail, so don't print. */ /* It is normal for this to fail, so don't print. */
if ( myState != GET_ALL_RESPONSE ) if ( ( myState != GET_ALL_RESPONSE ) && !IsLongArray )
printf("BACnet Abort: %s\r\n", bactext_abort_reason_name(abort_reason)); printf("-- BACnet Abort: %s ", bactext_abort_reason_name(abort_reason));
#else #else
(void) abort_reason; (void) abort_reason;
#endif #endif
@@ -362,6 +367,7 @@ void PrintReadPropertyData(
BACNET_APPLICATION_DATA_VALUE *value, *old_value; BACNET_APPLICATION_DATA_VALUE *value, *old_value;
bool print_brace = false; bool print_brace = false;
KEY object_list_element; KEY object_list_element;
bool isSequence = false; /* Ie, will need bracketing braces {} */
if (rpm_property == NULL ) if (rpm_property == NULL )
{ {
@@ -405,8 +411,11 @@ void PrintReadPropertyData(
{ {
switch( rpm_property->propertyIdentifier ) switch( rpm_property->propertyIdentifier )
{ {
/* These are all arrays, so they open and close with braces */
case PROP_OBJECT_LIST: case PROP_OBJECT_LIST:
case PROP_STATE_TEXT:
case PROP_STRUCTURED_OBJECT_LIST: case PROP_STRUCTURED_OBJECT_LIST:
case PROP_SUBORDINATE_ANNOTATIONS:
case PROP_SUBORDINATE_LIST: case PROP_SUBORDINATE_LIST:
if ( Using_Walked_List ) if ( Using_Walked_List )
{ {
@@ -423,21 +432,30 @@ void PrintReadPropertyData(
assert( Walked_List_Index == rpm_property->propertyArrayIndex); assert( Walked_List_Index == rpm_property->propertyArrayIndex);
} }
else else
{
Walked_List_Index++; Walked_List_Index++;
/* If we got the whole Object List array in one RP call, keep
* the Index and List_Length in sync as we cycle through. */
if ( rpm_property->propertyIdentifier == PROP_OBJECT_LIST)
Object_List_Length = ++Object_List_Index;
}
if ( Walked_List_Index == 1 ) if ( Walked_List_Index == 1 )
{ {
/* Open the list of Objects (opening brace may be already printed) */ /* Open this Array of Objects for the first entry (unless
* opening brace has already printed, since this is an array
* of values[] ) */
if( value->next == NULL ) if( value->next == NULL )
fprintf(stdout, "{ \r\n "); fprintf(stdout, "{ \r\n ");
else else
fprintf(stdout, "\r\n "); fprintf(stdout, "\r\n ");
} }
if ( value->tag != BACNET_APPLICATION_TAG_OBJECT_ID ) {
assert( false ); /* Something not right here */ if ( rpm_property->propertyIdentifier == PROP_OBJECT_LIST)
break;
}
else if ( rpm_property->propertyIdentifier == PROP_OBJECT_LIST)
{ {
if ( value->tag != BACNET_APPLICATION_TAG_OBJECT_ID ) {
assert( false ); /* Something not right here */
break;
}
/* Store the object list so we can interrogate /* Store the object list so we can interrogate
each object. */ each object. */
object_list_element = object_list_element =
@@ -447,16 +465,42 @@ void PrintReadPropertyData(
* yet, so just leave it null. The key is Key here. */ * yet, so just leave it null. The key is Key here. */
Keylist_Data_Add( Object_List, object_list_element, NULL ); Keylist_Data_Add( Object_List, object_list_element, NULL );
} }
else if ( rpm_property->propertyIdentifier == PROP_STATE_TEXT )
{
/* Make sure it fits within 31 chars for original VTS3 limitation.
* If longer, take first 15 dash, and last 15 chars. */
if ( value->type.Character_String.length > 31 )
{
int iLast15idx = value->type.Character_String.length - 15;
value->type.Character_String.value[15] = '-';
memcpy( &value->type.Character_String.value[16],
&value->type.Character_String.value[iLast15idx], 15 );
value->type.Character_String.value[31] = 0;
value->type.Character_String.length = 31;
}
}
else if ( rpm_property->propertyIdentifier == PROP_SUBORDINATE_LIST) else if ( rpm_property->propertyIdentifier == PROP_SUBORDINATE_LIST)
{ {
if ( value->tag != BACNET_APPLICATION_TAG_OBJECT_ID ) {
assert( false ); /* Something not right here */
break;
}
/* TODO: handle Sequence of { Device ObjID, Object ID }, */ /* TODO: handle Sequence of { Device ObjID, Object ID }, */
isSequence = true;
} }
/* If the object is a Sequence, it needs its own bracketing braces */
if ( isSequence )
fprintf(stdout, "{");
bacapp_print_value(stdout, value, rpm_property->propertyIdentifier ); bacapp_print_value(stdout, value, rpm_property->propertyIdentifier );
if ( isSequence )
fprintf(stdout, "}");
if ( ( Walked_List_Index < Walked_List_Length ) || if ( ( Walked_List_Index < Walked_List_Length ) ||
( value->next != NULL ) ) ( value->next != NULL ) )
{ {
/* There are more. */ /* There are more. */
fprintf(stdout, ","); fprintf(stdout, ", ");
if (!(Walked_List_Index % 4)) if (!(Walked_List_Index % 4))
fprintf(stdout, "\r\n "); fprintf(stdout, "\r\n ");
} else { } else {
@@ -557,27 +601,37 @@ static uint8_t Read_Properties(
if ( (pPropList != NULL ) && ( pPropList[Property_List_Index] != -1) ) if ( (pPropList != NULL ) && ( pPropList[Property_List_Index] != -1) )
{ {
int prop = pPropList[Property_List_Index]; int prop = pPropList[Property_List_Index];
int32_t array_index;
IsLongArray = false;
if ( Using_Walked_List ) if ( Using_Walked_List )
{ {
if (Walked_List_Length == 0) { if (Walked_List_Length == 0) {
printf(" %s: ", bactext_property_name( prop ) ); // printf(" %s: ", bactext_property_name( prop ) );
invoke_id = array_index = 0;
Send_Read_Property_Request(device_instance,
pMyObject->type, pMyObject->instance,
prop, 0);
} else { } else {
invoke_id = array_index = Walked_List_Index;
Send_Read_Property_Request(device_instance,
pMyObject->type, pMyObject->instance,
prop, Walked_List_Index);
} }
} else { } else {
printf(" %s: ", bactext_property_name( prop ) ); printf(" %s: ", bactext_property_name( prop ) );
invoke_id = array_index = BACNET_ARRAY_ALL;
Send_Read_Property_Request(device_instance,
pMyObject->type, pMyObject->instance, switch( prop )
prop, BACNET_ARRAY_ALL); {
/* These are all potentially long arrays, so they may abort */
case PROP_OBJECT_LIST:
case PROP_STATE_TEXT:
case PROP_STRUCTURED_OBJECT_LIST:
case PROP_SUBORDINATE_ANNOTATIONS:
case PROP_SUBORDINATE_LIST:
IsLongArray = true;
break;
}
} }
invoke_id =
Send_Read_Property_Request(device_instance,
pMyObject->type, pMyObject->instance,
prop, array_index );
} }
return invoke_id; return invoke_id;
@@ -956,24 +1010,31 @@ int main(
} }
else else
Property_List_Index++; Property_List_Index++;
if ( pPropList[Property_List_Index] == PROP_OBJECT_LIST ) // if ( pPropList[Property_List_Index] == PROP_OBJECT_LIST )
{ // {
if ( !Using_Walked_List ) /* Just switched */ // if ( !Using_Walked_List ) /* Just switched */
{ // {
Using_Walked_List = true; // Using_Walked_List = true;
Walked_List_Index = Walked_List_Length = 0; // Walked_List_Index = Walked_List_Length = 0;
} // }
} // }
myState = GET_PROPERTY_REQUEST; /* Go fetch next Property */ myState = GET_PROPERTY_REQUEST; /* Go fetch next Property */
} }
else if (tsm_invoke_id_free(invoke_id)) { else if (tsm_invoke_id_free(invoke_id)) {
invoke_id = 0; invoke_id = 0;
if (Error_Detected) if (Error_Detected)
{ {
/* OK, skip this one and try the next property. */ if ( IsLongArray ) {
fprintf( stdout, " -- Failed to get %s \r\n", /* Change to using a Walked List and retry this property */
bactext_property_name(pPropList[Property_List_Index]) ); Using_Walked_List = true;
Property_List_Index++; Walked_List_Index = Walked_List_Length = 0;
}
else {
/* OK, skip this one and try the next property. */
fprintf( stdout, " -- Failed to get %s \r\n",
bactext_property_name(pPropList[Property_List_Index]) );
Property_List_Index++;
}
} }
myState = GET_PROPERTY_REQUEST; myState = GET_PROPERTY_REQUEST;
} else if (tsm_invoke_id_failed(invoke_id)) { } else if (tsm_invoke_id_failed(invoke_id)) {