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