Added BACnet application encoding and decoding for bit strings.

Added BACnet text for month_name, week_of_month, day_of_week, event_state, binary_present_value, reliability, device_status, and segmentation.
Added BACnet application handling for printing the property value to a stream.
This commit is contained in:
skarg
2006-02-09 17:28:03 +00:00
parent 5e6ef04cf8
commit ce18b3a55d
4 changed files with 338 additions and 66 deletions
+159 -54
View File
@@ -36,10 +36,12 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include "bacenum.h" #include "bacenum.h"
#include "bacdcode.h" #include "bacdcode.h"
#include "bacdef.h" #include "bacdef.h"
#include "bacapp.h" #include "bacapp.h"
#include "bactext.h"
int bacapp_encode_application_data( int bacapp_encode_application_data(
uint8_t *apdu, uint8_t *apdu,
@@ -68,14 +70,18 @@ int bacapp_encode_application_data(
apdu_len += encode_tagged_double(&apdu[apdu_len], apdu_len += encode_tagged_double(&apdu[apdu_len],
value->type.Double); value->type.Double);
#endif #endif
else if (value->tag == BACNET_APPLICATION_TAG_CHARACTER_STRING)
apdu_len += encode_tagged_character_string(
&apdu[apdu_len],
&value->type.Character_String);
else if (value->tag == BACNET_APPLICATION_TAG_OCTET_STRING) else if (value->tag == BACNET_APPLICATION_TAG_OCTET_STRING)
apdu_len += encode_tagged_octet_string( apdu_len += encode_tagged_octet_string(
&apdu[apdu_len], &apdu[apdu_len],
&value->type.Octet_String); &value->type.Octet_String);
else if (value->tag == BACNET_APPLICATION_TAG_CHARACTER_STRING)
apdu_len += encode_tagged_character_string(
&apdu[apdu_len],
&value->type.Character_String);
else if (value->tag == BACNET_APPLICATION_TAG_BIT_STRING)
apdu_len += encode_tagged_bitstring(
&apdu[apdu_len],
&value->type.Bit_String);
else if (value->tag == BACNET_APPLICATION_TAG_ENUMERATED) else if (value->tag == BACNET_APPLICATION_TAG_ENUMERATED)
apdu_len += encode_tagged_enumerated(&apdu[apdu_len], apdu_len += encode_tagged_enumerated(&apdu[apdu_len],
value->type.Enumerated); value->type.Enumerated);
@@ -122,65 +128,45 @@ int bacapp_decode_application_data(
if (tag_len) if (tag_len)
{ {
len += tag_len; len += tag_len;
value->tag = tag_number;
if (tag_number == BACNET_APPLICATION_TAG_NULL) if (tag_number == BACNET_APPLICATION_TAG_NULL)
{ {
value->tag = tag_number; /* nothing else to do */
} }
else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN) else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN)
{
value->tag = tag_number;
value->type.Boolean = decode_boolean(len_value_type); value->type.Boolean = decode_boolean(len_value_type);
}
else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT)
{
value->tag = tag_number;
len += decode_unsigned(&apdu[len], len += decode_unsigned(&apdu[len],
len_value_type, len_value_type,
&value->type.Unsigned_Int); &value->type.Unsigned_Int);
}
else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT)
{
value->tag = tag_number;
len += decode_signed(&apdu[len], len += decode_signed(&apdu[len],
len_value_type, len_value_type,
&value->type.Signed_Int); &value->type.Signed_Int);
}
else if (tag_number == BACNET_APPLICATION_TAG_REAL) else if (tag_number == BACNET_APPLICATION_TAG_REAL)
{
value->tag = tag_number;
len += decode_real(&apdu[len],&(value->type.Real)); len += decode_real(&apdu[len],&(value->type.Real));
}
#if 0 #if 0
else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE) else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE)
{
value->tag = tag_number;
len += decode_double(&apdu[len],&(value->type.Double)); len += decode_double(&apdu[len],&(value->type.Double));
}
#endif #endif
else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING)
{
value->tag = tag_number;
len += decode_character_string(&apdu[len],
len_value_type,
&value->type.Character_String);
}
else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING) else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING)
{
value->tag = tag_number;
len += decode_octet_string(&apdu[len], len += decode_octet_string(&apdu[len],
len_value_type, len_value_type,
&value->type.Octet_String); &value->type.Octet_String);
} else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING)
len += decode_character_string(&apdu[len],
len_value_type,
&value->type.Character_String);
else if (tag_number == BACNET_APPLICATION_TAG_BIT_STRING)
len += decode_bitstring(&apdu[len],
len_value_type,
&value->type.Bit_String);
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED) else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
{
value->tag = tag_number;
len += decode_enumerated(&apdu[len], len += decode_enumerated(&apdu[len],
len_value_type, len_value_type,
&value->type.Enumerated); &value->type.Enumerated);
}
else if (tag_number == BACNET_APPLICATION_TAG_DATE) else if (tag_number == BACNET_APPLICATION_TAG_DATE)
{ {
value->tag = tag_number;
len += decode_date(&apdu[len], &year, &month, &day, &wday); len += decode_date(&apdu[len], &year, &month, &day, &wday);
value->type.Date.year = year; value->type.Date.year = year;
value->type.Date.month = month; value->type.Date.month = month;
@@ -189,7 +175,6 @@ int bacapp_decode_application_data(
} }
else if (tag_number == BACNET_APPLICATION_TAG_TIME) else if (tag_number == BACNET_APPLICATION_TAG_TIME)
{ {
value->tag = tag_number;
len += decode_bacnet_time(&apdu[len], &hour, &min, &sec, &hundredths); len += decode_bacnet_time(&apdu[len], &hour, &min, &sec, &hundredths);
value->type.Time.hour = hour; value->type.Time.hour = hour;
value->type.Time.min = min; value->type.Time.min = min;
@@ -198,7 +183,6 @@ int bacapp_decode_application_data(
} }
else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID)
{ {
value->tag = tag_number;
len += decode_object_id(&apdu[len], len += decode_object_id(&apdu[len],
&object_type, &object_type,
&instance); &instance);
@@ -258,16 +242,17 @@ bool bacapp_copy(
dest_value->type.Object_Id.type = src_value->type.Object_Id.type; dest_value->type.Object_Id.type = src_value->type.Object_Id.type;
dest_value->type.Object_Id.instance = src_value->type.Object_Id.instance; dest_value->type.Object_Id.instance = src_value->type.Object_Id.instance;
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
characterstring_copy(
&dest_value->type.Character_String,
&src_value->type.Character_String);
break;
case BACNET_APPLICATION_TAG_OCTET_STRING: case BACNET_APPLICATION_TAG_OCTET_STRING:
octetstring_copy( octetstring_copy(
&dest_value->type.Octet_String, &dest_value->type.Octet_String,
&src_value->type.Octet_String); &src_value->type.Octet_String);
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
characterstring_copy(
&dest_value->type.Character_String,
&src_value->type.Character_String);
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
default: default:
status = false; status = false;
break; break;
@@ -344,27 +329,147 @@ bool bacapp_compare(
status = false; status = false;
break; break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING: case BACNET_APPLICATION_TAG_CHARACTER_STRING:
status = !characterstring_same(
&value->type.Character_String,
&test_value->type.Character_String);
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
default:
status = false;
break;
}
}
return status;
}
bool bacapp_print_value(
FILE *stream,
BACNET_APPLICATION_DATA_VALUE *value,
BACNET_PROPERTY_ID property)
{
bool status = true; /*return value*/
size_t len = 0, i = 0;
char *char_str;
uint8_t *octet_str;
if (value)
{
switch (value->tag)
{
case BACNET_APPLICATION_TAG_NULL:
fprintf(stream,"Null");
break;
case BACNET_APPLICATION_TAG_BOOLEAN:
fprintf(stream,"%s",value->type.Boolean?"TRUE":"FALSE");
break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
fprintf(stream,"%u",value->type.Unsigned_Int);
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
fprintf(stream,"%d",value->type.Signed_Int);
break;
case BACNET_APPLICATION_TAG_REAL:
fprintf(stream,"%f",(double)value->type.Real);
break;
case BACNET_APPLICATION_TAG_DOUBLE:
fprintf(stream,"%f",value->type.Double);
break;
case BACNET_APPLICATION_TAG_ENUMERATED:
switch (property)
{ {
size_t length, test_length, i; case PROP_OBJECT_TYPE:
char *str,*test_str; fprintf(stream,"%s",
length = characterstring_length(&value->type.Character_String); bactext_object_type_name(value->type.Enumerated));
str = characterstring_value(&value->type.Character_String); break;
test_length = characterstring_length(&test_value->type.Character_String); case PROP_EVENT_STATE:
test_str = characterstring_value(&test_value->type.Character_String); fprintf(stream,"%s",
if (length != test_length) bactext_event_state_name(value->type.Enumerated));
status = false; break;
for (i = 0; i < test_length; i++) case PROP_UNITS:
{ fprintf(stream,"%s",
if (str[i] != test_str[i]) bactext_engineering_unit_name(value->type.Enumerated));
status = false; break;
} case PROP_PRESENT_VALUE:
fprintf(stream,"%s",
bactext_binary_present_value_name(value->type.Enumerated));
break;
case PROP_RELIABILITY:
fprintf(stream,"%s",
bactext_reliability_name(value->type.Enumerated));
break;
case PROP_SYSTEM_STATUS:
fprintf(stream,"%s",
bactext_device_status_name(value->type.Enumerated));
break;
case PROP_SEGMENTATION_SUPPORTED:
fprintf(stream,"%s",
bactext_segmentation_name(value->type.Enumerated));
break;
default:
fprintf(stream,"%u",value->type.Enumerated);
break;
} }
break; break;
case BACNET_APPLICATION_TAG_DATE:
fprintf(stream,"%s, %s %u, %u",
bactext_day_of_week_name(value->type.Date.wday),
bactext_month_name(value->type.Date.month),
(unsigned)value->type.Date.day,
(unsigned)value->type.Date.year);
break;
case BACNET_APPLICATION_TAG_TIME:
fprintf(stream,"%02u:%02u:%02u.%03u",
(unsigned)value->type.Time.hour,
(unsigned)value->type.Time.min,
(unsigned)value->type.Time.sec,
(unsigned)value->type.Time.hundredths);
break;
case BACNET_APPLICATION_TAG_OBJECT_ID:
fprintf(stream,"%s %u",
bactext_object_type_name(value->type.Object_Id.type),
value->type.Object_Id.instance);
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
len = octetstring_length(&value->type.Octet_String);
octet_str = octetstring_value(&value->type.Octet_String);
for (i = 0; i < len; i++)
{
fprintf(stream,"%02X",*octet_str);
octet_str++;
}
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len = characterstring_length(&value->type.Character_String);
char_str = characterstring_value(&value->type.Character_String);
fprintf(stream,"\"");
for (i = 0; i < len; i++)
{
if (isprint(*char_str))
fprintf(stream,"%c",*char_str);
else
fprintf(stream,".",*char_str);
char_str++;
}
fprintf(stream,"\"");
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
len = bitstring_bits_used(&value->type.Bit_String);
fprintf(stream,"{");
for (i = 0; i < len; i++)
{
fprintf(stream,"%s",
bitstring_bit(&value->type.Bit_String,i)?"true":"false");
if (i < len-1)
fprintf(stream,",");
}
fprintf(stream,"}");
break;
default: default:
status = false; status = false;
break; break;
} }
} }
return status; return status;
} }
+6
View File
@@ -36,6 +36,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
#include "bacdef.h" #include "bacdef.h"
#include "bacstr.h" #include "bacstr.h"
@@ -86,6 +87,11 @@ bool bacapp_parse_application_data(
const char *argv, const char *argv,
BACNET_APPLICATION_DATA_VALUE *value); BACNET_APPLICATION_DATA_VALUE *value);
bool bacapp_print_value(
FILE *stream,
BACNET_APPLICATION_DATA_VALUE *value,
BACNET_PROPERTY_ID property);
#ifdef TEST #ifdef TEST
#include "ctest.h" #include "ctest.h"
void testBACnetApplicationData(Test * pTest); void testBACnetApplicationData(Test * pTest);
+151
View File
@@ -701,3 +701,154 @@ const char *bactext_error_code_name(int index)
Vendor_Proprietary_String); Vendor_Proprietary_String);
} }
INDTEXT_DATA bacnet_month_names[] = {
{1, "January"},
{2, "February"},
{3, "March"},
{4, "April"},
{5, "May"},
{6, "June"},
{7, "July"},
{8, "August"},
{9, "September"},
{10, "October"},
{11, "November"},
{12, "December"},
{255,"Any Month"},
{0,NULL}
};
const char *bactext_month_name(int index)
{
return indtext_by_index_default(
bacnet_month_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_week_of_month_names[] = {
{1, "days numbered 1-7"},
{2, "days numbered 8-14"},
{3, "days numbered 15-21"},
{4, "days numbered 22-28"},
{5, "days numbered 29-31"},
{6, "last 7 days of this month"},
{255, "any week of this month"},
{0,NULL}
};
const char *bactext_week_of_month_name(int index)
{
return indtext_by_index_default(
bacnet_week_of_month_names,
index,
ASHRAE_Reserved_String);
}
/* note: different than DaysOfWeek bit string where 0=monday */
INDTEXT_DATA bacnet_day_of_week_names[] = {
{1, "Monday"},
{2, "Tuesday"},
{3, "Wednesday"},
{4, "Thursday"},
{5, "Friday"},
{6, "Saturday"},
{7, "Sunday"},
{255, "any day of week"},
{0,NULL}
};
const char *bactext_day_of_week_name(int index)
{
return indtext_by_index_default(
bacnet_day_of_week_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_event_state_names[] = {
{EVENT_STATE_NORMAL, "normal"},
{EVENT_STATE_FAULT, "fault"},
{EVENT_STATE_OFFNORMAL, "offnormal"},
{EVENT_STATE_HIGH_LIMIT, "high limit"},
{EVENT_STATE_LOW_LIMIT, "low limit"},
{0,NULL}
};
const char *bactext_event_state_name(int index)
{
return indtext_by_index_default(
bacnet_event_state_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_binary_present_value_names[] = {
{BINARY_INACTIVE,"inactive"},
{BINARY_ACTIVE,"active"},
{0,NULL}
};
const char *bactext_binary_present_value_name(int index)
{
return indtext_by_index_default(
bacnet_binary_present_value_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_reliability_names[] = {
{RELIABILITY_NO_FAULT_DETECTED,"no-fault-detected"},
{RELIABILITY_NO_SENSOR,"no-sensor"},
{RELIABILITY_OVER_RANGE,"over-range"},
{RELIABILITY_UNDER_RANGE,"under-range"},
{RELIABILITY_OPEN_LOOP,"open-loop"},
{RELIABILITY_SHORTED_LOOP,"shorted-loop"},
{RELIABILITY_NO_OUTPUT,"no-output"},
{RELIABILITY_UNRELIABLE_OTHER,"unreliable-other"},
{RELIABILITY_PROCESS_ERROR,"process-error"},
{RELIABILITY_MULTI_STATE_FAULT,"mult-state-fault"},
{RELIABILITY_CONFIGURATION_ERROR,"configuration-error"},
{0,NULL}
};
const char *bactext_reliability_name(int index)
{
return indtext_by_index_default(
bacnet_reliability_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_device_status_names[] = {
{STATUS_OPERATIONAL,"operational"},
{STATUS_OPERATIONAL_READ_ONLY,"operational-read-only"},
{STATUS_DOWNLOAD_REQUIRED,"download-required"},
{STATUS_DOWNLOAD_IN_PROGRESS,"download-in-progress"},
{STATUS_NON_OPERATIONAL,"non-operational"},
{0,NULL}
};
const char *bactext_device_status_name(int index)
{
return indtext_by_index_default(
bacnet_device_status_names,
index,
ASHRAE_Reserved_String);
}
INDTEXT_DATA bacnet_segmentation_names[] = {
{SEGMENTATION_BOTH,"segmented-both"},
{SEGMENTATION_TRANSMIT,"segmented-transmit"},
{SEGMENTATION_RECEIVE,"segmented-receive"},
{SEGMENTATION_NONE,"no-segmentation"},
{0,NULL}
};
const char *bactext_segmentation_name(int index)
{
return indtext_by_index_default(
bacnet_segmentation_names,
index,
ASHRAE_Reserved_String);
}
+10
View File
@@ -53,6 +53,16 @@ const char *bactext_abort_reason_name(int index);
const char *bactext_error_class_name(int index); const char *bactext_error_class_name(int index);
const char *bactext_error_code_name(int index); const char *bactext_error_code_name(int index);
unsigned bactext_property_id(const char* name); unsigned bactext_property_id(const char* name);
const char *bactext_month_name(int index);
const char *bactext_week_of_month_name(int index);
const char *bactext_day_of_week_name(int index);
const char *bactext_event_state_name(int index);
const char *bactext_binary_present_value_name(int index);
const char *bactext_reliability_name(int index);
const char *bactext_device_status_name(int index);
const char *bactext_segmentation_name(int index);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */