From 137f36a977adc3feaeff0a17bfe365474002df1b Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 5 Jan 2006 18:40:11 +0000 Subject: [PATCH] Modified the character strings encoding to intialize character strings with NULLs at the end. Changed device object demo to use ANSI X34 only. Fixed bug in WriteProperty for Device Object Name. --- bacnet-stack/bacdcode.c | 18 ------------ bacnet-stack/bacenum.h | 2 +- bacnet-stack/bacstr.c | 32 +++++++++++++-------- bacnet-stack/bacstr.h | 3 +- bacnet-stack/device.c | 62 +++++++++++++++++++++++++++-------------- 5 files changed, 64 insertions(+), 53 deletions(-) diff --git a/bacnet-stack/bacdcode.c b/bacnet-stack/bacdcode.c index 821140a9..b593e0b6 100644 --- a/bacnet-stack/bacdcode.c +++ b/bacnet-stack/bacdcode.c @@ -843,24 +843,6 @@ int decode_octet_string(uint8_t * apdu, uint32_t len_value, return len; } -// from clause 20.2.9 Encoding of a Character String Value -// returns the number of apdu bytes consumed -int encode_bacnet_string(uint8_t * apdu, const char *char_string, int len) -{ - int i; - - // limit - 6 octets is the most our tag and type could be - if (len > (MAX_APDU - 6)) - len = MAX_APDU - 6; - for (i = 0; i < len; i++) { - apdu[1 + i] = char_string[i]; - } - apdu[0] = CHARACTER_ANSI; - len++; - - return len; -} - // from clause 20.2.9 Encoding of a Character String Value // returns the number of apdu bytes consumed int encode_bacnet_character_string(uint8_t * apdu, diff --git a/bacnet-stack/bacenum.h b/bacnet-stack/bacenum.h index 1f266651..c100ba9c 100644 --- a/bacnet-stack/bacenum.h +++ b/bacnet-stack/bacenum.h @@ -729,7 +729,7 @@ typedef enum typedef enum { - CHARACTER_ANSI = 0, + CHARACTER_ANSI_X34 = 0, CHARACTER_MS_DBCS = 1, CHARACTER_JISC_6226 = 2, CHARACTER_UCS4 = 3, diff --git a/bacnet-stack/bacstr.c b/bacnet-stack/bacstr.c index bad1eb53..81d9cfc9 100644 --- a/bacnet-stack/bacstr.c +++ b/bacnet-stack/bacstr.c @@ -168,6 +168,7 @@ uint8_t bitstring_bits_capacity(BACNET_BIT_STRING *bit_string) return 0; } +#define CHARACTER_STRING_CAPACITY (MAX_CHARACTER_STRING_BYTES - 1) /* returns false if the string exceeds capacity initialize by using length=0 */ bool characterstring_init( @@ -183,19 +184,26 @@ bool characterstring_init( { char_string->length = 0; char_string->encoding = encoding; - if (length <= sizeof(char_string->value)) + /* save a byte at the end for NULL - + note: assumes printable characters */ + if (length <= CHARACTER_STRING_CAPACITY) { if (value) { - for (i = 0; i < length; i++) + for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++) { - char_string->value[char_string->length] = value[i]; - char_string->length++; + if (i < length) + { + char_string->value[char_string->length] = value[i]; + char_string->length++; + } + else + char_string->value[i] = 0; } } else { - for (i = 0; i < sizeof(char_string->value); i++) + for (i = 0; i < MAX_CHARACTER_STRING_BYTES; i++) { char_string->value[i] = 0; } @@ -208,12 +216,12 @@ bool characterstring_init( } bool characterstring_init_ansi( - BACNET_CHARACTER_STRING *char_string, - char *value) + BACNET_CHARACTER_STRING *char_string, + char *value) { return characterstring_init( char_string, - CHARACTER_ANSI, + CHARACTER_ANSI_X34, value, value?strlen(value):0); } @@ -228,7 +236,7 @@ bool characterstring_append( if (char_string) { - if ((length + char_string->length) <= sizeof(char_string->value)) + if ((length + char_string->length) <= CHARACTER_STRING_CAPACITY) { for (i = 0; i < length; i++) { @@ -253,7 +261,7 @@ bool characterstring_truncate( if (char_string) { - if (length <= sizeof(char_string->value)) + if (length <= CHARACTER_STRING_CAPACITY) { char_string->length = length; status = true; @@ -296,7 +304,7 @@ size_t characterstring_capacity(BACNET_CHARACTER_STRING *char_string) if (char_string) { - length = sizeof(char_string->value); + length = CHARACTER_STRING_CAPACITY; } return length; @@ -318,7 +326,7 @@ uint8_t characterstring_encoding(BACNET_CHARACTER_STRING *char_string) /* returns false if the string exceeds capacity initialize by using length=0 */ bool octetstring_init( - BACNET_OCTET_STRING *octet_string, + BACNET_OCTET_STRING *octet_string, uint8_t *value, size_t length) { diff --git a/bacnet-stack/bacstr.h b/bacnet-stack/bacstr.h index 9ae9951b..5ccd876d 100644 --- a/bacnet-stack/bacstr.h +++ b/bacnet-stack/bacstr.h @@ -48,12 +48,13 @@ typedef struct BACnet_Bit_String uint8_t value[MAX_BITSTRING_BYTES]; } BACNET_BIT_STRING; +#define MAX_CHARACTER_STRING_BYTES (MAX_APDU-6) typedef struct BACnet_Character_String { size_t length; uint8_t encoding; /* limit - 6 octets is the most our tag and type could be */ - char value[MAX_APDU-6]; + char value[MAX_CHARACTER_STRING_BYTES]; } BACNET_CHARACTER_STRING; /* FIXME: convert the bacdcode library to use BACNET_OCTET_STRING diff --git a/bacnet-stack/device.c b/bacnet-stack/device.c index 41050d9a..0165ac78 100644 --- a/bacnet-stack/device.c +++ b/bacnet-stack/device.c @@ -38,8 +38,6 @@ #endif static uint32_t Object_Instance_Number = 0; -// FIXME: it is likely that this name is configurable, -// so consider a fixed sized string static char Object_Name[16] = "SimpleServer"; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static char Vendor_Name[16] = "ASHRAE"; @@ -108,6 +106,25 @@ bool Device_Valid_Object_Instance_Number(uint32_t object_id) (object_id == BACNET_MAX_INSTANCE)); } +const char *Device_Object_Name(void) +{ + return Object_Name; +} + +bool Device_Set_Object_Name(const char *name, size_t length) +{ + bool status = false; /*return value*/ + + if (length < sizeof(Object_Name)) + { + memmove(Object_Name,name,length); + Object_Name[length] = 0; + status = true; + } + + return status; +} + BACNET_DEVICE_STATUS Device_System_Status(void) { return System_Status; @@ -385,43 +402,36 @@ int Device_Encode_Property_APDU( Object_Instance_Number); break; case PROP_OBJECT_NAME: - characterstring_init(&char_string,CHARACTER_ANSI, - Object_Name,strlen(Object_Name)); + characterstring_init_ansi(&char_string, Object_Name); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_OBJECT_TYPE: apdu_len = encode_tagged_enumerated(&apdu[0], OBJECT_DEVICE); break; case PROP_DESCRIPTION: - characterstring_init(&char_string,CHARACTER_ANSI, - Description,strlen(Description)); + characterstring_init_ansi(&char_string, Description); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_SYSTEM_STATUS: apdu_len = encode_tagged_enumerated(&apdu[0], System_Status); break; case PROP_VENDOR_NAME: - characterstring_init(&char_string,CHARACTER_ANSI, - Vendor_Name,strlen(Vendor_Name)); + characterstring_init_ansi(&char_string, Vendor_Name); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_VENDOR_IDENTIFIER: apdu_len = encode_tagged_unsigned(&apdu[0], Vendor_Identifier); break; case PROP_MODEL_NAME: - characterstring_init(&char_string,CHARACTER_ANSI, - Model_Name,strlen(Model_Name)); + characterstring_init_ansi(&char_string, Model_Name); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_FIRMWARE_REVISION: - characterstring_init(&char_string,CHARACTER_ANSI, - Firmware_Revision,strlen(Firmware_Revision)); + characterstring_init_ansi(&char_string, Firmware_Revision); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; case PROP_APPLICATION_SOFTWARE_VERSION: - characterstring_init(&char_string,CHARACTER_ANSI, - Application_Software_Version, - strlen(Application_Software_Version)); + characterstring_init_ansi(&char_string, Application_Software_Version); apdu_len = encode_tagged_character_string(&apdu[0], &char_string); break; // if you support time @@ -460,7 +470,7 @@ int Device_Encode_Property_APDU( // initialize all the services to not-supported bitstring_set_bit(&bit_string, (uint8_t)i, false); } - /* FIXME: set the services that YOUR device executes */ + /* FIXME: set only the services that YOUR device executes */ bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_WHO_IS, true); bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_I_AM, true); bitstring_set_bit(&bit_string, SERVICE_SUPPORTED_READ_PROPERTY, true); @@ -650,13 +660,23 @@ bool Device_Write_Property( case PROP_OBJECT_NAME: if (wp_data->value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { - status = Device_Set_Vendor_Name( - characterstring_value(&wp_data->value.type.Character_String), - characterstring_length(&wp_data->value.type.Character_String)); - if (!status) + uint8_t encoding; + encoding = characterstring_encoding(&wp_data->value.type.Character_String); + if (encoding == CHARACTER_ANSI_X34) + { + status = Device_Set_Object_Name( + characterstring_value(&wp_data->value.type.Character_String), + characterstring_length(&wp_data->value.type.Character_String)); + if (!status) + { + *error_class = ERROR_CLASS_PROPERTY; + *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; + } + } + else { *error_class = ERROR_CLASS_PROPERTY; - *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; + *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else