Device_Set_System_Status() now does some range checking (also has local flag to allow internal and external sources have different levels of control.

Simplified write property code using new validation helper functions in h_wp.c. Added location, description and model name to the writable properties.
This commit is contained in:
petermcs
2010-02-03 22:45:07 +00:00
parent 9b19207fd1
commit a076bca5dc
2 changed files with 120 additions and 75 deletions
+117 -73
View File
@@ -133,15 +133,24 @@ void Device_Property_Lists(
properties that are writable or that may change. properties that are writable or that may change.
The properties that are constant can be hard coded The properties that are constant can be hard coded
into the read-property encoding. */ into the read-property encoding. */
/* String Lengths - excluding any nul terminator */
#define MAX_DEV_NAME_LEN 32
#define MAX_DEV_LOC_LEN 64
#define MAX_DEV_MOD_LEN 32
#define MAX_DEV_VER_LEN 16
#define MAX_DEV_DESC_LEN 64
static uint32_t Object_Instance_Number = 260001; static uint32_t Object_Instance_Number = 260001;
static char My_Object_Name[16] = "SimpleServer"; static char My_Object_Name[MAX_DEV_NAME_LEN + 1] = "SimpleServer";
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL; static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
static char *Vendor_Name = BACNET_VENDOR_NAME; static char *Vendor_Name = BACNET_VENDOR_NAME;
static uint16_t Vendor_Identifier = BACNET_VENDOR_ID; static uint16_t Vendor_Identifier = BACNET_VENDOR_ID;
static char Model_Name[16] = "GNU"; static char Model_Name[MAX_DEV_MOD_LEN + 1] = "GNU";
static char Application_Software_Version[16] = "1.0"; static char Application_Software_Version[MAX_DEV_VER_LEN + 1] = "1.0";
static char Location[16] = "USA"; static char Location[MAX_DEV_LOC_LEN + 1] = "USA";
static char Description[16] = "server"; static char Description[MAX_DEV_DESC_LEN + 1] = "server";
/* static uint8_t Protocol_Version = 1; - constant, not settable */ /* static uint8_t Protocol_Version = 1; - constant, not settable */
/* static uint8_t Protocol_Revision = 4; - constant, not settable */ /* static uint8_t Protocol_Revision = 4; - constant, not settable */
/* Protocol_Services_Supported - dynamically generated */ /* Protocol_Services_Supported - dynamically generated */
@@ -216,7 +225,9 @@ bool Device_Set_Object_Name(
const char *name, const char *name,
size_t length) size_t length)
{ {
bool status = false; /*return value */ bool status; /*return value */
status = false;
/* FIXME: All the object names in a device must be unique. /* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in Disallow setting the Device Object Name to any objects in
@@ -238,11 +249,71 @@ BACNET_DEVICE_STATUS Device_System_Status(
return System_Status; return System_Status;
} }
void Device_Set_System_Status( int Device_Set_System_Status(
BACNET_DEVICE_STATUS status) BACNET_DEVICE_STATUS status,
bool local)
{ {
/* FIXME: bounds check? */ int result; /*return value - 0 = ok, -1 = bad value, -2 = not allowed */
result = 0;
/* We limit the options available depending on whether the source is
* internal or external. */
if(local) {
switch(status) {
case STATUS_OPERATIONAL:
case STATUS_OPERATIONAL_READ_ONLY:
case STATUS_DOWNLOAD_REQUIRED:
case STATUS_DOWNLOAD_IN_PROGRESS:
case STATUS_NON_OPERATIONAL:
System_Status = status;
break;
/* Don't support backup at present so don't allow setting */
case STATUS_BACKUP_IN_PROGRESS:
result = -2;
break;
default:
result = -1;
break;
}
} else {
switch(status) {
/* Allow these for the moment as a way to easily alter
* overall device operation. The lack of password protection
* or other authentication makes allowing writes to this
* property a risky facility to provide.
*/
case STATUS_OPERATIONAL:
case STATUS_OPERATIONAL_READ_ONLY:
case STATUS_NON_OPERATIONAL:
System_Status = status;
break;
/* Don't allow outsider set this - it should probably
* be set if the device config is incomplete or
* corrupted or perhaps after some sort of operator
* wipe operation.
*/
case STATUS_DOWNLOAD_REQUIRED:
/* Don't allow outsider set this - it should be set
* internally at the start of a multi packet download
* perhaps indirectly via PT or WF to a config file.
*/
case STATUS_DOWNLOAD_IN_PROGRESS:
/* Don't support backup at present so don't allow setting */
case STATUS_BACKUP_IN_PROGRESS:
result = -2;
break;
default:
result = -1;
break;
}
}
System_Status = status; System_Status = status;
return(result);
} }
const char *Device_Vendor_Name( const char *Device_Vendor_Name(
@@ -811,6 +882,7 @@ bool Device_Write_Property(
bool status = false; /* return value */ bool status = false; /* return value */
int len = 0; int len = 0;
BACNET_APPLICATION_DATA_VALUE value; BACNET_APPLICATION_DATA_VALUE value;
int temp;
if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT; *error_class = ERROR_CLASS_OBJECT;
@@ -825,92 +897,70 @@ bool Device_Write_Property(
/* FIXME: len == 0: unable to decode? */ /* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) { switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_OBJECT_ID, error_class, error_code) == true) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) && if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type. (Device_Set_Object_Instance_Number(value.type.Object_Id.instance))) {
Object_Id.instance))) {
/* FIXME: we could send an I-Am broadcast to let the world know */ /* FIXME: we could send an I-Am broadcast to let the world know */
status = true; status = true;
} else { } else {
*error_class = ERROR_CLASS_PROPERTY; *error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} }
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_NUMBER_OF_APDU_RETRIES: case PROP_NUMBER_OF_APDU_RETRIES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
/* FIXME: bounds check? */ /* FIXME: bounds check? */
apdu_retries_set((uint8_t) value.type.Unsigned_Int); apdu_retries_set((uint8_t) value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_APDU_TIMEOUT: case PROP_APDU_TIMEOUT:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
/* FIXME: bounds check? */ /* FIXME: bounds check? */
apdu_timeout_set((uint16_t) value.type.Unsigned_Int); apdu_timeout_set((uint16_t) value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_VENDOR_IDENTIFIER: case PROP_VENDOR_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
/* FIXME: bounds check? */ /* FIXME: bounds check? */
Device_Set_Vendor_Identifier((uint16_t) value. Device_Set_Vendor_Identifier((uint16_t) value.type.Unsigned_Int);
type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_SYSTEM_STATUS: case PROP_SYSTEM_STATUS:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, error_class, error_code) == true) {
/* FIXME: bounds check? */ temp = Device_Set_System_Status((BACNET_DEVICE_STATUS) value.type.Enumerated, false);
Device_Set_System_Status((BACNET_DEVICE_STATUS) value. if(temp == 0)
type.Enumerated); status = true;
status = true; else {
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
if (characterstring_encoding(&value.type.Character_String) == CHARACTER_ANSI_X34) {
if(characterstring_length(&value.type.Character_String) == 0) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} else {
status =
Device_Set_Object_Name(characterstring_value
(&value.type.Character_String),
characterstring_length(&value.type.Character_String));
if (!status) {
*error_class = ERROR_CLASS_RESOURCES;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY; *error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; *error_code = temp == -1 ? ERROR_CODE_VALUE_OUT_OF_RANGE : ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
} }
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_OBJECT_NAME:
if((status = WPValidateString(&value, MAX_DEV_LOC_LEN, false, error_class, error_code)) == true)
Device_Set_Object_Name(characterstring_value(&value.type.Character_String), characterstring_length(&value.type.Character_String));
break;
case PROP_LOCATION:
if((status = WPValidateString(&value, MAX_DEV_LOC_LEN, true, error_class, error_code)) == true)
Device_Set_Location(characterstring_value(&value.type.Character_String), characterstring_length(&value.type.Character_String));
break;
case PROP_DESCRIPTION:
if((status = WPValidateString(&value, MAX_DEV_DESC_LEN, true, error_class, error_code)) == true)
Device_Set_Description(characterstring_value(&value.type.Character_String), characterstring_length(&value.type.Character_String));
break;
case PROP_MODEL_NAME:
if((status = WPValidateString(&value, MAX_DEV_MOD_LEN, true, error_class, error_code)) == true)
Device_Set_Model_Name(characterstring_value(&value.type.Character_String), characterstring_length(&value.type.Character_String));
break;
#if defined(BACDL_MSTP) #if defined(BACDL_MSTP)
case PROP_MAX_INFO_FRAMES: case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
if (value.type.Unsigned_Int <= 255) { if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames((uint8_t) value. dlmstp_set_max_info_frames((uint8_t) value.
type.Unsigned_Int); type.Unsigned_Int);
@@ -919,13 +969,10 @@ bool Device_Write_Property(
*error_class = ERROR_CLASS_PROPERTY; *error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} }
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
case PROP_MAX_MASTER: case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
if ((value.type.Unsigned_Int > 0) && if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) { (value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master((uint8_t) value.type.Unsigned_Int); dlmstp_set_max_master((uint8_t) value.type.Unsigned_Int);
@@ -934,9 +981,6 @@ bool Device_Write_Property(
*error_class = ERROR_CLASS_PROPERTY; *error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} }
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
} }
break; break;
#endif #endif
@@ -1025,7 +1069,7 @@ void testDevice(
ct_test(pTest, status == false); ct_test(pTest, status == false);
Device_Set_System_Status(STATUS_NON_OPERATIONAL); Device_Set_System_Status(STATUS_NON_OPERATIONAL, true);
ct_test(pTest, Device_System_Status() == STATUS_NON_OPERATIONAL); ct_test(pTest, Device_System_Status() == STATUS_NON_OPERATIONAL);
ct_test(pTest, Device_Vendor_Identifier() == BACNET_VENDOR_ID); ct_test(pTest, Device_Vendor_Identifier() == BACNET_VENDOR_ID);
+3 -2
View File
@@ -86,8 +86,9 @@ extern "C" {
BACNET_DEVICE_STATUS Device_System_Status( BACNET_DEVICE_STATUS Device_System_Status(
void); void);
void Device_Set_System_Status( int Device_Set_System_Status(
BACNET_DEVICE_STATUS status); BACNET_DEVICE_STATUS status,
bool local);
const char *Device_Vendor_Name( const char *Device_Vendor_Name(
void); void);