/* returns true if successful */ bool Analog_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ unsigned int object_index = 0; unsigned int priority = 0; uint8_t level = ANALOG_LEVEL_NULL; int len = 0; BACNET_APPLICATION_DATA_VALUE value; Analog_Value_Init(); if (!Analog_Value_Valid_Instance(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_REAL) { priority = wp_data->priority; /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ if (priority && (priority <= BACNET_MAX_PRIORITY) && (priority != 6 /* reserved */ ) && (value.type.Real >= 0.0) && (value.type.Real <= 100.0)) { level = (uint8_t) value.type.Real; object_index = Analog_Value_Instance_To_Index (wp_data->object_instance); priority--; Present_Value[object_index] = level; /* Note: you could set the physical output here if we are the highest priority. However, if Out of Service is TRUE, then don't set the physical output. This comment may apply to the main loop (i.e. check out of service before changing output) */ status = true; } else if (priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } #if 0 } else if (value.tag == BACNET_APPLICATION_TAG_NULL) { level = ANALOG_LEVEL_NULL; object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); priority = wp_data->priority; if (priority && (priority <= BACNET_MAX_PRIORITY)) { priority--; Present_Value[object_index][priority] = level; /* Note: you could set the physical output here to the next highest priority, or to the relinquish default if no priorities are set. However, if Out of Service is TRUE, then don't set the physical output. This comment may apply to the main loop (i.e. check out of service before changing output) */ status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } #endif } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #if 0 case PROP_OUT_OF_SERVICE: if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) { object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); Analog_Value_Out_Of_Service[object_index] = value.type.Boolean; status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #endif default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/* returns true if successful */ bool Analog_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int object_index = 0; int len = 0; BACNET_APPLICATION_DATA_VALUE value; ANALOG_VALUE_DESCR *CurrentAV; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->object_property != PROP_EVENT_TIME_STAMPS) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); if (object_index < MAX_ANALOG_VALUES) CurrentAV = &AV_Descr[object_index]; else return false; switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_REAL) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ if (Analog_Value_Present_Value_Set(wp_data->object_instance, value.type.Real, wp_data->priority)) { status = true; } else if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Out_Of_Service = value.type.Boolean; } break; case PROP_UNITS: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Units = value.type.Enumerated; } break; #if defined(INTRINSIC_REPORTING) case PROP_TIME_DELAY: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Time_Delay = value.type.Unsigned_Int; CurrentAV->Remaining_Time_Delay = CurrentAV->Time_Delay; } break; case PROP_NOTIFICATION_CLASS: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Notification_Class = value.type.Unsigned_Int; } break; case PROP_HIGH_LIMIT: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->High_Limit = value.type.Real; } break; case PROP_LOW_LIMIT: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Low_Limit = value.type.Real; } break; case PROP_DEADBAND: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL, &wp_data->error_class, &wp_data->error_code); if (status) { CurrentAV->Deadband = value.type.Real; } break; case PROP_LIMIT_ENABLE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Bit_String.bits_used == 2) { CurrentAV->Limit_Enable = value.type.Bit_String.value[0]; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; status = false; } } break; case PROP_EVENT_ENABLE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Bit_String.bits_used == 3) { CurrentAV->Event_Enable = value.type.Bit_String.value[0]; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; status = false; } } break; case PROP_NOTIFY_TYPE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { switch ((BACNET_NOTIFY_TYPE) value.type.Enumerated) { case NOTIFY_EVENT: CurrentAV->Notify_Type = 1; break; case NOTIFY_ALARM: CurrentAV->Notify_Type = 0; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; status = false; break; } } break; #endif case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_DESCRIPTION: #if defined(INTRINSIC_REPORTING) case PROP_ACKED_TRANSITIONS: case PROP_EVENT_TIME_STAMPS: #endif wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; case PROP_RELINQUISH_DEFAULT: case PROP_PRIORITY_ARRAY: default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool Binary_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ unsigned int object_index = 0; int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!Binary_Value_Valid_Instance(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { if ((value.type.Enumerated == BINARY_ACTIVE) || (value.type.Enumerated == BINARY_INACTIVE)) { object_index = Binary_Value_Instance_To_Index (wp_data->object_instance); /* NOTE: this Binary value has no priority array */ Present_Value[object_index] = (BACNET_BINARY_PV) value.type.Enumerated; /* Note: you could set the physical output here if we are the highest priority. However, if Out of Service is TRUE, then don't set the physical output. */ if (Present_Value[0] == BINARY_ACTIVE) { LED_GREEN_ON(); } else { LED_GREEN_OFF(); } status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #if 0 case PROP_OUT_OF_SERVICE: if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) { object_index = Binary_Value_Instance_To_Index(wp_data->object_instance); Binary_Value_Out_Of_Service[object_index] = value.type.Boolean; status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #endif default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/* returns true if successful */ bool Binary_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int object_index = 0; unsigned int priority = 0; BACNET_BINARY_PV level = BINARY_NULL; int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } /* only array properties can have array options */ if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { priority = wp_data->priority; /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ if (priority && (priority <= BACNET_MAX_PRIORITY) && (priority != 6 /* reserved */ ) && (value.type.Enumerated <= MAX_BINARY_PV)) { level = (BACNET_BINARY_PV) value.type.Enumerated; object_index = Binary_Value_Instance_To_Index (wp_data->object_instance); priority--; Binary_Value_Level[object_index][priority] = level; /* Note: you could set the physical output here if we are the highest priority. However, if Out of Service is TRUE, then don't set the physical output. This comment may apply to the main loop (i.e. check out of service before changing output) */ status = true; } else if (priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, &wp_data->error_class, &wp_data->error_code); if (status) { level = BINARY_NULL; object_index = Binary_Value_Instance_To_Index (wp_data->object_instance); priority = wp_data->priority; if (priority && (priority <= BACNET_MAX_PRIORITY)) { priority--; Binary_Value_Level[object_index][priority] = level; /* Note: you could set the physical output here to the next highest priority, or to the relinquish default if no priorities are set. However, if Out of Service is TRUE, then don't set the physical output. This comment may apply to the main loop (i.e. check out of service before changing output) */ } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { object_index = Binary_Value_Instance_To_Index(wp_data->object_instance); Binary_Value_Out_Of_Service[object_index] = value.type.Boolean; } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_DESCRIPTION: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_PRIORITY_ARRAY: case PROP_RELINQUISH_DEFAULT: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
bool Notification_Class_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { NOTIFICATION_CLASS_INFO *CurrentNotify; NOTIFICATION_CLASS_INFO TmpNotify; BACNET_APPLICATION_DATA_VALUE value; bool status = false; int iOffset = 0; uint8_t idx = 0; int len = 0; CurrentNotify = &NC_Info[Notification_Class_Instance_To_Index(wp_data-> object_instance)]; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRIORITY: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { if (wp_data->array_index == 0) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; } else if (wp_data->array_index == BACNET_ARRAY_ALL) { /* FIXME: wite all array */ } else if (wp_data->array_index <= 3) { CurrentNotify->Priority[wp_data->array_index - 1] = value.type.Unsigned_Int; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX; } } break; case PROP_ACK_REQUIRED: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Bit_String.bits_used == 3) { CurrentNotify->Ack_Required = value.type.Bit_String.value[0]; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_RECIPIENT_LIST: memset(&TmpNotify, 0x00, sizeof(NOTIFICATION_CLASS_INFO)); /* decode all packed */ while (iOffset < wp_data->application_data_len) { /* Decode Valid Days */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } if (value.type.Bit_String.bits_used == MAX_BACNET_DAYS_OF_WEEK) /* store value */ TmpNotify.Recipient_List[idx].ValidDays = value.type.Bit_String.value[0]; else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_OTHER; return false; } iOffset += len; /* Decode From Time */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].FromTime = value.type.Time; iOffset += len; /* Decode To Time */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ToTime = value.type.Time; iOffset += len; /* context tag [0] - Device */ if (decode_is_context_tag(&wp_data->application_data[iOffset], 0)) { TmpNotify.Recipient_List[idx].Recipient.RecipientType = RECIPIENT_TYPE_DEVICE; /* Decode Network Number */ len = bacapp_decode_context_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value, PROP_RECIPIENT_LIST); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_OBJECT_ID)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].Recipient._. DeviceIdentifier = value.type.Object_Id.instance; iOffset += len; } /* opening tag [1] - Recipient */ else if (decode_is_opening_tag_number(&wp_data-> application_data[iOffset], 1)) { iOffset++; TmpNotify.Recipient_List[idx].Recipient.RecipientType = RECIPIENT_TYPE_ADDRESS; /* Decode Network Number */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].Recipient._.Address.net = value.type.Unsigned_Int; iOffset += len; /* Decode Address */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_OCTET_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ if (TmpNotify.Recipient_List[idx].Recipient._.Address. net == 0) { memcpy(TmpNotify.Recipient_List[idx].Recipient._. Address.mac, value.type.Octet_String.value, value.type.Octet_String.length); TmpNotify.Recipient_List[idx].Recipient._.Address. mac_len = value.type.Octet_String.length; } else { memcpy(TmpNotify.Recipient_List[idx].Recipient._. Address.adr, value.type.Octet_String.value, value.type.Octet_String.length); TmpNotify.Recipient_List[idx].Recipient._.Address.len = value.type.Octet_String.length; } iOffset += len; /* closing tag [1] - Recipient */ if (decode_is_closing_tag_number(&wp_data-> application_data[iOffset], 1)) iOffset++; else { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } } else { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* Process Identifier */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ProcessIdentifier = value.type.Unsigned_Int; iOffset += len; /* Issue Confirmed Notifications */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BOOLEAN)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } /* store value */ TmpNotify.Recipient_List[idx].ConfirmedNotify = value.type.Boolean; iOffset += len; /* Transitions */ len = bacapp_decode_application_data(&wp_data-> application_data[iOffset], wp_data->application_data_len, &value); if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) { /* Bad decode, wrong tag or following required parameter missing */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; return false; } if (value.type.Bit_String.bits_used == MAX_BACNET_EVENT_TRANSITION) /* store value */ TmpNotify.Recipient_List[idx].Transitions = value.type.Bit_String.value[0]; else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_OTHER; return false; } iOffset += len; /* Increasing element of list */ if (++idx >= NC_MAX_RECIPIENTS) { wp_data->error_class = ERROR_CLASS_RESOURCES; wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; return false; } } /* Decoded all recipient list */ /* copy elements from temporary object */ for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++) { BACNET_ADDRESS src = { 0 }; unsigned max_apdu = 0; int32_t DeviceID; CurrentNotify->Recipient_List[idx] = TmpNotify.Recipient_List[idx]; if (CurrentNotify->Recipient_List[idx].Recipient. RecipientType == RECIPIENT_TYPE_DEVICE) { /* copy Device_ID */ DeviceID = CurrentNotify->Recipient_List[idx].Recipient._. DeviceIdentifier; address_bind_request(DeviceID, &max_apdu, &src); } else if (CurrentNotify->Recipient_List[idx].Recipient. RecipientType == RECIPIENT_TYPE_ADDRESS) { /* copy Address */ /* src = CurrentNotify->Recipient_List[idx].Recipient._.Address; */ /* address_bind_request(BACNET_MAX_INSTANCE, &max_apdu, &src); */ } } status = true; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool Binary_Input_Write_Property( BACNET_WRITE_PROPERTY_DATA far * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } /* only array properties can have array options */ if (wp_data->array_index != BACNET_ARRAY_ALL) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Enumerated <= MAX_BINARY_PV) { Binary_Input_Present_Value_Set(wp_data->object_instance, (BACNET_BINARY_PV) value.type.Enumerated); } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { Binary_Input_Out_Of_Service_Set(wp_data->object_instance, value.type.Boolean); } break; case PROP_POLARITY: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Enumerated < MAX_POLARITY) { Binary_Input_Polarity_Set(wp_data->object_instance, (BACNET_POLARITY) value.type.Enumerated); } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_DESCRIPTION: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool Analog_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA xdata * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ unsigned int object_index = 0; int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!Analog_Value_Valid_Instance(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_REAL) { object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); AV_Present_Value[object_index] = value.type.Real; // wirte_bacnet_value_to_buf(AV,wp_data->priority,object_index); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_OUT_OF_SERVICE: case PROP_DESCRIPTION: case PROP_PRIORITY_ARRAY: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool Credential_Data_Input_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; unsigned object_index = 0; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } /* only array properties can have array options */ if ((wp_data->object_property != PROP_SUPPORTED_FORMATS) && (wp_data->array_index != BACNET_ARRAY_ALL)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } object_index = Credential_Data_Input_Instance_To_Index(wp_data->object_instance); switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (Credential_Data_Input_Out_Of_Service(wp_data->object_instance)) { BACNET_AUTHENTICATION_FACTOR tmp; len = bacapp_decode_authentication_factor(wp_data-> application_data, &tmp); if (len > 0) { memcpy(&cdi_descr[object_index].present_value, &tmp, sizeof(BACNET_AUTHENTICATION_FACTOR)); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } break; case PROP_RELIABILITY: if (Credential_Data_Input_Out_Of_Service(wp_data->object_instance)) { status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { cdi_descr[object_index].reliability = value.type.Enumerated; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_OUT_OF_SERVICE: case PROP_SUPPORTED_FORMATS: case PROP_UPDATE_TIME: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
void testWritePropertyTag( Test * pTest, BACNET_APPLICATION_DATA_VALUE * value) { BACNET_WRITE_PROPERTY_DATA wpdata = { 0 }; BACNET_WRITE_PROPERTY_DATA test_data = { 0 }; BACNET_APPLICATION_DATA_VALUE test_value; uint8_t apdu[480] = { 0 }; int len = 0; int apdu_len = 0; uint8_t invoke_id = 128; uint8_t test_invoke_id = 0; wpdata.application_data_len = bacapp_encode_application_data(&wpdata.application_data[0], value); len = wp_encode_apdu(&apdu[0], invoke_id, &wpdata); ct_test(pTest, len != 0); /* decode the data */ apdu_len = len; len = wp_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &test_data); ct_test(pTest, len != -1); ct_test(pTest, test_data.object_type == wpdata.object_type); ct_test(pTest, test_data.object_instance == wpdata.object_instance); ct_test(pTest, test_data.object_property == wpdata.object_property); ct_test(pTest, test_data.array_index == wpdata.array_index); /* decode the application value of the request */ len = bacapp_decode_application_data(test_data.application_data, test_data.application_data_len, &test_value); ct_test(pTest, test_value.tag == value->tag); switch (test_value.tag) { case BACNET_APPLICATION_TAG_NULL: break; case BACNET_APPLICATION_TAG_BOOLEAN: ct_test(pTest, test_value.type.Boolean == value->type.Boolean); break; case BACNET_APPLICATION_TAG_UNSIGNED_INT: ct_test(pTest, test_value.type.Unsigned_Int == value->type.Unsigned_Int); break; case BACNET_APPLICATION_TAG_SIGNED_INT: ct_test(pTest, test_value.type.Signed_Int == value->type.Signed_Int); break; case BACNET_APPLICATION_TAG_REAL: ct_test(pTest, test_value.type.Real == value->type.Real); break; case BACNET_APPLICATION_TAG_ENUMERATED: ct_test(pTest, test_value.type.Enumerated == value->type.Enumerated); break; case BACNET_APPLICATION_TAG_DATE: ct_test(pTest, test_value.type.Date.year == value->type.Date.year); ct_test(pTest, test_value.type.Date.month == value->type.Date.month); ct_test(pTest, test_value.type.Date.day == value->type.Date.day); ct_test(pTest, test_value.type.Date.wday == value->type.Date.wday); break; case BACNET_APPLICATION_TAG_TIME: ct_test(pTest, test_value.type.Time.hour == value->type.Time.hour); ct_test(pTest, test_value.type.Time.min == value->type.Time.min); ct_test(pTest, test_value.type.Time.sec == value->type.Time.sec); ct_test(pTest, test_value.type.Time.hundredths == value->type.Time.hundredths); break; case BACNET_APPLICATION_TAG_OBJECT_ID: ct_test(pTest, test_value.type.Object_Id.type == value->type.Object_Id.type); ct_test(pTest, test_value.type.Object_Id.instance == value->type.Object_Id.instance); break; default: break; } }
/* returns true if successful */ bool Analog_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ #if 0 unsigned int object_index = 0; unsigned int priority = 0; #endif BACNET_APPLICATION_DATA_VALUE value; int len = 0; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_REAL, &wp_data->error_class, &wp_data->error_code); if (status) { status = Analog_Value_Present_Value_Set(wp_data->object_instance, value.type.Real, wp_data->priority); if (!status) { if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } } break; case PROP_OUT_OF_SERVICE: #if 0 status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); Analog_Value_Out_Of_Service[object_index] = value.type.Boolean; } break; #endif case PROP_UNITS: #if 0 status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { object_index = Analog_Value_Instance_To_Index(wp_data->object_instance); Analog_Value_Units[object_index] = value.type.Unsigned_Int; } break; #endif case PROP_PRIORITY_ARRAY: case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_DESCRIPTION: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; case PROP_RELINQUISH_DEFAULT: default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } /* not using len at this time */ len = len; return status; }
/* returns true if successful */ bool Life_Safety_Point_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int object_index = 0; int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } /* only array properties can have array options */ if (wp_data->array_index != BACNET_ARRAY_ALL) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_MODE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Enumerated <= MAX_LIFE_SAFETY_MODE) { object_index = Life_Safety_Point_Instance_To_Index (wp_data->object_instance); Life_Safety_Point_Mode[object_index] = value.type.Enumerated; } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { object_index = Life_Safety_Point_Instance_To_Index (wp_data->object_instance); Life_Safety_Point_Out_Of_Service[object_index] = value.type.Boolean; } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_DESCRIPTION: case PROP_OBJECT_TYPE: case PROP_PRESENT_VALUE: case PROP_TRACKING_VALUE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_RELIABILITY: case PROP_ACCEPTED_MODES: case PROP_SILENCED: case PROP_OPERATION_EXPECTED: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool Device_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* FIXME: we could send an I-Am broadcast to let the world know */ status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_NUMBER_OF_APDU_RETRIES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { /* FIXME: bounds check? */ 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; case PROP_APDU_TIMEOUT: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { /* FIXME: bounds check? */ 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; case PROP_VENDOR_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { /* FIXME: bounds check? */ Device_Set_Vendor_Identifier((uint16_t) value. type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_SYSTEM_STATUS: if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) { /* FIXME: bounds check? */ Device_Set_System_Status((BACNET_DEVICE_STATUS) value. type.Enumerated); status = true; } 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) { uint8_t encoding; encoding = characterstring_encoding(&value.type.Character_String); if (encoding == CHARACTER_ANSI_X34) { status = Device_Set_Object_Name(characterstring_value (&value.type.Character_String), characterstring_length(&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_CHARACTER_SET_NOT_SUPPORTED; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #if defined(BACDL_MSTP) case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames((uint8_t) value. type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master((uint8_t) value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; #endif default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/** * WriteProperty handler for this object. For the given WriteProperty * data, the application_data is loaded or the error flags are set. * * @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including * requested data and space for the reply, or error response. * * @return false if an error is loaded, true if no errors */ bool Integer_Value_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->object_property != PROP_EVENT_TIME_STAMPS) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_SIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { Integer_Value_Present_Value_Set(wp_data->object_instance, value.type.Signed_Int, wp_data->priority); } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { Integer_Value_Out_Of_Service_Set( wp_data->object_instance, value.type.Boolean); } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_UNITS: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/* returns true if successful */ bool bacfile_write_property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!bacfile_valid_instance(wp_data->object_instance)) { wp_data->error_class = ERROR_CLASS_OBJECT; wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* only array properties can have array options */ if (wp_data->array_index != BACNET_ARRAY_ALL) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } /* FIXME: len < application_data_len: more data? */ switch (wp_data->object_property) { case PROP_ARCHIVE: /* 12.13.8 Archive This property, of type BOOLEAN, indicates whether the File object has been saved for historical or backup purposes. This property shall be logical TRUE only if no changes have been made to the file data by internal processes or through File Access Services since the last time the object was archived. */ status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Boolean) { /* FIXME: do something to wp_data->object_instance */ } else { /* FIXME: do something to wp_data->object_instance */ } } break; case PROP_FILE_SIZE: /* If the file size can be changed by writing to the file, and File_Access_Method is STREAM_ACCESS, then this property shall be writable. */ status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { /* FIXME: do something with value.type.Unsigned to wp_data->object_instance */ } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_DESCRIPTION: case PROP_FILE_TYPE: case PROP_MODIFICATION_DATE: case PROP_READ_ONLY: case PROP_FILE_ACCESS_METHOD: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
bool Device_Write_Property_Local( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value - false=error */ int len = 0; uint8_t encoding = 0; size_t length = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_OBJECT_LIST) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch ((int) wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* we could send an I-Am broadcast to let the world know */ status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { length = characterstring_length(&value.type.Character_String); if (length < 1) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } else if (length < characterstring_capacity(&My_Object_Name)) { encoding = characterstring_encoding(&value.type.Character_String); if (encoding < MAX_CHARACTER_STRING_ENCODING) { /* All the object names in a device must be unique. */ if (Device_Valid_Object_Name(&value.type. Character_String, NULL, NULL)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_DUPLICATE_NAME; } else { Device_Set_Object_Name(&value.type. Character_String); status = true; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 115200) { RS485_Set_Baud_Rate(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_NUMBER_OF_APDU_RETRIES: case PROP_APDU_TIMEOUT: case PROP_VENDOR_IDENTIFIER: case PROP_SYSTEM_STATUS: case PROP_LOCATION: case PROP_DESCRIPTION: case PROP_MODEL_NAME: case PROP_VENDOR_NAME: case PROP_FIRMWARE_REVISION: case PROP_APPLICATION_SOFTWARE_VERSION: case PROP_LOCAL_TIME: case PROP_UTC_OFFSET: case PROP_LOCAL_DATE: case PROP_DAYLIGHT_SAVINGS_STATUS: case PROP_PROTOCOL_VERSION: case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: case PROP_OBJECT_LIST: case PROP_MAX_APDU_LENGTH_ACCEPTED: case PROP_SEGMENTATION_SUPPORTED: case PROP_DEVICE_ADDRESS_BINDING: case PROP_DATABASE_REVISION: case PROP_ACTIVE_COV_SUBSCRIPTIONS: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } /* not using len at this time */ len = len; return status; }
void testReadPropertyMultipleAck( Test * pTest) { uint8_t apdu[480] = { 0 }; int len = 0; int test_len = 0; int apdu_len = 0; uint8_t invoke_id = 12; uint8_t test_invoke_id = 0; uint8_t *service_request = NULL; unsigned service_request_len = 0; BACNET_OBJECT_TYPE object_type = OBJECT_DEVICE; uint32_t object_instance = 0; BACNET_PROPERTY_ID object_property = PROP_OBJECT_IDENTIFIER; uint32_t array_index = 0; BACNET_APPLICATION_DATA_VALUE application_data[4] = { {0} }; BACNET_APPLICATION_DATA_VALUE test_application_data = { 0 }; uint8_t application_data_buffer[MAX_APDU] = { 0 }; int application_data_buffer_len = 0; BACNET_ERROR_CLASS error_class; BACNET_ERROR_CODE error_code; BACNET_RPM_DATA rpmdata; /* build the RPM - try to make it easy for the Application Layer development */ /* IDEA: similar construction, but pass apdu, apdu_len pointer, size of apdu to let the called function handle the out of space problem that these get into by returning a boolean of success/failure. It almost needs to use the keylist library or something similar. Also check case of storing a backoff point (i.e. save enough room for object_end) */ apdu_len = rpm_ack_encode_apdu_init(&apdu[0], invoke_id); /* object beginning */ rpmdata.object_type = OBJECT_DEVICE; rpmdata.object_instance = 123; apdu_len += rpm_ack_encode_apdu_object_begin(&apdu[apdu_len], &rpmdata); /* reply property */ apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL); /* reply value */ application_data[0].tag = BACNET_APPLICATION_TAG_OBJECT_ID; application_data[0].type.Object_Id.type = OBJECT_DEVICE; application_data[0].type.Object_Id.instance = 123; application_data_buffer_len = bacapp_encode_application_data(&application_data_buffer[0], &application_data[0]); apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], &application_data_buffer[0], application_data_buffer_len); /* reply property */ apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_OBJECT_TYPE, BACNET_ARRAY_ALL); /* reply value */ application_data[1].tag = BACNET_APPLICATION_TAG_ENUMERATED; application_data[1].type.Enumerated = OBJECT_DEVICE; application_data_buffer_len = bacapp_encode_application_data(&application_data_buffer[0], &application_data[1]); apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], &application_data_buffer[0], application_data_buffer_len); /* object end */ apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]); /* object beginning */ rpmdata.object_type = OBJECT_ANALOG_INPUT; rpmdata.object_instance = 33; apdu_len += rpm_ack_encode_apdu_object_begin(&apdu[apdu_len], &rpmdata); /* reply property */ apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_PRESENT_VALUE, BACNET_ARRAY_ALL); /* reply value */ application_data[2].tag = BACNET_APPLICATION_TAG_REAL; application_data[2].type.Real = 0.0; application_data_buffer_len = bacapp_encode_application_data(&application_data_buffer[0], &application_data[2]); apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len], &application_data_buffer[0], application_data_buffer_len); /* reply property */ apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len], PROP_DEADBAND, BACNET_ARRAY_ALL); /* reply error */ apdu_len += rpm_ack_encode_apdu_object_property_error(&apdu[apdu_len], ERROR_CLASS_PROPERTY, ERROR_CODE_UNKNOWN_PROPERTY); /* object end */ apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]); ct_test(pTest, apdu_len != 0); /****** decode the packet ******/ test_len = rpm_ack_decode_apdu(&apdu[0], apdu_len, &test_invoke_id, &service_request, /* will point to the service request in the apdu */ &service_request_len); ct_test(pTest, test_len != -1); ct_test(pTest, test_invoke_id == invoke_id); ct_test(pTest, service_request != NULL); ct_test(pTest, service_request_len > 0); /* the first part should be the first object id */ test_len = rpm_ack_decode_object_id(service_request, service_request_len, &object_type, &object_instance); ct_test(pTest, test_len != -1); ct_test(pTest, object_type == OBJECT_DEVICE); ct_test(pTest, object_instance == 123); len = test_len; /* extract the property */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, object_property == PROP_OBJECT_IDENTIFIER); ct_test(pTest, array_index == BACNET_ARRAY_ALL); len += test_len; /* what is the result? An error or a value? */ ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4)); len++; /* decode the object property portion of the service request */ /* note: if this was an array, there could have been more than one element to decode */ test_len = bacapp_decode_application_data(&service_request[len], service_request_len - len, &test_application_data); ct_test(pTest, test_len > 0); ct_test(pTest, bacapp_same_value(&application_data[0], &test_application_data)); len += test_len; ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4)); len++; /* see if there is another property */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, test_len != -1); ct_test(pTest, object_property == PROP_OBJECT_TYPE); ct_test(pTest, array_index == BACNET_ARRAY_ALL); len += test_len; /* what is the result value? */ ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4)); len++; /* decode the object property portion of the service request */ test_len = bacapp_decode_application_data(&service_request[len], service_request_len - len, &test_application_data); ct_test(pTest, test_len > 0); ct_test(pTest, bacapp_same_value(&application_data[1], &test_application_data)); len += test_len; ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4)); len++; /* see if there is another property */ /* this time we should fail */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, test_len == -1); /* see if it is the end of this object */ test_len = rpm_ack_decode_object_end(&service_request[len], service_request_len - len); ct_test(pTest, test_len == 1); len += test_len; /* try to decode another object id */ test_len = rpm_ack_decode_object_id(&service_request[len], service_request_len - len, &object_type, &object_instance); ct_test(pTest, test_len != -1); ct_test(pTest, object_type == OBJECT_ANALOG_INPUT); ct_test(pTest, object_instance == 33); len += test_len; /* decode the object property portion of the service request only */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, test_len != -1); ct_test(pTest, object_property == PROP_PRESENT_VALUE); ct_test(pTest, array_index == BACNET_ARRAY_ALL); len += test_len; /* what is the result value? */ ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 4)); len++; /* decode the object property portion of the service request */ test_len = bacapp_decode_application_data(&service_request[len], service_request_len - len, &test_application_data); ct_test(pTest, test_len > 0); ct_test(pTest, bacapp_same_value(&application_data[2], &test_application_data)); len += test_len; ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 4)); len++; /* see if there is another property */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, test_len != -1); ct_test(pTest, object_property == PROP_DEADBAND); ct_test(pTest, array_index == BACNET_ARRAY_ALL); len += test_len; /* what is the result value? */ ct_test(pTest, decode_is_opening_tag_number(&service_request[len], 5)); len++; /* it was an error reply */ test_len = bacerror_decode_error_class_and_code(&service_request[len], service_request_len - len, &error_class, &error_code); ct_test(pTest, test_len != 0); ct_test(pTest, error_class == ERROR_CLASS_PROPERTY); ct_test(pTest, error_code == ERROR_CODE_UNKNOWN_PROPERTY); len += test_len; ct_test(pTest, decode_is_closing_tag_number(&service_request[len], 5)); len++; /* is there another property? */ test_len = rpm_ack_decode_object_property(&service_request[len], service_request_len - len, &object_property, &array_index); ct_test(pTest, test_len == -1); /* got an error -1, is it the end of this object? */ test_len = rpm_ack_decode_object_end(&service_request[len], service_request_len - len); ct_test(pTest, test_len == 1); len += test_len; /* check for another object */ test_len = rpm_ack_decode_object_id(&service_request[len], service_request_len - len, &object_type, &object_instance); ct_test(pTest, test_len == 0); ct_test(pTest, len == service_request_len); }
bool Device_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data, BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; if (!Device_Valid_Object_Instance_Number(wp_data->object_instance)) { *error_class = ERROR_CLASS_OBJECT; *error_code = ERROR_CODE_UNKNOWN_OBJECT; return false; } /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ /* FIXME: len == 0: unable to decode? */ switch (wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* we could send an I-Am broadcast to let the world know */ status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } 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) { uint8_t encoding; encoding = characterstring_encoding(&value.type.Character_String); if (encoding == CHARACTER_ANSI_X34) { if (characterstring_ansi_copy(&Object_Name[0], sizeof(Object_Name), &value.type.Character_String)) { status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int > 115200) { RS485_Set_Baud_Rate(value.type.Unsigned_Int); status = true; } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; default: *error_class = ERROR_CLASS_PROPERTY; *error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/* returns true if successful */ bool Lighting_Output_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int object_index = 0; uint8_t level = LIGHTING_LEVEL_NULL; int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_REAL) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ status = Lighting_Output_Present_Value_Set(wp_data->object_instance, value.type.Real, wp_data->priority); if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, &wp_data->error_class, &wp_data->error_code); if (status) { level = LIGHTING_LEVEL_NULL; object_index = Lighting_Output_Instance_To_Index (wp_data->object_instance); status = Lighting_Output_Present_Value_Relinquish (wp_data->object_instance, wp_data->priority); if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. - Note Lighting_Output_Present_Value_Relinquish() will have returned false because of this */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } } break; case PROP_LIGHTING_COMMAND: /* FIXME: error checking? */ Lighting_Output_Decode_Lighting_Command(wp_data->application_data, wp_data->application_data_len, &Lighting_Command[wp_data->object_instance]); break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { object_index = Lighting_Output_Instance_To_Index (wp_data->object_instance); Lighting_Output_Out_Of_Service[object_index] = value.type.Boolean; } break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; } return status; }
/* returns true if successful */ bool Binary_Output_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ unsigned int priority = 0; BACNET_BINARY_PV level = BINARY_NULL; int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { priority = wp_data->priority; /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ if (priority && (priority <= BACNET_MAX_PRIORITY) && (priority != 6 /* reserved */ ) && (value.type.Enumerated <= MAX_BINARY_PV)) { level = (BACNET_BINARY_PV) value.type.Enumerated; priority--; Binary_Output_Present_Value_Set(wp_data->object_instance, level, priority); } else if (priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, &wp_data->error_class, &wp_data->error_code); if (status) { level = BINARY_NULL; priority = wp_data->priority; if (priority && (priority <= BACNET_MAX_PRIORITY)) { priority--; Binary_Output_Present_Value_Set (wp_data->object_instance, level, priority); } else if (priority == 6) { status = false; /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { Binary_Output_Out_Of_Service_Set(wp_data->object_instance, value.type.Boolean); } break; case PROP_POLARITY: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class, &wp_data->error_code); if (status) { if (value.type.Enumerated < MAX_POLARITY) { Binary_Output_Polarity_Set(wp_data->object_instance, (BACNET_POLARITY) value.type.Enumerated); } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_RELIABILITY: case PROP_EVENT_STATE: case PROP_PRIORITY_ARRAY: case PROP_RELINQUISH_DEFAULT: case PROP_ACTIVE_TEXT: case PROP_INACTIVE_TEXT: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } /* not using len at this time */ len = len; return status; }
/** Decode the received RPM data and make a linked list of the results. * @ingroup DSRPM * * @param apdu [in] The received apdu data. * @param apdu_len [in] Total length of the apdu. * @param read_access_data [out] Pointer to the head of the linked list * where the RPM data is to be stored. * @return The number of bytes decoded, or -1 on error */ int rpm_ack_decode_service_request( uint8_t * apdu, int apdu_len, BACNET_READ_ACCESS_DATA * read_access_data) { int decoded_len = 0; /* return value */ uint32_t error_value = 0; /* decoded error value */ int len = 0; /* number of bytes returned from decoding */ uint8_t tag_number = 0; /* decoded tag number */ uint32_t len_value = 0; /* decoded length value */ BACNET_READ_ACCESS_DATA *rpm_object; BACNET_READ_ACCESS_DATA *old_rpm_object; BACNET_PROPERTY_REFERENCE *rpm_property; BACNET_PROPERTY_REFERENCE *old_rpm_property; BACNET_APPLICATION_DATA_VALUE *value; BACNET_APPLICATION_DATA_VALUE *old_value; assert(read_access_data != NULL); rpm_object = read_access_data; old_rpm_object = rpm_object; while (rpm_object && apdu_len) { len = rpm_ack_decode_object_id(apdu, apdu_len, &rpm_object->object_type, &rpm_object->object_instance); if (len <= 0) { old_rpm_object->next = NULL; free(rpm_object); break; } decoded_len += len; apdu_len -= len; apdu += len; rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE)); rpm_object->listOfProperties = rpm_property; old_rpm_property = rpm_property; while (rpm_property && apdu_len) { len = rpm_ack_decode_object_property(apdu, apdu_len, &rpm_property->propertyIdentifier, &rpm_property->propertyArrayIndex); if (len <= 0) { old_rpm_property->next = NULL; if (rpm_object->listOfProperties == rpm_property) { /* was this the only property in the list? */ rpm_object->listOfProperties = NULL; } free(rpm_property); break; } decoded_len += len; apdu_len -= len; apdu += len; if (apdu_len && decode_is_opening_tag_number(apdu, 4)) { /* propertyValue */ decoded_len++; apdu_len--; apdu++; /* note: if this is an array, there will be more than one element to decode */ value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); rpm_property->value = value; old_value = value; while (value && (apdu_len > 0)) { if (IS_CONTEXT_SPECIFIC(*apdu)) { len = bacapp_decode_context_data(apdu, apdu_len, value, rpm_property->propertyIdentifier); } else { len = bacapp_decode_application_data(apdu, apdu_len, value); } /* If len == 0 then it's an empty structure, which is OK. */ if (len < 0) { /* problem decoding */ /* calling function will free the memory */ return BACNET_STATUS_ERROR; } decoded_len += len; apdu_len -= len; apdu += len; if (apdu_len && decode_is_closing_tag_number(apdu, 4)) { decoded_len++; apdu_len--; apdu++; break; } else { old_value = value; value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); old_value->next = value; } } } else if (apdu_len && decode_is_opening_tag_number(apdu, 5)) { /* propertyAccessError */ decoded_len++; apdu_len--; apdu++; /* decode the class and code sequence */ len = decode_tag_number_and_value(apdu, &tag_number, &len_value); decoded_len += len; apdu_len -= len; apdu += len; /* FIXME: we could validate that the tag is enumerated... */ len = decode_enumerated(apdu, len_value, &error_value); rpm_property->error.error_class = error_value; decoded_len += len; apdu_len -= len; apdu += len; len = decode_tag_number_and_value(apdu, &tag_number, &len_value); decoded_len += len; apdu_len -= len; apdu += len; /* FIXME: we could validate that the tag is enumerated... */ len = decode_enumerated(apdu, len_value, &error_value); rpm_property->error.error_code = error_value; decoded_len += len; apdu_len -= len; apdu += len; if (apdu_len && decode_is_closing_tag_number(apdu, 5)) { decoded_len++; apdu_len--; apdu++; } } old_rpm_property = rpm_property; rpm_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE)); old_rpm_property->next = rpm_property; } len = rpm_decode_object_end(apdu, apdu_len); if (len) { decoded_len += len; apdu_len -= len; apdu += len; } if (apdu_len) { old_rpm_object = rpm_object; rpm_object = calloc(1, sizeof(BACNET_READ_ACCESS_DATA)); old_rpm_object->next = rpm_object; } } return decoded_len; }
/* returns true if successful */ bool Multistate_Input_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; int element_len = 0; BACNET_APPLICATION_DATA_VALUE value; uint32_t max_states = 0; uint32_t array_index = 0; int object_type = 0; uint32_t object_instance = 0; /* decode the first chunk of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* len < application_data_len: extra data for arrays only */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_STATE_TEXT) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { /* All the object names in a device must be unique */ if (Device_Valid_Object_Name(&value.type.Character_String, &object_type, &object_instance)) { if ((object_type == wp_data->object_type) && (object_instance == wp_data->object_instance)) { /* writing same name to same object */ status = true; } else { status = false; wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_DUPLICATE_NAME; } } else { status = Multistate_Input_Object_Name_Write(wp_data-> object_instance, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_DESCRIPTION: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = Multistate_Input_Description_Write(wp_data-> object_instance, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_PRESENT_VALUE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, &wp_data->error_class, &wp_data->error_code); if (status) { status = Multistate_Input_Present_Value_Set (wp_data->object_instance, value.type.Unsigned_Int); if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { Multistate_Input_Out_Of_Service_Set(wp_data->object_instance, value.type.Boolean); } break; case PROP_STATE_TEXT: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { if (wp_data->array_index == 0) { /* Array element zero is the number of elements in the array. We have a fixed size array, so we are read-only. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else if (wp_data->array_index == BACNET_ARRAY_ALL) { max_states = Multistate_Input_Max_States(wp_data->object_instance); array_index = 1; element_len = len; do { if (element_len) { status = Multistate_Input_State_Text_Write(wp_data-> object_instance, array_index, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } max_states--; array_index++; if (max_states) { element_len = bacapp_decode_application_data(&wp_data-> application_data[len], wp_data->application_data_len - len, &value); if (element_len < 0) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; break; } len += element_len; } } while (max_states); } else { max_states = Multistate_Input_Max_States(wp_data->object_instance); if (wp_data->array_index <= max_states) { status = Multistate_Input_State_Text_Write(wp_data-> object_instance, wp_data->array_index, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_TYPE: case PROP_STATUS_FLAGS: case PROP_EVENT_STATE: case PROP_NUMBER_OF_STATES: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/** Decode the received RP data into a linked list of the results, with the * same data structure used by RPM ACK replies. * This function is provided to provide common handling for RP and RPM data, * and fully decodes the value(s) portion of the data for one property. * @ingroup DSRP * @see rp_ack_decode_service_request(), rpm_ack_decode_service_request() * * @param apdu [in] The received apdu data. * @param apdu_len [in] Total length of the apdu. * @param read_access_data [out] Pointer to the head of the linked list * where the RP data is to be stored. * @return Number of decoded bytes (could be less than apdu_len), * or -1 on decoding error. */ int rp_ack_fully_decode_service_request( uint8_t * apdu, int apdu_len, BACNET_READ_ACCESS_DATA * read_access_data) { int decoded_len = 0; /* return value */ BACNET_READ_PROPERTY_DATA rp1data; BACNET_PROPERTY_REFERENCE *rp1_property; /* single property */ BACNET_APPLICATION_DATA_VALUE *value, *old_value; uint8_t *vdata; int vlen, len; decoded_len = rp_ack_decode_service_request(apdu, apdu_len, &rp1data); if (decoded_len > 0) { /* Then we have to transfer to the BACNET_READ_ACCESS_DATA structure * and decode the value(s) portion */ read_access_data->object_type = rp1data.object_type; read_access_data->object_instance = rp1data.object_instance; rp1_property = calloc(1, sizeof(BACNET_PROPERTY_REFERENCE)); read_access_data->listOfProperties = rp1_property; if (rp1_property == NULL) { /* can't proceed if calloc failed. */ return BACNET_STATUS_ERROR; } rp1_property->propertyIdentifier = rp1data.object_property; rp1_property->propertyArrayIndex = rp1data.array_index; /* Is there no Error case possible here, as there is when decoding RPM? */ /* rp1_property->error.error_class = ?? */ /* rp_ack_decode_service_request() processing already removed the * Opening and Closing '3' Tags. * note: if this is an array, there will be more than one element to decode */ vdata = rp1data.application_data; vlen = rp1data.application_data_len; value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); rp1_property->value = value; old_value = value; while (value && vdata && (vlen > 0)) { if (IS_CONTEXT_SPECIFIC(*vdata)) { len = bacapp_decode_context_data(vdata, vlen, value, rp1_property->propertyIdentifier); } else { len = bacapp_decode_application_data(vdata, vlen, value); } if (len < 0) { /* unable to decode the data */ while (value) { /* free the linked list of values */ old_value = value; value = value->next; free(old_value); } free(rp1_property); read_access_data->listOfProperties = NULL; return len; } decoded_len += len; vlen -= len; vdata += len; /* If unexpected closing tag here: */ if (vlen && decode_is_closing_tag_number(vdata, 3)) { decoded_len++; vlen--; vdata++; break; } else { if (len == 0) { /* nothing decoded and no closing tag, so malformed */ while (value) { /* free the linked list of values */ old_value = value; value = value->next; free(old_value); } free(rp1_property); read_access_data->listOfProperties = NULL; return BACNET_STATUS_ERROR; } if (vlen > 0) { /* If more values */ old_value = value; value = calloc(1, sizeof(BACNET_APPLICATION_DATA_VALUE)); old_value->next = value; } } } } return decoded_len; }
bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value - false=error */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; uint8_t max_master = 0; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_OBJECT_LIST) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch ((int) wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type.Object_Id. instance))) { nvm_write(NVM_DEVICE_0, (uint8_t *) & value.type.Object_Id.instance, 4); /* we could send an I-Am broadcast to let the world know */ status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { max_master = value.type.Unsigned_Int; dlmstp_set_max_master(max_master); nvm_write(NVM_MAX_MASTER, &max_master, 1); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write_unique(NVM_DEVICE_NAME, wp_data->object_type, wp_data->object_instance, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_DESCRIPTION: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write(NVM_DEVICE_DESCRIPTION, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_LOCATION: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write(NVM_DEVICE_LOCATION, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_TYPE: case PROP_VENDOR_NAME: case PROP_FIRMWARE_REVISION: case PROP_APPLICATION_SOFTWARE_VERSION: case PROP_DAYLIGHT_SAVINGS_STATUS: case PROP_PROTOCOL_VERSION: case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: case PROP_OBJECT_LIST: case PROP_MAX_APDU_LENGTH_ACCEPTED: case PROP_SEGMENTATION_SUPPORTED: case PROP_DEVICE_ADDRESS_BINDING: case PROP_DATABASE_REVISION: case 512: case 513: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
/** * WriteProperty handler for this object. For the given WriteProperty * data, the application_data is loaded or the error flags are set. * * @param wp_data - BACNET_WRITE_PROPERTY_DATA data, including * requested data and space for the reply, or error response. * * @return false if an error is loaded, true if no errors */ bool Lighting_Output_Write_Property( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_PRIORITY_ARRAY) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_PRESENT_VALUE: if (value.tag == BACNET_APPLICATION_TAG_REAL) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ status = Lighting_Output_Present_Value_Set(wp_data->object_instance, value.type.Real, wp_data->priority); if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, &wp_data->error_class, &wp_data->error_code); if (status) { if (wp_data->priority == 6) { /* Command priority 6 is reserved for use by Minimum On/Off algorithm and may not be used for other purposes in any object. - Note Lighting_Output_Present_Value_Relinquish() will have returned false because of this */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; } else { status = Lighting_Output_Present_Value_Relinquish( wp_data->object_instance, wp_data->priority); if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } } } break; case PROP_LIGHTING_COMMAND: if (value.tag == BACNET_APPLICATION_TAG_LIGHTING_COMMAND) { status = Lighting_Output_Lighting_Command_Set( wp_data->object_instance, &value.type.Lighting_Command); if (!status) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OUT_OF_SERVICE: status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, &wp_data->error_class, &wp_data->error_code); if (status) { Lighting_Output_Out_Of_Service_Set( wp_data->object_instance, value.type.Boolean); } break; case PROP_OBJECT_IDENTIFIER: case PROP_OBJECT_NAME: case PROP_OBJECT_TYPE: case PROP_TRACKING_VALUE: case PROP_IN_PROGRESS: case PROP_STATUS_FLAGS: case PROP_BLINK_WARN_ENABLE: case PROP_EGRESS_TIME: case PROP_EGRESS_ACTIVE: case PROP_DEFAULT_FADE_TIME: case PROP_DEFAULT_RAMP_RATE: case PROP_DEFAULT_STEP_INCREMENT: case PROP_PRIORITY_ARRAY: case PROP_RELINQUISH_DEFAULT: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }