Refactored RP, WP, RPM to reduce coupling with objects for Linux and Win32 ports.

This commit is contained in:
skarg
2010-02-10 16:27:31 +00:00
parent a7de276acc
commit f0863c0238
69 changed files with 2734 additions and 1710 deletions
+1 -1
View File
@@ -94,7 +94,7 @@ iamrouter: demo/iamrouter/Makefile
initrouter: demo/initrouter/Makefile
( cd demo/initrouter ; make ; cp bacinitr ../../bin )
ports: atmega168 at91sam7s bdk-atxx4-mstp
ports: atmega168 bdk-atxx4-mstp at91sam7s
echo "Built the ports"
atmega168: ports/atmega168/Makefile
-2
View File
@@ -117,8 +117,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -242,8 +242,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
+51 -126
View File
@@ -38,65 +38,13 @@
#include "abort.h"
#include "rp.h"
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
/* function that handles the reading of properties from objects */
static read_property_function Read_Property_Function;
static read_property_function Read_Property[MAX_BACNET_OBJECT_TYPE];
static object_valid_instance_function Valid_Instance[MAX_BACNET_OBJECT_TYPE];
void handler_read_property_object_set(
BACNET_OBJECT_TYPE object_type,
read_property_function pFunction1,
object_valid_instance_function pFunction2)
void handler_read_property_function_set(
read_property_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Read_Property[object_type] = pFunction1;
Valid_Instance[object_type] = pFunction2;
}
}
/* Encodes the property APDU and returns the length,
or sets the error, and returns -1 */
int Encode_Property_APDU(
uint8_t * apdu,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = -1;
read_property_function object_rp = NULL;
object_valid_instance_function object_valid = NULL;
/* initialize the default return values */
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
/* handle each object type */
if (object_type < MAX_BACNET_OBJECT_TYPE) {
object_rp = Read_Property[object_type];
object_valid = Valid_Instance[object_type];
}
if (object_rp && object_valid) {
/* There are handlers for this type of object */
if(object_valid(object_instance)) {
apdu_len =
object_rp(&apdu[0], object_instance, property, array_index,
error_class, error_code);
} else {
/* The specified object instance is not valid */
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
} else {
/* We don't support this object type */
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return apdu_len;
Read_Property_Function = pFunction;
}
void handler_read_property(
@@ -105,26 +53,26 @@ void handler_read_property(
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
BACNET_READ_PROPERTY_DATA rpdata;
int len = 0;
int pdu_len = 0;
int apdu_len = -1;
int npdu_len = -1;
BACNET_NPDU_DATA npdu_data;
bool error = false;
int bytes_sent = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_ADDRESS my_address;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
pdu_len =
npdu_len =
npdu_encode_pdu(&Handler_Transmit_Buffer[0], src, &my_address,
&npdu_data);
if (service_data->segmented_message) {
/* we don't support segmentation - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
@@ -132,78 +80,81 @@ void handler_read_property(
#endif
goto RP_ABORT;
}
len = rp_decode_service_request(service_request, service_len, &data);
len = rp_decode_service_request(service_request, service_len, &rpdata);
#if PRINT_ENABLED
if (len <= 0)
if (len <= 0) {
fprintf(stderr, "RP: Unable to decode Request!\n");
}
#endif
if (len < 0) {
/* bad decoding - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr, "RP: Bad Encoding. Sending Abort!\n");
#endif
goto RP_ABORT;
}
/* assume that there is an error */
error = true;
len =
Encode_Property_APDU(&Temp_Buf[0], data.object_type,
data.object_instance, data.object_property, data.array_index,
&error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, &data);
if (len > service_data->max_resp) {
/* too big for the sender - send an abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
if (Read_Property_Function) {
apdu_len = rp_ack_encode_apdu_init(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
&rpdata);
/* configure our storage */
rpdata.application_data = &Handler_Transmit_Buffer[npdu_len+apdu_len];
rpdata.application_data_len =
sizeof(Handler_Transmit_Buffer) - (npdu_len + apdu_len);
len = Read_Property_Function(&rpdata);
if (len >= 0) {
apdu_len += len;
len = rp_ack_encode_apdu_object_property_end(
&Handler_Transmit_Buffer[npdu_len+apdu_len]);
apdu_len += len;
if (apdu_len > service_data->max_resp) {
/* too big for the sender - send an abort */
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
#if PRINT_ENABLED
fprintf(stderr, "RP: Message too large. Sending Abort!\n");
fprintf(stderr, "RP: Message too large. Sending Abort!\n");
#endif
goto RP_ABORT;
} else {
goto RP_ABORT;
} else {
#if PRINT_ENABLED
fprintf(stderr, "RP: Sending Ack!\n");
fprintf(stderr, "RP: Sending Ack!\n");
#endif
error = false;
error = false;
}
}
}
if (error) {
if (len == -2) {
/* BACnet APDU too small to fit data, so proper response is Abort */
len =
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
apdu_len =
abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
#if PRINT_ENABLED
fprintf(stderr, "RP: Reply too big to fit into APDU!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
apdu_len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_READ_PROPERTY,
error_class, error_code);
rpdata.error_class, rpdata.error_code);
#if PRINT_ENABLED
fprintf(stderr, "RP: Sending Error!\n");
#endif
}
}
}
RP_ABORT:
pdu_len += len;
pdu_len = npdu_len + apdu_len;
bytes_sent =
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
datalink_send_pdu(src, &npdu_data, &Handler_Transmit_Buffer[0],
pdu_len);
#if PRINT_ENABLED
if (bytes_sent <= 0)
@@ -212,29 +163,3 @@ void handler_read_property(
return;
}
int local_read_property(
uint8_t * value,
uint8_t * status,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *Source,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
/* Try to fetch the required property */
len = Encode_Property_APDU(value, Source->objectIdentifier.type,
Source->objectIdentifier.instance, Source->propertyIdentifier,
Source->arrayIndex, error_class, error_code);
if((len >= 0) && (status != NULL)){
/* Fetch the status flags if required */
Encode_Property_APDU(status, Source->objectIdentifier.type,
Source->objectIdentifier.instance, PROP_STATUS_FLAGS,
0, error_class, error_code);
}
return(len);
}
+30 -83
View File
@@ -39,85 +39,24 @@
#include "rpm.h"
#include "handlers.h"
/* function that handles the reading of properties from objects */
static read_property_function Read_Property_Function;
static rpm_object_property_lists_function RPM_Property_List;
void handler_rpm_function_set(
read_property_function pFunction)
{
Read_Property_Function = pFunction;
}
void handler_rpm_list_set(
rpm_object_property_lists_function pFunction)
{
RPM_Property_List = pFunction;
}
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
static rpm_property_lists_function RPM_Lists[MAX_BACNET_OBJECT_TYPE];
struct property_list_t {
const int *pList;
unsigned count;
};
struct special_property_list_t {
struct property_list_t Required;
struct property_list_t Optional;
struct property_list_t Proprietary;
};
static unsigned property_list_count(
const int *pList)
{
unsigned property_count = 0;
if (pList) {
while (*pList != -1) {
property_count++;
pList++;
}
}
return property_count;
}
void handler_read_property_multiple_list_set(
BACNET_OBJECT_TYPE object_type,
rpm_property_lists_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
RPM_Lists[object_type] = pFunction;
}
}
/* for a given object type, returns the special property list */
static void RPM_Property_List(
BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList)
{
rpm_property_lists_function object_property_list = NULL;
pPropertyList->Required.pList = NULL;
pPropertyList->Optional.pList = NULL;
pPropertyList->Proprietary.pList = NULL;
if (object_type < MAX_BACNET_OBJECT_TYPE) {
object_property_list = RPM_Lists[object_type];
}
if (object_property_list) {
object_property_list(&pPropertyList->Required.pList,
&pPropertyList->Optional.pList, &pPropertyList->Proprietary.pList);
}
/* fill the count */
if (pPropertyList->Required.pList) {
pPropertyList->Required.count =
property_list_count(pPropertyList->Required.pList);
} else {
pPropertyList->Required.count = 0;
}
if (pPropertyList->Optional.pList) {
pPropertyList->Optional.count =
property_list_count(pPropertyList->Optional.pList);
} else {
pPropertyList->Optional.count = 0;
}
if (pPropertyList->Proprietary.pList) {
pPropertyList->Proprietary.count =
property_list_count(pPropertyList->Proprietary.pList);
} else {
pPropertyList->Proprietary.count = 0;
}
return;
}
static int RPM_Object_Property(
struct special_property_list_t *pPropertyList,
BACNET_PROPERTY_ID special_property,
@@ -185,8 +124,7 @@ static int RPM_Encode_Property(
int len = 0;
size_t copy_len = 0;
int apdu_len = 0;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
BACNET_READ_PROPERTY_DATA rpdata;
len =
rpm_ack_encode_apdu_object_property(&Temp_Buf[0], object_property,
@@ -196,14 +134,23 @@ static int RPM_Encode_Property(
return 0;
}
apdu_len += len;
len =
Encode_Property_APDU(&Temp_Buf[0], object_type, object_instance,
object_property, array_index, &error_class, &error_code);
len = 0;
if (Read_Property_Function) {
rpdata.error_class = ERROR_CLASS_OBJECT;
rpdata.error_code = ERROR_CODE_UNKNOWN_OBJECT;
rpdata.object_type = object_type;
rpdata.object_instance = object_instance;
rpdata.object_property = object_property;
rpdata.array_index = array_index;
rpdata.application_data = &Temp_Buf[0];
rpdata.application_data_len = sizeof(Temp_Buf);
len = Read_Property_Function(&rpdata);
}
if (len < 0) {
/* error was returned - encode that for the response */
len =
rpm_ack_encode_apdu_object_property_error(&Temp_Buf[0],
error_class, error_code);
rpdata.error_class, rpdata.error_code);
copy_len =
memcopy(&apdu[0], &Temp_Buf[0], offset + apdu_len, len, max_apdu);
if (copy_len == 0) {
+10 -19
View File
@@ -37,15 +37,12 @@
#include "abort.h"
#include "wp.h"
static write_property_function Write_Property[MAX_BACNET_OBJECT_TYPE];
static write_property_function Write_Property;
void handler_write_property_object_set(
BACNET_OBJECT_TYPE object_type,
void handler_write_property_function_set(
write_property_function pFunction)
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Write_Property[object_type] = pFunction;
}
Write_Property = pFunction;
}
void handler_write_property(
@@ -58,11 +55,8 @@ void handler_write_property(
int len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
int bytes_sent = 0;
BACNET_ADDRESS my_address;
write_property_function wp_function = NULL;
/* encode the NPDU portion of the packet */
datalink_get_my_address(&my_address);
@@ -103,11 +97,8 @@ void handler_write_property(
#endif
goto WP_ABORT;
}
if (wp_data.object_type < MAX_BACNET_OBJECT_TYPE) {
wp_function = Write_Property[wp_data.object_type];
}
if (wp_function) {
if (wp_function(&wp_data, &error_class, &error_code)) {
if (Write_Property) {
if (Write_Property(&wp_data) >= 0) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
@@ -118,19 +109,19 @@ void handler_write_property(
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
wp_data.error_class, wp_data.error_code);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Error!\n");
#endif
}
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
#if PRINT_ENABLED
fprintf(stderr, "WP: Sending Unknown Object Error!\n");
fprintf(stderr, "WP: No WP Function Set. Sending Abort!\n");
#endif
goto WP_ABORT;
}
WP_ABORT:
pdu_len += len;
-2
View File
@@ -85,8 +85,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -207,8 +207,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
+36 -32
View File
@@ -142,29 +142,30 @@ char *Analog_Input_Name(
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Analog_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
(void) array_index;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
Analog_Input_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -175,7 +176,7 @@ int Analog_Input_Encode_Property_APDU(
case PROP_PRESENT_VALUE:
apdu_len =
encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
Analog_Input_Present_Value(rpdata->object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -196,26 +197,28 @@ int Analog_Input_Encode_Property_APDU(
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
case 9997:
apdu_len = encode_application_real(&apdu[0], (float) 90.510);
/* test case for real encoding-decoding unsigned value correctly */
apdu_len = encode_application_real(&apdu[0], 90.510F);
break;
case 9998:
/* test case for unsigned encoding-decoding unsigned value correctly */
apdu_len = encode_application_unsigned(&apdu[0], 90);
break;
/* test case for signed encoding-decoding negative value correctly */
case 9999:
/* test case for signed encoding-decoding negative value correctly */
apdu_len = encode_application_signed(&apdu[0], -200);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -239,24 +242,25 @@ void testAnalogInput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
uint16_t decoded_type = 0;
BACNET_READ_PROPERTY_DATA rpdata;
/* FIXME: we should do a lot more testing here... */
len =
Analog_Input_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
Analog_Input_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_ANALOG_INPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Analog_Input_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_INPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+74 -69
View File
@@ -37,8 +37,6 @@
#include "ao.h"
#include "handlers.h"
#define MAX_ANALOG_OUTPUTS 4
/* we choose to have a NULL level in our system represented by */
/* a particular value. When the priorities are not in use, they */
/* will be relinquished (i.e. set to the NULL level). */
@@ -265,13 +263,8 @@ char *Analog_Output_Name(
}
/* return apdu len, or -1 on error */
int Analog_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Analog_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -281,17 +274,24 @@ int Analog_Output_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Output_Name(object_instance));
Analog_Output_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -300,7 +300,7 @@ int Analog_Output_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Output_Present_Value(object_instance);
real_value = Analog_Output_Present_Value(rpdata->object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
@@ -316,7 +316,7 @@ int Analog_Output_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Output_Instance_To_Index(object_instance);
object_index = Analog_Output_Instance_To_Index(rpdata->object_instance);
state = Analog_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -325,14 +325,14 @@ int Analog_Output_Encode_Property_APDU(
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index =
Analog_Output_Instance_To_Index(object_instance);
Analog_Output_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Output_Level[object_index][i] == AO_LEVEL_NULL)
@@ -347,28 +347,28 @@ int Analog_Output_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Analog_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][array_index - 1] ==
Analog_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][rpdata->array_index - 1] ==
AO_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Output_Level[object_index][array_index - 1];
Analog_Output_Level[object_index][rpdata->array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -378,17 +378,17 @@ int Analog_Output_Encode_Property_APDU(
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -397,9 +397,7 @@ int Analog_Output_Encode_Property_APDU(
/* returns true if successful */
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -407,11 +405,6 @@ bool Analog_Output_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Analog_Output_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,
@@ -431,27 +424,37 @@ bool Analog_Output_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
level = AO_LEVEL_NULL;
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
status =
Analog_Output_Present_Value_Relinquish
(wp_data->object_instance, wp_data->priority);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*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 = AO_LEVEL_NULL;
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
status =
Analog_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_OUT_OF_SERVICE:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
object_index =
Analog_Output_Instance_To_Index(wp_data->object_instance);
Analog_Output_Out_Of_Service[object_index] =
@@ -459,8 +462,8 @@ bool Analog_Output_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -480,23 +483,25 @@ void testAnalogOutput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
uint16_t decoded_type = 0;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Analog_Output_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Analog_Output_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_ANALOG_OUTPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Analog_Output_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_OUTPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+84 -92
View File
@@ -52,9 +52,6 @@ static uint8_t Analog_Value_Level[MAX_ANALOG_VALUES][BACNET_MAX_PRIORITY];
/* without changing the physical output */
static bool Analog_Value_Out_Of_Service[MAX_ANALOG_VALUES];
/* we need to have our arrays initialized before answering any calls */
static bool Analog_Value_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -99,14 +96,10 @@ void Analog_Value_Init(
{
unsigned i, j;
if (!Analog_Value_Initialized) {
Analog_Value_Initialized = true;
/* initialize all the analog output priority arrays to NULL */
for (i = 0; i < MAX_ANALOG_VALUES; i++) {
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
Analog_Value_Level[i][j] = ANALOG_LEVEL_NULL;
}
/* initialize all the analog output priority arrays to NULL */
for (i = 0; i < MAX_ANALOG_VALUES; i++) {
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
Analog_Value_Level[i][j] = ANALOG_LEVEL_NULL;
}
}
@@ -119,7 +112,6 @@ void Analog_Value_Init(
bool Analog_Value_Valid_Instance(
uint32_t object_instance)
{
Analog_Value_Init();
if (object_instance < MAX_ANALOG_VALUES)
return true;
@@ -131,7 +123,6 @@ bool Analog_Value_Valid_Instance(
unsigned Analog_Value_Count(
void)
{
Analog_Value_Init();
return MAX_ANALOG_VALUES;
}
@@ -141,7 +132,6 @@ unsigned Analog_Value_Count(
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
Analog_Value_Init();
return index;
}
@@ -153,7 +143,6 @@ unsigned Analog_Value_Instance_To_Index(
{
unsigned index = MAX_ANALOG_VALUES;
Analog_Value_Init();
if (object_instance < MAX_ANALOG_VALUES)
index = object_instance;
@@ -168,7 +157,6 @@ bool Analog_Value_Present_Value_Set(
unsigned index = 0;
bool status = false;
Analog_Value_Init();
index = Analog_Value_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_VALUES) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
@@ -195,7 +183,6 @@ float Analog_Value_Present_Value(
unsigned index = 0;
unsigned i = 0;
Analog_Value_Init();
index = Analog_Value_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_VALUES) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -224,13 +211,8 @@ char *Analog_Value_Name(
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Analog_Value_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -240,18 +222,24 @@ int Analog_Value_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Analog_Value_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
Analog_Value_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -260,7 +248,7 @@ int Analog_Value_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
real_value = Analog_Value_Present_Value(rpdata->object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
@@ -276,7 +264,7 @@ int Analog_Value_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Analog_Value_Instance_To_Index(object_instance);
object_index = Analog_Value_Instance_To_Index(rpdata->object_instance);
state = Analog_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -285,13 +273,13 @@ int Analog_Value_Encode_Property_APDU(
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Analog_Value_Level[object_index][i] ==
@@ -307,27 +295,27 @@ int Analog_Value_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Value_Level[object_index][array_index - 1] ==
object_index = Analog_Value_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Value_Level[object_index][rpdata->array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Analog_Value_Level[object_index][array_index - 1];
Analog_Value_Level[object_index][rpdata->array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -337,17 +325,17 @@ int Analog_Value_Encode_Property_APDU(
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -356,9 +344,7 @@ int Analog_Value_Encode_Property_APDU(
/* 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)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -367,12 +353,6 @@ bool Analog_Value_Write_Property(
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,
@@ -392,43 +372,53 @@ bool Analog_Value_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
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--;
Analog_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) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*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 = 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--;
Analog_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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -444,27 +434,29 @@ bool Analog_Value_Write_Property(
void testAnalog_Value(
Test * pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_VALUE;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
len =
Analog_Value_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Analog_Value_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_ANALOG_VALUE;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Analog_Value_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_ANALOG_VALUE);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+33 -26
View File
@@ -39,6 +39,8 @@
#include "device.h"
#include "arf.h"
#include "awf.h"
#include "rp.h"
#include "wp.h"
typedef struct {
uint32_t instance;
@@ -181,29 +183,30 @@ static unsigned bacfile_file_size(
}
/* return the number of bytes used, or -1 on error */
int bacfile_encode_property_apdu(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int bacfile_read_property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
char text_string[32] = { "" };
BACNET_CHARACTER_STRING char_string;
BACNET_DATE bdate;
BACNET_TIME btime;
uint8_t *apdu = NULL;
(void) array_index;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_FILE,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string, "FILE %lu", (unsigned long)object_instance);
sprintf(text_string, "FILE %lu", (unsigned long)rpdata->object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
@@ -213,7 +216,7 @@ int bacfile_encode_property_apdu(
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
bacfile_name(object_instance));
bacfile_name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -225,7 +228,7 @@ int bacfile_encode_property_apdu(
case PROP_FILE_SIZE:
apdu_len =
encode_application_unsigned(&apdu[0],
bacfile_file_size(object_instance));
bacfile_file_size(rpdata->object_instance));
break;
case PROP_MODIFICATION_DATE:
/* FIXME: get the actual value instead of April Fool's Day */
@@ -261,8 +264,8 @@ int bacfile_encode_property_apdu(
encode_application_enumerated(&apdu[0], FILE_STREAM_ACCESS);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
@@ -272,17 +275,15 @@ int bacfile_encode_property_apdu(
/* returns true if successful */
bool bacfile_write_property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
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)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
@@ -300,7 +301,11 @@ bool bacfile_write_property(
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. */
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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 {
@@ -312,22 +317,24 @@ bool bacfile_write_property(
/* 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. */
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
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;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
}
uint32_t bacfile_instance(
char *filename)
{
+58 -52
View File
@@ -31,13 +31,14 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "rp.h"
#include "wp.h"
#include "cov.h"
#include "config.h" /* the custom stuff */
#include "bi.h"
#include "handlers.h"
#define MAX_BINARY_INPUTS 5
/* stores the current value */
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
/* out of service decouples physical input from Present_Value */
@@ -148,7 +149,7 @@ unsigned Binary_Input_Instance_To_Index(
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(
BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
@@ -240,11 +241,12 @@ bool Binary_Input_Encode_Value_List(
return true;
}
static void Binary_Input_Present_Value_Set(
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
BACNET_BINARY_PV value)
{
unsigned index = 0;
bool status = false;
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
@@ -252,9 +254,10 @@ static void Binary_Input_Present_Value_Set(
Change_Of_Value[index] = true;
}
Present_Value[index] = value;
status = true;
}
return;
return status;
}
static void Binary_Input_Out_Of_Service_Set(
@@ -289,31 +292,32 @@ char *Binary_Input_Name(
/* return apdu length, or -1 on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Binary_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
uint8_t *apdu = NULL;
(void) array_index;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* note: object name must be unique in our device */
characterstring_init_ansi(&char_string,
Binary_Input_Name(object_instance));
Binary_Input_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -325,7 +329,7 @@ int Binary_Input_Encode_Property_APDU(
/* note: you need to look up the actual value */
apdu_len =
encode_application_enumerated(&apdu[0],
Binary_Input_Present_Value(object_instance));
Binary_Input_Present_Value(rpdata->object_instance));
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
@@ -333,7 +337,7 @@ int Binary_Input_Encode_Property_APDU(
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Binary_Input_Out_Of_Service(object_instance)) {
if (Binary_Input_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
true);
} else {
@@ -350,22 +354,22 @@ int Binary_Input_Encode_Property_APDU(
case PROP_OUT_OF_SERVICE:
apdu_len =
encode_application_boolean(&apdu[0],
Binary_Input_Out_Of_Service(object_instance));
Binary_Input_Out_Of_Service(rpdata->object_instance));
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -374,19 +378,12 @@ int Binary_Input_Encode_Property_APDU(
/* returns true if successful */
bool Binary_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
if (!Binary_Input_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,
@@ -395,26 +392,34 @@ bool Binary_Input_Write_Property(
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, error_class, error_code) == true) {
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);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -429,28 +434,29 @@ bool Binary_Input_Write_Property(
void testBinaryInput(
Test * pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_OUTPUT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
/* FIXME: we should do a lot more testing here... */
len =
Binary_Input_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
Binary_Input_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_BINARY_INPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Binary_Input_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_BINARY_INPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+4
View File
@@ -12,6 +12,10 @@ SRCS = bi.c \
$(SRC_DIR)/bacint.c \
$(SRC_DIR)/bacstr.c \
$(SRC_DIR)/bacreal.c \
$(SRC_DIR)/bacapp.c \
$(SRC_DIR)/bactext.c \
$(SRC_DIR)/indtext.c \
$(SRC_DIR)/datetime.c \
$(TEST_DIR)/ctest.c
TARGET = binary_input
+82 -78
View File
@@ -33,11 +33,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
#include "bo.h"
#include "handlers.h"
#define MAX_BINARY_OUTPUTS 6
/* When all the priorities are level null, the present value returns */
/* the Relinquish Default value */
#define RELINQUISH_DEFAULT BINARY_INACTIVE
@@ -159,7 +159,6 @@ static BACNET_BINARY_PV Binary_Output_Present_Value(
unsigned index = 0;
unsigned i = 0;
Binary_Output_Init();
index = Binary_Output_Instance_To_Index(object_instance);
if (index < MAX_BINARY_OUTPUTS) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -188,13 +187,8 @@ char *Binary_Output_Name(
}
/* return apdu len, or -1 on error */
int Binary_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Binary_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -205,20 +199,26 @@ int Binary_Output_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Binary_Output_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
object_instance);
rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Output_Name(object_instance));
Binary_Output_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -227,7 +227,7 @@ int Binary_Output_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_BINARY_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Output_Present_Value(object_instance);
present_value = Binary_Output_Present_Value(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -245,7 +245,7 @@ int Binary_Output_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Binary_Output_Instance_To_Index(object_instance);
object_index = Binary_Output_Instance_To_Index(rpdata->object_instance);
state = Binary_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -254,14 +254,14 @@ int Binary_Output_Encode_Property_APDU(
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index =
Binary_Output_Instance_To_Index(object_instance);
Binary_Output_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Output_Level[object_index][i] == BINARY_NULL)
@@ -276,29 +276,29 @@ int Binary_Output_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Binary_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Output_Level[object_index][array_index - 1] ==
Binary_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Output_Level[object_index][rpdata->array_index - 1] ==
BINARY_NULL)
apdu_len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Output_Level[object_index][array_index - 1];
Binary_Output_Level[object_index][rpdata->array_index - 1];
apdu_len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -319,17 +319,17 @@ int Binary_Output_Encode_Property_APDU(
encode_application_character_string(&apdu[0], &char_string);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -338,9 +338,7 @@ int Binary_Output_Encode_Property_APDU(
/* returns true if successful */
bool Binary_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -349,12 +347,6 @@ bool Binary_Output_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Binary_Output_Init();
if (!Binary_Output_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,
@@ -387,35 +379,45 @@ bool Binary_Output_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
level = BINARY_NULL;
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_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) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*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_Output_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
Binary_Output_Out_Of_Service[object_index] =
@@ -423,8 +425,8 @@ bool Binary_Output_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -444,23 +446,25 @@ void testBinaryOutput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_OUTPUT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Binary_Output_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Binary_Output_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_BINARY_OUTPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Binary_Output_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_BINARY_OUTPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+82 -78
View File
@@ -34,10 +34,10 @@
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "wp.h"
#include "rp.h"
#include "bv.h"
#include "handlers.h"
#define MAX_BINARY_VALUES 2
/* When all the priorities are level null, the present value returns */
/* the Relinquish Default value */
#define RELINQUISH_DEFAULT BINARY_INACTIVE
@@ -156,7 +156,6 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(
unsigned index = 0;
unsigned i = 0;
Binary_Value_Init();
index = Binary_Value_Instance_To_Index(object_instance);
if (index < MAX_BINARY_VALUES) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -185,13 +184,8 @@ char *Binary_Value_Name(
}
/* return apdu len, or -1 on error */
int Binary_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Binary_Value_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -201,20 +195,26 @@ int Binary_Value_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Binary_Value_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
Binary_Value_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -223,7 +223,7 @@ int Binary_Value_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
present_value = Binary_Value_Present_Value(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -241,19 +241,19 @@ int Binary_Value_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Binary_Value_Instance_To_Index(object_instance);
object_index = Binary_Value_Instance_To_Index(rpdata->object_instance);
state = Binary_Value_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Binary_Value_Instance_To_Index(object_instance);
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index = Binary_Value_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Binary_Value_Level[object_index][i] == BINARY_NULL)
@@ -268,28 +268,28 @@ int Binary_Value_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Binary_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Value_Level[object_index][array_index] ==
object_index = Binary_Value_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Value_Level[object_index][rpdata->array_index] ==
BINARY_NULL)
apdu_len = encode_application_null(&apdu[apdu_len]);
else {
present_value =
Binary_Value_Level[object_index][array_index];
Binary_Value_Level[object_index][rpdata->array_index];
apdu_len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -300,17 +300,17 @@ int Binary_Value_Encode_Property_APDU(
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -319,9 +319,7 @@ int Binary_Value_Encode_Property_APDU(
/* 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)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -330,12 +328,6 @@ bool Binary_Value_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Binary_Value_Init();
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,
@@ -368,42 +360,52 @@ bool Binary_Value_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
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) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -423,23 +425,25 @@ void testBinary_Value(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_BINARY_VALUE;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Binary_Value_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Binary_Value_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_BINARY_VALUE;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Binary_Value_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_BINARY_VALUE);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+494 -126
View File
@@ -34,11 +34,24 @@
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "wp.h" /* write property handling */
#include "rp.h" /* read property handling */
#include "version.h"
#include "device.h" /* me */
#include "handlers.h"
#include "datalink.h"
#include "address.h"
/* include the objects */
#include "device.h"
#include "ai.h"
#include "ao.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
#include "bv.h"
#include "lc.h"
#include "lsp.h"
#include "mso.h"
#include "trendlog.h"
#if defined(BACFILE)
#include "bacfile.h" /* object list dependency */
#endif
@@ -51,22 +64,279 @@
long int timezone;
#endif
static object_count_function Object_Count[MAX_BACNET_OBJECT_TYPE];
static object_index_to_instance_function
Object_Index_To_Instance[MAX_BACNET_OBJECT_TYPE];
static object_name_function Object_Name[MAX_BACNET_OBJECT_TYPE];
void Device_Object_Function_Set(
BACNET_OBJECT_TYPE object_type,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function)
static struct object_functions {
BACNET_OBJECT_TYPE Object_Type;
object_init_function Object_Init;
object_count_function Object_Count;
object_index_to_instance_function Object_Index_To_Instance;
object_valid_instance_function Object_Valid_Instance;
object_name_function Object_Name;
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] =
{
if (object_type < MAX_BACNET_OBJECT_TYPE) {
Object_Count[object_type] = count_function;
Object_Index_To_Instance[object_type] = index_function;
Object_Name[object_type] = name_function;
{OBJECT_DEVICE,
NULL,
Device_Count,
Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Name,
Device_Read_Property,
Device_Write_Property,
Device_Property_Lists},
{OBJECT_ANALOG_INPUT,
Analog_Input_Init,
Analog_Input_Count,
Analog_Input_Index_To_Instance,
Analog_Input_Valid_Instance,
Analog_Input_Name,
Analog_Input_Read_Property,
NULL,
Analog_Input_Property_Lists},
{OBJECT_ANALOG_OUTPUT,
Analog_Output_Init,
Analog_Output_Count,
Analog_Output_Index_To_Instance,
Analog_Output_Valid_Instance,
Analog_Output_Name,
Analog_Output_Read_Property,
Analog_Output_Write_Property,
Analog_Output_Property_Lists},
{OBJECT_ANALOG_VALUE,
Analog_Value_Init,
Analog_Value_Count,
Analog_Value_Index_To_Instance,
Analog_Value_Valid_Instance,
Analog_Value_Name,
Analog_Value_Read_Property,
Analog_Value_Write_Property,
Analog_Value_Property_Lists},
{OBJECT_BINARY_INPUT,
Binary_Input_Init,
Binary_Input_Count,
Binary_Input_Index_To_Instance,
Binary_Input_Valid_Instance,
Binary_Input_Name,
Binary_Input_Read_Property,
NULL,
Binary_Input_Property_Lists},
{OBJECT_BINARY_OUTPUT,
Binary_Output_Init,
Binary_Output_Count,
Binary_Output_Index_To_Instance,
Binary_Output_Valid_Instance,
Binary_Output_Name,
Binary_Output_Read_Property,
Binary_Output_Write_Property,
Binary_Output_Property_Lists},
{OBJECT_BINARY_VALUE,
Binary_Value_Init,
Binary_Value_Count,
Binary_Value_Index_To_Instance,
Binary_Value_Valid_Instance,
Binary_Value_Name,
Binary_Value_Read_Property,
Binary_Value_Write_Property,
Binary_Value_Property_Lists},
{OBJECT_LIFE_SAFETY_POINT,
Life_Safety_Point_Init,
Life_Safety_Point_Count,
Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Valid_Instance,
Life_Safety_Point_Name,
Life_Safety_Point_Read_Property,
Life_Safety_Point_Write_Property,
Life_Safety_Point_Property_Lists},
{OBJECT_LOAD_CONTROL,
Load_Control_Init,
Load_Control_Count,
Load_Control_Index_To_Instance,
Load_Control_Valid_Instance,
Load_Control_Name,
Load_Control_Read_Property,
Load_Control_Write_Property,
Load_Control_Property_Lists},
{OBJECT_MULTI_STATE_OUTPUT,
Multistate_Output_Init,
Multistate_Output_Count,
Multistate_Output_Index_To_Instance,
Multistate_Output_Valid_Instance,
Multistate_Output_Name,
Multistate_Output_Read_Property,
Multistate_Output_Write_Property,
Multistate_Output_Property_Lists},
{OBJECT_TRENDLOG,
Trend_Log_Init,
Trend_Log_Count,
Trend_Log_Index_To_Instance,
Trend_Log_Valid_Instance,
Trend_Log_Name,
Trend_Log_Read_Property,
Trend_Log_Write_Property,
Trend_Log_Property_Lists},
#if defined(BACFILE)
{OBJECT_FILE,
bacfile_init,
bacfile_count,
bacfile_index_to_instance,
bacfile_valid_instance,
bacfile_name,
bacfile_read_property,
bacfile_write_property,
BACfile_Property_Lists},
#endif
{-1, NULL, NULL, NULL, NULL, NULL, NULL, NULL}
};
/* Encodes the property APDU and returns the length,
or sets the error, and returns -1 */
int Device_Objects_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = -1;
unsigned index = 0;
struct object_functions *pObject = NULL;
bool found = false;
/* initialize the default return values */
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
/* handle each object type */
if (pObject->Object_Type == rpdata->object_type) {
found = true;
if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(rpdata->object_instance)) {
if (pObject->Object_Read_Property) {
apdu_len = pObject->Object_Read_Property(rpdata);
}
} else {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
}
index++;
pObject = &Object_Table[index];
}
if (!found) {
rpdata->error_class = ERROR_CLASS_OBJECT;
rpdata->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return apdu_len;
}
bool Device_Objects_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
int apdu_len = -1;
unsigned index = 0;
struct object_functions *pObject = NULL;
bool found = false;
/* initialize the default return values */
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
/* handle each object type */
if (pObject->Object_Type == wp_data->object_type) {
found = true;
if (pObject->Object_Valid_Instance &&
pObject->Object_Valid_Instance(wp_data->object_instance)) {
if (pObject->Object_Write_Property) {
apdu_len = pObject->Object_Write_Property(wp_data);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
}
} else {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
}
index++;
pObject = &Object_Table[index];
}
if (!found) {
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
}
return apdu_len;
}
static unsigned property_list_count(
const int *pList)
{
unsigned property_count = 0;
if (pList) {
while (*pList != -1) {
property_count++;
pList++;
}
}
return property_count;
}
/* for a given object type, returns the special property list */
static void Device_Objects_Property_List(
BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList)
{
rpm_property_lists_function object_property_list = NULL;
unsigned index = 0;
struct object_functions *pObject = NULL;
bool found = false;
pPropertyList->Required.pList = NULL;
pPropertyList->Optional.pList = NULL;
pPropertyList->Proprietary.pList = NULL;
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
/* handle each object type */
if (pObject->Object_Type == object_type) {
found = true;
object_property_list = pObject->Object_RPM_List;
break;
}
index++;
pObject = &Object_Table[index];
}
if (found && object_property_list) {
object_property_list(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
}
/* fill the count */
if (pPropertyList->Required.pList) {
pPropertyList->Required.count =
property_list_count(pPropertyList->Required.pList);
} else {
pPropertyList->Required.count = 0;
}
if (pPropertyList->Optional.pList) {
pPropertyList->Optional.count =
property_list_count(pPropertyList->Optional.pList);
} else {
pPropertyList->Optional.count = 0;
}
if (pPropertyList->Proprietary.pList) {
pPropertyList->Proprietary.count =
property_list_count(pPropertyList->Proprietary.pList);
} else {
pPropertyList->Proprietary.count = 0;
}
return;
}
/* These three arrays are used by the ReadPropertyMultiple handler */
@@ -184,6 +454,17 @@ static uint32_t Database_Revision = 0;
/* Slave_Address_Binding */
/* Profile_Name */
unsigned Device_Count(void)
{
return 1;
}
uint32_t Device_Index_To_Instance(
unsigned index)
{
return Object_Instance_Number;
}
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(
void)
@@ -215,6 +496,16 @@ bool Device_Valid_Object_Instance_Number(
(object_id == BACNET_MAX_INSTANCE));
}
char *Device_Name(
uint32_t object_instance)
{
if (object_instance == Object_Instance_Number) {
return My_Object_Name;
}
return NULL;
}
const char *Device_Object_Name(
void)
{
@@ -469,13 +760,18 @@ void Device_Inc_Database_Revision(
unsigned Device_Object_List_Count(
void)
{
unsigned count = 1; /* 1 for the device object */
unsigned i = 0; /* loop counter */
unsigned count = 0; /* number of objects */
unsigned index = 0; /* loop counter */
struct object_functions *pObject = NULL;
for (i = 0; i < MAX_BACNET_OBJECT_TYPE; i++) {
if (Object_Count[i]) {
count += Object_Count[i] ();
/* initialize the default return values */
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
if (pObject->Object_Count) {
count += pObject->Object_Count();
}
index++;
pObject = &Object_Table[index];
}
return count;
@@ -487,38 +783,32 @@ bool Device_Object_List_Identifier(
uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
unsigned count = 0;
unsigned i = 0; /* loop counter */
unsigned object_index = 0;
unsigned index = 0; /* loop counter */
struct object_functions *pObject = NULL;
/* array index zero is length - so invalid */
if (array_index == 0) {
return status;
}
/* device object */
if (array_index == 1) {
*object_type = OBJECT_DEVICE;
*instance = Object_Instance_Number;
status = true;
}
if (!status) {
/* array index starts at 1, and if we are this far,
we are not the device object, so array_index must
be at least 2. */
object_index = array_index - 2;
/* look through the objects to find the right index */
for (i = 0; i < MAX_BACNET_OBJECT_TYPE; i++) {
if (Object_Count[i] && Object_Index_To_Instance[i]) {
object_index -= count;
count = Object_Count[i] ();
if (object_index < count) {
*object_type = i;
*instance = Object_Index_To_Instance[i] (object_index);
status = true;
break;
}
object_index = array_index - 1;
/* initialize the default return values */
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
if (pObject->Object_Count &&
pObject->Object_Index_To_Instance) {
object_index -= count;
count = pObject->Object_Count();
if (object_index < count) {
*object_type = pObject->Object_Type;
*instance = pObject->Object_Index_To_Instance(object_index);
status = true;
break;
}
}
index++;
pObject = &Object_Table[index];
}
return status;
@@ -563,20 +853,20 @@ char *Device_Valid_Object_Id(
uint32_t object_instance)
{
char *name = NULL; /* return value */
object_name_function name_function = NULL;
unsigned index = 0; /* loop counter */
struct object_functions *pObject = NULL;
if (object_type < MAX_BACNET_OBJECT_TYPE) {
name_function = Object_Name[object_type];
}
if (name_function) {
name = name_function(object_instance);
} else {
if ((object_type == OBJECT_DEVICE) &&
(object_instance == Object_Instance_Number)) {
name = My_Object_Name;
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
if ((pObject->Object_Type == object_type) &&
(pObject->Object_Name)) {
name = pObject->Object_Name(object_instance);
break;
}
index++;
pObject = &Object_Table[index];
}
return name;
}
@@ -647,13 +937,8 @@ int tm_isdst Daylight Savings flag.
/* return the length of the apdu encoded or -1 for error or
-2 for abort message */
int Device_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Device_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
@@ -663,9 +948,17 @@ int Device_Encode_Property_APDU(
int object_type = 0;
uint32_t instance = 0;
unsigned count = 0;
uint8_t *apdu = NULL;
struct object_functions *pObject = NULL;
bool found = false;
object_instance = object_instance;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
@@ -763,28 +1056,38 @@ int Device_Encode_Property_APDU(
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
if ((i == OBJECT_DEVICE) || Object_Count[i]) {
bitstring_set_bit(&bit_string, i, true);
} else {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* set the object types with objects to supported */
i = 0;
pObject = &Object_Table[i];
while (pObject->Object_Type != -1) {
if ((pObject->Object_Count) &&
(pObject->Object_Count() > 0)) {
bitstring_set_bit(&bit_string, pObject->Object_Type, true);
}
i++;
pObject = &Object_Table[i];
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
found = Device_Object_List_Identifier(
i,
&object_type,
&instance);
if (found) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
@@ -798,21 +1101,24 @@ int Device_Encode_Property_APDU(
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
found = Device_Object_List_Identifier(
rpdata->array_index,
&object_type,
&instance);
if (found) {
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -855,17 +1161,17 @@ int Device_Encode_Property_APDU(
apdu_len = handler_cov_encode_subscriptions(&apdu[0], MAX_APDU);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_OBJECT_LIST) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_OBJECT_LIST) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -874,20 +1180,13 @@ int Device_Encode_Property_APDU(
/* returns true if successful */
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
int temp;
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,
@@ -896,96 +1195,149 @@ bool Device_Write_Property(
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_OBJECT_ID, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_OBJECT_ID,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
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;
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_NUMBER_OF_APDU_RETRIES:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* FIXME: bounds check? */
apdu_retries_set((uint8_t) value.type.Unsigned_Int);
}
break;
case PROP_APDU_TIMEOUT:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* FIXME: bounds check? */
apdu_timeout_set((uint16_t) value.type.Unsigned_Int);
}
break;
case PROP_VENDOR_IDENTIFIER:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* FIXME: bounds check? */
Device_Set_Vendor_Identifier((uint16_t) value.type.Unsigned_Int);
Device_Set_Vendor_Identifier((uint16_t) value.
type.Unsigned_Int);
}
break;
case PROP_SYSTEM_STATUS:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, error_class, error_code) == true) {
temp = Device_Set_System_Status((BACNET_DEVICE_STATUS) value.type.Enumerated, false);
if(temp == 0)
status = true;
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = temp == -1 ? ERROR_CODE_VALUE_OUT_OF_RANGE : ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
temp = Device_Set_System_Status((BACNET_DEVICE_STATUS)
value.type.Enumerated, false);
if (temp != 0) {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
if (temp == -1) {
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
} else {
wp_data->error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
}
}
}
break;
case PROP_OBJECT_NAME:
if((status = WPValidateString(&value, MAX_DEV_LOC_LEN, false, error_class, error_code)) == true)
status = WPValidateString(&value,
MAX_DEV_LOC_LEN,
false,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
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)
status = WPValidateString(&value,
MAX_DEV_LOC_LEN,
true,
&wp_data->error_class, &wp_data->error_code);
if (status) {
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)
status = WPValidateString(&value,
MAX_DEV_DESC_LEN,
true,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
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)
status = WPValidateString(&value,
MAX_DEV_MOD_LEN,
true,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
Device_Set_Model_Name(characterstring_value(&value.type.Character_String), characterstring_length(&value.type.Character_String));
}
break;
#if defined(BACDL_MSTP)
case PROP_MAX_INFO_FRAMES:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
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;
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_MAX_MASTER:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
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;
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -995,6 +1347,22 @@ bool Device_Write_Property(
void Device_Init(
void)
{
unsigned index = 0; /* loop counter */
struct object_functions *pObject = NULL;
handler_read_property_function_set(Device_Objects_Read_Property);
handler_rpm_function_set(Device_Objects_Read_Property);
handler_rpm_list_set(Device_Objects_Property_List);
handler_write_property_function_set(Device_Objects_Write_Property);
pObject = &Object_Table[0];
while (pObject->Object_Type != -1) {
if (pObject->Object_Init) {
pObject->Object_Init();
}
index++;
pObject = &Object_Table[index];
}
}
bool DeviceGetRRInfo(
+124 -109
View File
@@ -136,9 +136,6 @@ static float Shed_Level_Values[MAX_SHED_LEVELS] = {
};
/* we need to have our arrays initialized before answering any calls */
static bool Load_Control_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Load_Control_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
@@ -189,29 +186,26 @@ void Load_Control_Init(
{
unsigned i, j;
if (!Load_Control_Initialized) {
Load_Control_Initialized = true;
for (i = 0; i < MAX_LOAD_CONTROLS; i++) {
/* FIXME: load saved data? */
Present_Value[i] = BACNET_SHED_INACTIVE;
Requested_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Requested_Shed_Level[i].value.level = 0;
datetime_wildcard_set(&Start_Time[i]);
datetime_wildcard_set(&End_Time[i]);
datetime_wildcard_set(&Current_Time);
Shed_Duration[i] = 0;
Duty_Window[i] = 0;
Load_Control_Enable[i] = true;
Full_Duty_Baseline[i] = 1.500; /* kilowatts */
Expected_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Expected_Shed_Level[i].value.level = 0;
Actual_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Actual_Shed_Level[i].value.level = 0;
Load_Control_Request_Written[i] = false;
Start_Time_Property_Written[i] = false;
for (j = 0; j < MAX_SHED_LEVELS; j++) {
Shed_Levels[i][j] = j + 1;
}
for (i = 0; i < MAX_LOAD_CONTROLS; i++) {
/* FIXME: load saved data? */
Present_Value[i] = BACNET_SHED_INACTIVE;
Requested_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Requested_Shed_Level[i].value.level = 0;
datetime_wildcard_set(&Start_Time[i]);
datetime_wildcard_set(&End_Time[i]);
datetime_wildcard_set(&Current_Time);
Shed_Duration[i] = 0;
Duty_Window[i] = 0;
Load_Control_Enable[i] = true;
Full_Duty_Baseline[i] = 1.500; /* kilowatts */
Expected_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Expected_Shed_Level[i].value.level = 0;
Actual_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Actual_Shed_Level[i].value.level = 0;
Load_Control_Request_Written[i] = false;
Start_Time_Property_Written[i] = false;
for (j = 0; j < MAX_SHED_LEVELS; j++) {
Shed_Levels[i][j] = j + 1;
}
}
@@ -224,7 +218,6 @@ void Load_Control_Init(
bool Load_Control_Valid_Instance(
uint32_t object_instance)
{
Load_Control_Init();
if (object_instance < MAX_LOAD_CONTROLS)
return true;
@@ -236,7 +229,6 @@ bool Load_Control_Valid_Instance(
unsigned Load_Control_Count(
void)
{
Load_Control_Init();
return MAX_LOAD_CONTROLS;
}
@@ -246,7 +238,6 @@ unsigned Load_Control_Count(
uint32_t Load_Control_Index_To_Instance(
unsigned index)
{
Load_Control_Init();
return index;
}
@@ -258,7 +249,6 @@ unsigned Load_Control_Instance_To_Index(
{
unsigned index = MAX_LOAD_CONTROLS;
Load_Control_Init();
if (object_instance < MAX_LOAD_CONTROLS)
index = object_instance;
@@ -271,7 +261,6 @@ static BACNET_SHED_STATE Load_Control_Present_Value(
BACNET_SHED_STATE value = BACNET_SHED_INACTIVE;
unsigned index = 0;
Load_Control_Init();
index = Load_Control_Instance_To_Index(object_instance);
if (index < MAX_LOAD_CONTROLS) {
value = Present_Value[index];
@@ -666,7 +655,6 @@ void Load_Control_State_Machine_Handler(
unsigned i = 0;
static bool initialized = false;
Load_Control_Init();
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_LOAD_CONTROLS; i++) {
@@ -689,13 +677,8 @@ void Load_Control_State_Machine_Handler(
}
/* return apdu len, or -1 on error */
int Load_Control_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Load_Control_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -705,19 +688,25 @@ int Load_Control_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Load_Control_Init();
object_index = Load_Control_Instance_To_Index(object_instance);
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
object_index = Load_Control_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_LOAD_CONTROL,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Load_Control_Name(object_instance));
Load_Control_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -726,7 +715,7 @@ int Load_Control_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], OBJECT_LOAD_CONTROL);
break;
case PROP_PRESENT_VALUE:
enumeration = Load_Control_Present_Value(object_instance);
enumeration = Load_Control_Present_Value(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], enumeration);
break;
case PROP_STATUS_FLAGS:
@@ -841,12 +830,12 @@ int Load_Control_Encode_Property_APDU(
break;
case PROP_SHED_LEVELS:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], MAX_SHED_LEVELS);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
apdu_len = 0;
for (i = 0; i < MAX_SHED_LEVELS; i++) {
/* FIXME: check if we have room before adding it to APDU */
@@ -857,32 +846,32 @@ int Load_Control_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
if (array_index <= MAX_SHED_LEVELS) {
if (rpdata->array_index <= MAX_SHED_LEVELS) {
apdu_len =
encode_application_unsigned(&apdu[0],
Shed_Levels[object_index][array_index - 1]);
Shed_Levels[object_index][rpdata->array_index - 1]);
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_SHED_LEVEL_DESCRIPTIONS:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], MAX_SHED_LEVELS);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
apdu_len = 0;
for (i = 0; i < MAX_SHED_LEVELS; i++) {
/* FIXME: check if we have room before adding it to APDU */
@@ -895,39 +884,39 @@ int Load_Control_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
if (array_index <= MAX_SHED_LEVELS) {
if (rpdata->array_index <= MAX_SHED_LEVELS) {
characterstring_init_ansi(&char_string,
Shed_Level_Descriptions[array_index - 1]);
Shed_Level_Descriptions[rpdata->array_index - 1]);
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_SHED_LEVEL_DESCRIPTIONS) &&
(property != PROP_SHED_LEVELS) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_SHED_LEVEL_DESCRIPTIONS) &&
(rpdata->object_property != PROP_SHED_LEVELS) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -936,9 +925,7 @@ int Load_Control_Encode_Property_APDU(
/* returns true if successful */
bool Load_Control_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -946,12 +933,6 @@ bool Load_Control_Write_Property(
BACNET_APPLICATION_DATA_VALUE value;
BACNET_DATE TempDate; /* build here in case of error in time half of datetime */
Load_Control_Init();
if (!Load_Control_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,
@@ -988,8 +969,8 @@ bool Load_Control_Write_Property(
status = true;
} else {
/* error! */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
if (status) {
Load_Control_Request_Written[object_index] = true;
@@ -997,65 +978,96 @@ bool Load_Control_Write_Property(
break;
case PROP_START_TIME:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_DATE, error_class, error_code)) == false)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_DATE,
&wp_data->error_class,
&wp_data->error_code);
if (!status) {
/* don't continue if we don't have a valid date */
break;
}
/* Hold the date until we are sure the time is also there */
TempDate = value.type.Date;
len = bacapp_decode_application_data(wp_data->application_data + len,
wp_data->application_data_len - len, &value);
if (len && ((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_TIME, error_class, error_code)) == true)) {
/* Write time and date and set written flag */
Start_Time[object_index].date = TempDate;
Start_Time[object_index].time = value.type.Time;
Start_Time_Property_Written[object_index] = true;
if (len) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_TIME,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* Write time and date and set written flag */
Start_Time[object_index].date = TempDate;
Start_Time[object_index].time = value.type.Time;
Start_Time_Property_Written[object_index] = true;
}
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
break;
case PROP_SHED_DURATION:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
Shed_Duration[object_index] = value.type.Unsigned_Int;
Load_Control_Request_Written[object_index] = true;
}
break;
case PROP_DUTY_WINDOW:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
Duty_Window[object_index] = value.type.Unsigned_Int;
Load_Control_Request_Written[object_index] = true;
}
break;
case PROP_SHED_LEVELS:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* re-write the size of the array? */
if (wp_data->array_index == 0) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
status = false;
} else if (wp_data->array_index == BACNET_ARRAY_ALL) {
/* FIXME: write entire array */
status = true;
} else if (wp_data->array_index <= MAX_SHED_LEVELS) {
Shed_Levels[object_index][wp_data->array_index - 1] =
value.type.Unsigned_Int;
status = true;
} else {
/* FIXME: Something's missing from here so I'll just put in
* a place holder error here for the moment*/
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OTHER;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OTHER;
status = false;
}
}
break;
case PROP_ENABLE:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
Load_Control_Enable[object_index] = value.type.Boolean;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -1456,22 +1468,25 @@ void testLoadControl(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_LOAD_CONTROL;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Load_Control_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Load_Control_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_LOAD_CONTROL;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Load_Control_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_LOAD_CONTROL);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+96 -104
View File
@@ -38,8 +38,13 @@
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
<<<<<<< .mine
#include "lo.h"
=======
#include "handlers.h"
>>>>>>> .r1574
#define MAX_LIGHTING_OUTPUTS 5
@@ -79,8 +84,6 @@ static bool Lighting_Output_Out_Of_Service[MAX_LIGHTING_OUTPUTS];
/* the lighting command is what we are doing */
static uint8_t Lighting_Command_Priority = 16;
static BACNET_LIGHTING_COMMAND Lighting_Command[MAX_LIGHTING_OUTPUTS];
/* we need to have our arrays initialized before answering any calls */
static bool Lighting_Output_Initialized = false;
int Lighting_Output_Encode_Lighting_Command(
uint8_t * apdu,
@@ -136,13 +139,8 @@ int Lighting_Output_Decode_Lighting_Command(
{
int len = 0;
int apdu_len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
int type = 0; /* for decoding */
int property = 0; /* for decoding */
uint32_t unsigned_value = 0;
int i = 0; /* loop counter */
float real_value = 0.0;
/* check for value pointers */
@@ -183,20 +181,16 @@ void Lighting_Output_Init(
{
unsigned i, j;
if (!Lighting_Output_Initialized) {
Lighting_Output_Initialized = true;
/* initialize all the analog output priority arrays to NULL */
for (i = 0; i < MAX_LIGHTING_OUTPUTS; i++) {
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
Lighting_Output_Level[i][j] = LIGHTING_LEVEL_NULL;
}
Lighting_Command[i].operation = BACNET_LIGHTS_STOP;
Lighting_Output_Out_Of_Service[i] = false;
Lighting_Output_Progress[i] = LIGHTING_RELINQUISH_DEFAULT;
Lighting_Output_Min_Present_Value[i] = 0;
Lighting_Output_Max_Present_Value[i] = 100;
/* initialize all the analog output priority arrays to NULL */
for (i = 0; i < MAX_LIGHTING_OUTPUTS; i++) {
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
Lighting_Output_Level[i][j] = LIGHTING_LEVEL_NULL;
}
Lighting_Command[i].operation = BACNET_LIGHTS_STOP;
Lighting_Output_Out_Of_Service[i] = false;
Lighting_Output_Progress[i] = LIGHTING_RELINQUISH_DEFAULT;
Lighting_Output_Min_Present_Value[i] = 0;
Lighting_Output_Max_Present_Value[i] = 100;
}
return;
@@ -208,7 +202,6 @@ void Lighting_Output_Init(
bool Lighting_Output_Valid_Instance(
uint32_t object_instance)
{
Lighting_Output_Init();
if (object_instance < MAX_LIGHTING_OUTPUTS)
return true;
@@ -220,7 +213,6 @@ bool Lighting_Output_Valid_Instance(
unsigned Lighting_Output_Count(
void)
{
Lighting_Output_Init();
return MAX_LIGHTING_OUTPUTS;
}
@@ -230,7 +222,6 @@ unsigned Lighting_Output_Count(
uint32_t Lighting_Output_Index_To_Instance(
unsigned index)
{
Lighting_Output_Init();
return index;
}
@@ -242,7 +233,6 @@ unsigned Lighting_Output_Instance_To_Index(
{
unsigned index = MAX_LIGHTING_OUTPUTS;
Lighting_Output_Init();
if (object_instance < MAX_LIGHTING_OUTPUTS)
index = object_instance;
@@ -256,7 +246,6 @@ float Lighting_Output_Present_Value(
unsigned index = 0;
unsigned i = 0;
Lighting_Output_Init();
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -277,7 +266,6 @@ unsigned Lighting_Output_Present_Value_Priority(
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
Lighting_Output_Init();
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -349,7 +337,6 @@ float Lighting_Output_Progress_Value(
float value = LIGHTING_RELINQUISH_DEFAULT;
unsigned index = 0;
Lighting_Output_Init();
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
value = Lighting_Output_Progress[index];
@@ -373,13 +360,8 @@ char *Lighting_Output_Name(
}
/* return apdu len, or -1 on error */
int Lighting_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Lighting_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -389,20 +371,26 @@ int Lighting_Output_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Lighting_Output_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
object_instance);
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* object name must be unique in this device. */
/* FIXME: description could be writable and different than object name */
characterstring_init_ansi(&char_string,
Lighting_Output_Name(object_instance));
Lighting_Output_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -412,17 +400,17 @@ int Lighting_Output_Encode_Property_APDU(
OBJECT_LIGHTING_OUTPUT);
break;
case PROP_PRESENT_VALUE:
real_value = Lighting_Output_Present_Value(object_instance);
real_value = Lighting_Output_Present_Value(rpdata->object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_PROGRESS_VALUE:
real_value = Lighting_Output_Progress_Value(object_instance);
real_value = Lighting_Output_Progress_Value(rpdata->object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_LIGHTING_COMMAND:
apdu_len =
Lighting_Output_Encode_Lighting_Command(&apdu[0],
&Lighting_Command[object_instance]);
&Lighting_Command[rpdata->object_instance]);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -437,7 +425,7 @@ int Lighting_Output_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Lighting_Output_Instance_To_Index(object_instance);
object_index = Lighting_Output_Instance_To_Index(rpdata->object_instance);
state = Lighting_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -446,14 +434,14 @@ int Lighting_Output_Encode_Property_APDU(
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index =
Lighting_Output_Instance_To_Index(object_instance);
Lighting_Output_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Lighting_Output_Level[object_index][i] ==
@@ -469,29 +457,29 @@ int Lighting_Output_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Lighting_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Lighting_Output_Level[object_index][array_index - 1] ==
Lighting_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Lighting_Output_Level[object_index][rpdata->array_index - 1] ==
LIGHTING_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Lighting_Output_Level[object_index][array_index -
Lighting_Output_Level[object_index][rpdata->array_index -
1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -502,17 +490,17 @@ int Lighting_Output_Encode_Property_APDU(
apdu_len = encode_application_real(&apdu[0], real_value);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -521,9 +509,7 @@ int Lighting_Output_Encode_Property_APDU(
/* returns true if successful */
bool Lighting_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -531,12 +517,6 @@ bool Lighting_Output_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Lighting_Output_Init();
if (!Lighting_Output_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,
@@ -556,30 +536,36 @@ bool Lighting_Output_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
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 */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*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;
@@ -590,7 +576,11 @@ bool Lighting_Output_Write_Property(
&Lighting_Command[wp_data->object_instance]);
break;
case PROP_OUT_OF_SERVICE:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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);
@@ -599,8 +589,8 @@ bool Lighting_Output_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -620,23 +610,25 @@ void testLightingOutput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_LIGHTING_OUTPUT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Lighting_Output_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Lighting_Output_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_LIGHTING_OUTPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Lighting_Output_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_LIGHTING_OUTPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+53 -55
View File
@@ -33,11 +33,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
#include "lsp.h"
#include "handlers.h"
#define MAX_LIFE_SAFETY_POINTS 7
/* Here are our stored levels.*/
static BACNET_LIFE_SAFETY_MODE Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_STATE
@@ -118,7 +118,6 @@ void Life_Safety_Point_Init(
bool Life_Safety_Point_Valid_Instance(
uint32_t object_instance)
{
Life_Safety_Point_Init();
if (object_instance < MAX_LIFE_SAFETY_POINTS)
return true;
@@ -130,7 +129,6 @@ bool Life_Safety_Point_Valid_Instance(
unsigned Life_Safety_Point_Count(
void)
{
Life_Safety_Point_Init();
return MAX_LIFE_SAFETY_POINTS;
}
@@ -140,7 +138,6 @@ unsigned Life_Safety_Point_Count(
uint32_t Life_Safety_Point_Index_To_Instance(
unsigned index)
{
Life_Safety_Point_Init();
return index;
}
@@ -152,7 +149,6 @@ unsigned Life_Safety_Point_Instance_To_Index(
{
unsigned index = MAX_LIFE_SAFETY_POINTS;
Life_Safety_Point_Init();
if (object_instance < MAX_LIFE_SAFETY_POINTS)
index = object_instance;
@@ -165,7 +161,6 @@ static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(
BACNET_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
unsigned index = 0;
Life_Safety_Point_Init();
index = Life_Safety_Point_Instance_To_Index(object_instance);
if (index < MAX_LIFE_SAFETY_POINTS)
present_value = Life_Safety_Point_State[index];
@@ -188,13 +183,8 @@ char *Life_Safety_Point_Name(
}
/* return apdu len, or -1 on error */
int Life_Safety_Point_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Life_Safety_Point_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -207,18 +197,24 @@ int Life_Safety_Point_Encode_Property_APDU(
unsigned object_index = 0;
bool state = false;
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
uint8_t *apdu = NULL;
Life_Safety_Point_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_LIFE_SAFETY_POINT, object_instance);
OBJECT_LIFE_SAFETY_POINT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Life_Safety_Point_Name(object_instance));
Life_Safety_Point_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -228,7 +224,7 @@ int Life_Safety_Point_Encode_Property_APDU(
OBJECT_LIFE_SAFETY_POINT);
break;
case PROP_PRESENT_VALUE:
present_value = Life_Safety_Point_Present_Value(object_instance);
present_value = Life_Safety_Point_Present_Value(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -245,7 +241,7 @@ int Life_Safety_Point_Encode_Property_APDU(
break;
case PROP_OUT_OF_SERVICE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
Life_Safety_Point_Instance_To_Index(rpdata->object_instance);
state = Life_Safety_Point_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -256,7 +252,7 @@ int Life_Safety_Point_Encode_Property_APDU(
break;
case PROP_MODE:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
Life_Safety_Point_Instance_To_Index(rpdata->object_instance);
mode = Life_Safety_Point_Mode[object_index];
apdu_len = encode_application_enumerated(&apdu[0], mode);
break;
@@ -269,27 +265,27 @@ int Life_Safety_Point_Encode_Property_APDU(
break;
case PROP_SILENCED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
Life_Safety_Point_Instance_To_Index(rpdata->object_instance);
silenced_state = Life_Safety_Point_Silenced_State[object_index];
apdu_len = encode_application_enumerated(&apdu[0], silenced_state);
break;
case PROP_OPERATION_EXPECTED:
object_index =
Life_Safety_Point_Instance_To_Index(object_instance);
Life_Safety_Point_Instance_To_Index(rpdata->object_instance);
operation = Life_Safety_Point_Operation[object_index];
apdu_len = encode_application_enumerated(&apdu[0], operation);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -298,21 +294,13 @@ int Life_Safety_Point_Encode_Property_APDU(
/* returns true if successful */
bool Life_Safety_Point_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Life_Safety_Point_Init();
if (!Life_Safety_Point_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,
@@ -321,22 +309,30 @@ bool Life_Safety_Point_Write_Property(
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_MODE:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, error_class, error_code) == true) {
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;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
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);
@@ -345,8 +341,8 @@ bool Life_Safety_Point_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -366,23 +362,25 @@ void testLifeSafetyPoint(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_LIFE_SAFETY_POINT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Life_Safety_Point_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Life_Safety_Point_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_LIFE_SAFETY_POINT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Life_Safety_Point_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_LIFE_SAFETY_POINT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+70 -67
View File
@@ -33,13 +33,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
#include "ms-input.h"
#include "handlers.h"
#ifndef MAX_MULTISTATE_INPUTS
#define MAX_MULTISTATE_INPUTS 1
#endif
/* how many states? 0-253 is 254 states */
#ifndef MULTISTATE_NUMBER_OF_STATES
#define MULTISTATE_NUMBER_OF_STATES (254)
@@ -314,13 +312,8 @@ bool Multistate_Input_State_Text_Set(
/* return apdu len, or -1 on error */
int Multistate_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Multistate_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -330,24 +323,31 @@ int Multistate_Input_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_INPUT, object_instance);
OBJECT_MULTI_STATE_INPUT, rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string,
Multistate_Input_Name(object_instance));
Multistate_Input_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Multistate_Input_Description(object_instance));
Multistate_Input_Description(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -357,7 +357,7 @@ int Multistate_Input_Encode_Property_APDU(
OBJECT_MULTI_STATE_INPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Multistate_Input_Present_Value(object_instance);
present_value = Multistate_Input_Present_Value(rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -375,7 +375,7 @@ int Multistate_Input_Encode_Property_APDU(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index = Multistate_Input_Instance_To_Index(object_instance);
object_index = Multistate_Input_Instance_To_Index(rpdata->object_instance);
state = Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -385,19 +385,19 @@ int Multistate_Input_Encode_Property_APDU(
MULTISTATE_NUMBER_OF_STATES);
break;
case PROP_STATE_TEXT:
if (array_index == 0) {
if (rpdata->array_index == 0) {
/* Array element zero is the number of elements in the array */
apdu_len =
encode_application_unsigned(&apdu[0],
MULTISTATE_NUMBER_OF_STATES);
} else if (array_index == BACNET_ARRAY_ALL) {
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
object_index =
Multistate_Input_Instance_To_Index(object_instance);
Multistate_Input_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < MULTISTATE_NUMBER_OF_STATES; i++) {
characterstring_init_ansi(&char_string,
Multistate_Input_State_Text(object_instance, i));
Multistate_Input_State_Text(rpdata->object_instance, i));
/* FIXME: this might go beyond MAX_APDU length! */
len =
encode_application_character_string(&apdu[apdu_len],
@@ -406,42 +406,41 @@ int Multistate_Input_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU) {
apdu_len += len;
} else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Multistate_Input_Instance_To_Index(object_instance);
if (array_index <= MULTISTATE_NUMBER_OF_STATES) {
array_index--;
Multistate_Input_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= MULTISTATE_NUMBER_OF_STATES) {
characterstring_init_ansi(&char_string,
Multistate_Input_State_Text(object_instance,
array_index));
Multistate_Input_State_Text(rpdata->object_instance,
rpdata->array_index-1));
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_STATE_TEXT) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_STATE_TEXT) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -450,21 +449,13 @@ int Multistate_Input_Encode_Property_APDU(
/* returns true if successful */
bool Multistate_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Multistate_Input_Init();
if (!Multistate_Input_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,
@@ -473,23 +464,32 @@ bool Multistate_Input_Write_Property(
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
if (Out_Of_Service[object_index]) {
if (Multistate_Input_Present_Value_Set(wp_data->
object_instance, value.type.Unsigned_Int)) {
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
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;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
}
}
break;
case PROP_OUT_OF_SERVICE:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
object_index =
Multistate_Input_Instance_To_Index
(wp_data->object_instance);
@@ -497,8 +497,8 @@ bool Multistate_Input_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -518,22 +518,25 @@ void testMultistateInput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_MULTI_STATE_INPUT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Multistate_Input_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Multistate_Input_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_MULTI_STATE_INPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Multistate_Input_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_MULTI_STATE_INPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+40
View File
@@ -0,0 +1,40 @@
#Makefile to build test case
CC = gcc
SRC_DIR = ../../src
TEST_DIR = ../../test
INCLUDES = -I../../include -I$(TEST_DIR) -I.
DEFINES = -DBIG_ENDIAN=0 -DTEST -DBACAPP_ALL -DTEST_MULTISTATE_INPUT
CFLAGS = -Wall $(INCLUDES) $(DEFINES) -g
SRCS = ms-input.c \
$(SRC_DIR)/bacdcode.c \
$(SRC_DIR)/bacint.c \
$(SRC_DIR)/bacstr.c \
$(SRC_DIR)/bacreal.c \
$(SRC_DIR)/datetime.c \
$(SRC_DIR)/bacapp.c \
$(SRC_DIR)/bactext.c \
$(SRC_DIR)/indtext.c \
$(TEST_DIR)/ctest.c
TARGET = multistate_input
all: ${TARGET}
OBJS = ${SRCS:.c=.o}
${TARGET}: ${OBJS}
${CC} -o $@ ${OBJS}
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET} $(OBJS)
include: .depend
+84 -80
View File
@@ -33,11 +33,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
#include "mso.h"
#include "handlers.h"
#define MAX_MULTISTATE_OUTPUTS 4
/* When all the priorities are level null, the present value returns */
/* the Relinquish Default value */
#define MULTISTATE_RELINQUISH_DEFAULT 0
@@ -162,7 +162,6 @@ static uint32_t Multistate_Output_Present_Value(
unsigned index = 0;
unsigned i = 0;
Multistate_Output_Init();
index = Multistate_Output_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_OUTPUTS) {
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
@@ -191,13 +190,8 @@ char *Multistate_Output_Name(
}
/* return apdu len, or -1 on error */
int Multistate_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Multistate_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int len = 0;
int apdu_len = 0; /* return value */
@@ -207,20 +201,26 @@ int Multistate_Output_Encode_Property_APDU(
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
uint8_t *apdu = NULL;
Multistate_Output_Init();
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_OUTPUT, object_instance);
OBJECT_MULTI_STATE_OUTPUT, rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Multistate_Output_Name(object_instance));
Multistate_Output_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -230,7 +230,7 @@ int Multistate_Output_Encode_Property_APDU(
OBJECT_MULTI_STATE_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value = Multistate_Output_Present_Value(object_instance);
present_value = Multistate_Output_Present_Value(rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -249,20 +249,20 @@ int Multistate_Output_Encode_Property_APDU(
break;
case PROP_OUT_OF_SERVICE:
object_index =
Multistate_Output_Instance_To_Index(object_instance);
Multistate_Output_Instance_To_Index(rpdata->object_instance);
state = Multistate_Output_Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
if (rpdata->array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index =
Multistate_Output_Instance_To_Index(object_instance);
Multistate_Output_Instance_To_Index(rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Multistate_Output_Level[object_index][i] ==
@@ -279,30 +279,30 @@ int Multistate_Output_Encode_Property_APDU(
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
rpdata->error_class = ERROR_CLASS_SERVICES;
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index =
Multistate_Output_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Multistate_Output_Level[object_index][array_index -
Multistate_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Multistate_Output_Level[object_index][rpdata->array_index -
1] == MULTISTATE_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
present_value =
Multistate_Output_Level[object_index][array_index -
Multistate_Output_Level[object_index][rpdata->array_index -
1];
apdu_len =
encode_application_unsigned(&apdu[0],
present_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
@@ -319,17 +319,17 @@ int Multistate_Output_Encode_Property_APDU(
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_PRIORITY_ARRAY) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_PRIORITY_ARRAY) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -338,9 +338,7 @@ int Multistate_Output_Encode_Property_APDU(
/* returns true if successful */
bool Multistate_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -349,12 +347,6 @@ bool Multistate_Output_Write_Property(
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
Multistate_Output_Init();
if (!Multistate_Output_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,
@@ -388,37 +380,47 @@ bool Multistate_Output_Write_Property(
/* 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;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL, error_class, error_code) == true) {
level = MULTISTATE_NULL;
object_index =
Multistate_Output_Instance_To_Index
(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) 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;
} else {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
level = MULTISTATE_NULL;
object_index =
Multistate_Output_Instance_To_Index
(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) 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:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
object_index =
Multistate_Output_Instance_To_Index
(wp_data->object_instance);
@@ -427,8 +429,8 @@ bool Multistate_Output_Write_Property(
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -448,23 +450,25 @@ void testMultistateOutput(
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
BACNET_OBJECT_TYPE decoded_type = OBJECT_MULTI_STATE_OUTPUT;
uint16_t decoded_type = 0;
uint32_t decoded_instance = 0;
uint32_t instance = 123;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
BACNET_READ_PROPERTY_DATA rpdata;
len =
Multistate_Output_Encode_Property_APDU(&apdu[0], instance,
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
Multistate_Output_Init();
rpdata.application_data = &apdu[0];
rpdata.application_data_len = sizeof(apdu);
rpdata.object_type = OBJECT_MULTI_STATE_OUTPUT;
rpdata.object_instance = 1;
rpdata.object_property = PROP_OBJECT_IDENTIFIER;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Multistate_Output_Read_Property(&rpdata);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
len =
decode_object_id(&apdu[len], (int *) &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == OBJECT_MULTI_STATE_OUTPUT);
ct_test(pTest, decoded_instance == instance);
decode_object_id(&apdu[len], &decoded_type, &decoded_instance);
ct_test(pTest, decoded_type == rpdata.object_type);
ct_test(pTest, decoded_instance == rpdata.object_instance);
return;
}
+181 -92
View File
@@ -44,8 +44,6 @@
#include "bacfile.h" /* object list dependency */
#endif
#define MAX_TREND_LOGS 8
/* Error code for Trend Log storage */
typedef struct tl_error {
@@ -347,36 +345,33 @@ char *Trend_Log_Name(
/* return the length of the apdu encoded or -1 for error or
-2 for abort message */
int Trend_Log_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
int Trend_Log_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
int object_type = 0;
uint32_t instance = 0;
unsigned count = 0;
TL_LOG_INFO *CurrentLog;
uint8_t *apdu = NULL;
CurrentLog = &LogInfo[Trend_Log_Instance_To_Index(object_instance)]; /* Pin down which log to look at */
switch (property) {
if ((rpdata == NULL) ||
(rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
return 0;
}
apdu = rpdata->application_data;
CurrentLog = &LogInfo[Trend_Log_Instance_To_Index(rpdata->object_instance)]; /* Pin down which log to look at */
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_TRENDLOG,
object_instance);
rpdata->object_instance);
break;
case PROP_DESCRIPTION:
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string, Trend_Log_Name(object_instance));
characterstring_init_ansi(&char_string, Trend_Log_Name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -399,8 +394,8 @@ int Trend_Log_Encode_Property_APDU(
case PROP_LOG_BUFFER:
/* You can only read the buffer via the ReadRange service */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_READ_ACCESS_DENIED;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_READ_ACCESS_DENIED;
apdu_len = -1;
break;
@@ -482,17 +477,17 @@ int Trend_Log_Encode_Property_APDU(
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(property != PROP_EVENT_TIME_STAMPS) &&
(array_index != BACNET_ARRAY_ALL)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
(rpdata->object_property != PROP_EVENT_TIME_STAMPS) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = -1;
}
@@ -501,9 +496,7 @@ int Trend_Log_Encode_Property_APDU(
/* returns true if successful */
bool Trend_Log_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
BACNET_WRITE_PROPERTY_DATA * wp_data)
{
bool status = false; /* return value */
int len = 0;
@@ -514,14 +507,8 @@ bool Trend_Log_Write_Property(
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE TempSource;
bool bEffectiveEnable;
if (!Trend_Log_Valid_Instance(wp_data->object_instance)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
return false;
}
CurrentLog = &LogInfo[Trend_Log_Instance_To_Index(wp_data->object_instance)]; /* Pin down which log to look at */
/* Pin down which log to look at */
CurrentLog = &LogInfo[Trend_Log_Instance_To_Index(wp_data->object_instance)];
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
@@ -531,14 +518,19 @@ bool Trend_Log_Write_Property(
switch (wp_data->object_property) {
case PROP_ENABLE:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* Section 12.25.5 can't enable a full log with stop when full set */
if((CurrentLog->bEnable == false) &&
(CurrentLog->bStopWhenFull == true) &&
(CurrentLog->ulRecordCount == TL_MAX_ENTRIES) &&
(value.type.Boolean == true)) {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_LOG_BUFFER_FULL;
status = false;
wp_data->error_class = ERROR_CLASS_OBJECT;
wp_data->error_code = ERROR_CODE_LOG_BUFFER_FULL;
break;
}
@@ -549,24 +541,30 @@ bool Trend_Log_Write_Property(
/* To do: what actions do we need to take on writing ? */
if(value.type.Boolean == false) {
if(bEffectiveEnable == true) {
/* Only insert record if we really were enabled i.e. times and enable flags */
TL_Insert_Status_Rec(wp_data->object_instance, LOG_STATUS_LOG_DISABLED, true);
/* Only insert record if we really were
enabled i.e. times and enable flags */
TL_Insert_Status_Rec(wp_data->object_instance,
LOG_STATUS_LOG_DISABLED, true);
}
} else {
if(TL_Is_Enabled(wp_data->object_instance)) {
/* Have really gone from disabled to enabled as
* enable flag and times were correct
*/
TL_Insert_Status_Rec(wp_data->object_instance, LOG_STATUS_LOG_DISABLED, false);
TL_Insert_Status_Rec(wp_data->object_instance,
LOG_STATUS_LOG_DISABLED, false);
}
}
}
status = true;
}
break;
case PROP_STOP_WHEN_FULL:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* Only trigger this on a change of state */
if(CurrentLog->bStopWhenFull != value.type.Boolean) {
CurrentLog->bStopWhenFull = value.type.Boolean;
@@ -579,7 +577,8 @@ bool Trend_Log_Write_Property(
* disable the log and record the fact - see 135-2008 12.25.12
*/
CurrentLog->bEnable = false;
TL_Insert_Status_Rec(wp_data->object_instance, LOG_STATUS_LOG_DISABLED, true);
TL_Insert_Status_Rec(wp_data->object_instance,
LOG_STATUS_LOG_DISABLED, true);
}
}
}
@@ -590,12 +589,16 @@ bool Trend_Log_Write_Property(
* we would probably erase the current log, resize, re-initalise
* and carry on - however write is not allowed if enable is true.
*/
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
case PROP_RECORD_COUNT:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
if(value.type.Unsigned_Int == 0) {
/* Time to clear down the log */
CurrentLog->ulRecordCount = 0;
@@ -608,9 +611,12 @@ bool Trend_Log_Write_Property(
case PROP_LOGGING_TYPE:
/* logic
* triggered and polled options.
*/
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED, error_class, error_code) == true) {
*/
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
if(value.type.Enumerated != LOGGING_TYPE_COV) {
CurrentLog->LoggingType = value.type.Enumerated;
if(value.type.Enumerated == LOGGING_TYPE_POLLED) {
@@ -623,26 +629,37 @@ bool Trend_Log_Write_Property(
/* As per 12.25.27 0 the interval if triggered logging selected */
CurrentLog->ulLogInterval = 0;
}
status = true;
} else {
/* We don't currently support COV */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
}
}
break;
case PROP_START_TIME:
/* Copy the date part to safe place */
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_DATE, error_class, error_code) == false)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_DATE,
&wp_data->error_class,
&wp_data->error_code);
if (!status) {
break;
}
TempDate = value.type.Date;
/* Then decode the time part */
/* Then decode the time part */
len = bacapp_decode_application_data(wp_data->application_data + len,
wp_data->application_data_len - len, &value);
if (len && ((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_TIME, error_class, error_code)) == true)) {
if (len) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_TIME,
&wp_data->error_class,
&wp_data->error_code);
if (!status) {
break;
}
/* First record the current enable state of the log */
bEffectiveEnable = TL_Is_Enabled(wp_data->object_instance);
CurrentLog->StartTime.date = TempDate; /* Safe to copy the date now */
@@ -673,15 +690,26 @@ bool Trend_Log_Write_Property(
case PROP_STOP_TIME:
/* Copy the date part to safe place */
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_DATE, error_class, error_code) == false)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_DATE,
&wp_data->error_class,
&wp_data->error_code);
if (!status) {
break;
}
TempDate = value.type.Date;
/* Then decode the time part */
len = bacapp_decode_application_data(wp_data->application_data + len,
wp_data->application_data_len - len, &value);
if (len && ((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_TIME, error_class, error_code)) == true)) {
if (len) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_TIME,
&wp_data->error_class,
&wp_data->error_code);
if (!status) {
break;
}
/* First record the current enable state of the log */
bEffectiveEnable = TL_Is_Enabled(wp_data->object_instance);
CurrentLog->StopTime.date = TempDate; /* Safe to copy the date now */
@@ -718,8 +746,8 @@ bool Trend_Log_Write_Property(
len = bacapp_decode_context_data(wp_data->application_data, wp_data->application_data_len, &value, PROP_LOG_DEVICE_OBJECT_PROPERTY);
if((len == 0) || (value.context_tag != 0) || ((wp_data->application_data_len - len) == 0)) {
/* Bad decode, wrong tag or following required parameter missing */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OTHER;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OTHER;
break;
}
@@ -730,8 +758,8 @@ bool Trend_Log_Write_Property(
len = bacapp_decode_context_data(&wp_data->application_data[iOffset], wp_data->application_data_len, &value, PROP_LOG_DEVICE_OBJECT_PROPERTY);
if((len == 0) || (value.context_tag != 1)) {
/* Bad decode or wrong tag */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OTHER;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OTHER;
break;
}
@@ -744,8 +772,8 @@ bool Trend_Log_Write_Property(
len = bacapp_decode_context_data(&wp_data->application_data[iOffset], wp_data->application_data_len, &value, PROP_LOG_DEVICE_OBJECT_PROPERTY);
if((len == 0) || ((value.context_tag != 2) && (value.context_tag != 3))) {
/* Bad decode or wrong tag */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OTHER;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OTHER;
break;
}
@@ -759,8 +787,8 @@ bool Trend_Log_Write_Property(
len = bacapp_decode_context_data(&wp_data->application_data[iOffset], wp_data->application_data_len, &value, PROP_LOG_DEVICE_OBJECT_PROPERTY);
if((len == 0) || (value.context_tag != 3)) {
/* Bad decode or wrong tag */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OTHER;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OTHER;
break;
}
}
@@ -772,8 +800,8 @@ bool Trend_Log_Write_Property(
if((TempSource.deviceIndentifier.instance != Device_Object_Instance_Number()) ||
(TempSource.deviceIndentifier.type != OBJECT_DEVICE)) {
/* Not our ID so can't handle it at the moment */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
break;
}
}
@@ -795,58 +823,74 @@ bool Trend_Log_Write_Property(
case PROP_LOG_INTERVAL:
if(CurrentLog->LoggingType == LOGGING_TYPE_TRIGGERED) {
/* Read only if triggered log so flag error and bail out */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code) == true) {
if((CurrentLog->LoggingType == LOGGING_TYPE_POLLED) && (value.type.Unsigned_Int == 0)) {
/* We don't support COV at the moment so don't allow switching
* to it by clearing interval whilst in polling mode */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
if((CurrentLog->LoggingType == LOGGING_TYPE_POLLED) &&
(value.type.Unsigned_Int == 0)) {
/* We don't support COV at the moment so don't allow switching
* to it by clearing interval whilst in polling mode */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED;
status = false;
} else {
/* We only log to 1 sec accuracy so must divide by 100 before passing it on */
CurrentLog->ulLogInterval = value.type.Unsigned_Int / 100;
status = true;
}
}
break;
case PROP_ALIGN_INTERVALS:
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code)) == true)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
CurrentLog->bAlignIntervals = value.type.Boolean;
}
break;
case PROP_INTERVAL_OFFSET:
/* We only log to 1 sec accuracy so must divide by 100 before passing it on */
if((status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT, error_class, error_code)) == true)
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
CurrentLog->ulIntervalOffset = value.type.Unsigned_Int / 100;
}
break;
case PROP_TRIGGER:
if(WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN, error_class, error_code) == true) {
status = WPValidateArgType(&value,
BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* We will not allow triggered operation if polling with aligning
* to the clock as that will produce non aligned readings which
* goes against the reason for selscting this mode
*/
if((CurrentLog->LoggingType == LOGGING_TYPE_POLLED) &&
(CurrentLog->bAlignIntervals == true)) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NOT_CONFIGURED_FOR_TRIGGERED_LOGGING;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_NOT_CONFIGURED_FOR_TRIGGERED_LOGGING;
status = false;
} else {
CurrentLog->bTrigger = value.type.Boolean;
status = true;
}
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
@@ -1546,6 +1590,51 @@ int TL_encode_entry(uint8_t *apdu, int iLog, int iEntry)
return(iLen);
}
static int local_read_property(
uint8_t * value,
uint8_t * status,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *Source,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
BACNET_READ_PROPERTY_DATA rpdata;
if (value != NULL) {
/* configure our storage */
rpdata.application_data = value;
rpdata.application_data_len = MAX_APDU;
rpdata.object_type = Source->objectIdentifier.type;
rpdata.object_instance = Source->objectIdentifier.instance;
rpdata.object_property = Source->propertyIdentifier;
rpdata.array_index = Source->arrayIndex;
/* Try to fetch the required property */
len = Device_Objects_Read_Property(&rpdata);
if (len < 0) {
*error_class = rpdata.error_class;
*error_code = rpdata.error_code;
}
}
if((len >= 0) && (status != NULL)){
/* Fetch the status flags if required */
rpdata.application_data = status;
rpdata.application_data_len = MAX_APDU;
rpdata.object_property = PROP_STATUS_FLAGS;
rpdata.array_index = BACNET_ARRAY_ALL;
len = Device_Objects_Read_Property(&rpdata);
if (len < 0) {
*error_class = rpdata.error_class;
*error_code = rpdata.error_code;
}
} else {
*error_class = rpdata.error_class;
*error_code = rpdata.error_code;
}
return(len);
}
/****************************************************************************
* Attempt to fetch the logged property and store it in the Trend Log *
****************************************************************************/
+1
View File
@@ -124,6 +124,7 @@ void MyRejectHandler(
static void Init_Service_Handlers(
void)
{
Device_Init();
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -176,8 +176,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -113,8 +113,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -111,8 +111,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
+2 -92
View File
@@ -136,102 +136,12 @@ void MyRejectHandler(
/* Error_Detected = true; */
}
static void Init_Object(
BACNET_OBJECT_TYPE object_type,
rpm_property_lists_function rpm_list_function,
read_property_function rp_function,
object_valid_instance_function object_valid_function,
write_property_function wp_function,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function,
rr_info_function rr_inf_function)
{
handler_read_property_object_set(object_type, rp_function,
object_valid_function);
handler_write_property_object_set(object_type, wp_function);
handler_read_property_multiple_list_set(object_type, rpm_list_function);
Device_Object_Function_Set(object_type, count_function, index_function,
name_function);
handler_rr_object_set(object_type, rr_inf_function);
}
static void Init_Objects(
void)
{
Device_Init();
Init_Object(OBJECT_DEVICE, Device_Property_Lists,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number,
Device_Write_Property, NULL, NULL, NULL, DeviceGetRRInfo);
Analog_Input_Init();
Init_Object(OBJECT_ANALOG_INPUT, Analog_Input_Property_Lists,
Analog_Input_Encode_Property_APDU, Analog_Input_Valid_Instance, NULL,
Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Name, NULL);
Analog_Output_Init();
Init_Object(OBJECT_ANALOG_OUTPUT, Analog_Output_Property_Lists,
Analog_Output_Encode_Property_APDU, Analog_Output_Valid_Instance,
Analog_Output_Write_Property, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Name, NULL);
Analog_Value_Init();
Init_Object(OBJECT_ANALOG_VALUE, Analog_Value_Property_Lists,
Analog_Value_Encode_Property_APDU, Analog_Value_Valid_Instance,
Analog_Value_Write_Property, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Name, NULL);
Binary_Input_Init();
Init_Object(OBJECT_BINARY_INPUT, Binary_Input_Property_Lists,
Binary_Input_Encode_Property_APDU, Binary_Input_Valid_Instance, NULL,
Binary_Input_Count, Binary_Input_Index_To_Instance, Binary_Input_Name, NULL);
Binary_Output_Init();
Init_Object(OBJECT_BINARY_OUTPUT, Binary_Output_Property_Lists,
Binary_Output_Encode_Property_APDU, Binary_Output_Valid_Instance,
Binary_Output_Write_Property, Binary_Output_Count,
Binary_Output_Index_To_Instance, Binary_Output_Name, NULL);
Binary_Value_Init();
Init_Object(OBJECT_BINARY_VALUE, Binary_Value_Property_Lists,
Binary_Value_Encode_Property_APDU, Binary_Value_Valid_Instance,
Binary_Value_Write_Property, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Name, NULL);
Life_Safety_Point_Init();
Init_Object(OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Property_Lists,
Life_Safety_Point_Encode_Property_APDU,
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Write_Property,
Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Name, NULL);
Load_Control_Init();
Init_Object(OBJECT_LOAD_CONTROL, Load_Control_Property_Lists,
Load_Control_Encode_Property_APDU, Load_Control_Valid_Instance,
Load_Control_Write_Property, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Name, NULL);
Multistate_Output_Init();
Init_Object(OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Property_Lists,
Multistate_Output_Encode_Property_APDU,
Multistate_Output_Valid_Instance, Multistate_Output_Write_Property,
Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Name, NULL);
Trend_Log_Init();
Init_Object(OBJECT_TRENDLOG, Trend_Log_Property_Lists,
Trend_Log_Encode_Property_APDU,
Trend_Log_Valid_Instance, Trend_Log_Write_Property,
Trend_Log_Count, Trend_Log_Index_To_Instance,
Trend_Log_Name, TrendLogGetRRInfo);
#if defined(BACFILE)
bacfile_init();
Init_Object(OBJECT_FILE, BACfile_Property_Lists,
bacfile_encode_property_apdu, bacfile_valid_instance,
bacfile_write_property, bacfile_count, bacfile_index_to_instance,
bacfile_name, NULL);
#endif
handler_rr_object_set(OBJECT_DEVICE, DeviceGetRRInfo);
handler_rr_object_set(OBJECT_TRENDLOG, TrendLogGetRRInfo);
}
static void Init_Service_Handlers(
-2
View File
@@ -115,8 +115,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
+2 -101
View File
@@ -47,116 +47,18 @@
#include "txbuf.h"
#include "lc.h"
#include "version.h"
/* include the objects */
/* include the device object */
#include "device.h"
#include "ai.h"
#include "ao.h"
#include "av.h"
#include "bi.h"
#include "bo.h"
#include "bv.h"
#include "lc.h"
#include "lsp.h"
#include "mso.h"
#include "bacfile.h"
/* This is an example server application using the BACnet Stack */
/* buffers used for receiving */
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
static void Init_Object(
BACNET_OBJECT_TYPE object_type,
rpm_property_lists_function rpm_list_function,
read_property_function rp_function,
object_valid_instance_function object_valid_function,
write_property_function wp_function,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function)
{
handler_read_property_object_set(object_type, rp_function,
object_valid_function);
handler_write_property_object_set(object_type, wp_function);
handler_read_property_multiple_list_set(object_type, rpm_list_function);
Device_Object_Function_Set(object_type, count_function, index_function,
name_function);
}
static void Init_Objects(
void)
{
Device_Init();
Init_Object(OBJECT_DEVICE, Device_Property_Lists,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number,
Device_Write_Property, NULL, NULL, NULL);
Analog_Input_Init();
Init_Object(OBJECT_ANALOG_INPUT, Analog_Input_Property_Lists,
Analog_Input_Encode_Property_APDU, Analog_Input_Valid_Instance, NULL,
Analog_Input_Count, Analog_Input_Index_To_Instance, Analog_Input_Name);
Analog_Output_Init();
Init_Object(OBJECT_ANALOG_OUTPUT, Analog_Output_Property_Lists,
Analog_Output_Encode_Property_APDU, Analog_Output_Valid_Instance,
Analog_Output_Write_Property, Analog_Output_Count,
Analog_Output_Index_To_Instance, Analog_Output_Name);
Analog_Value_Init();
Init_Object(OBJECT_ANALOG_VALUE, Analog_Value_Property_Lists,
Analog_Value_Encode_Property_APDU, Analog_Value_Valid_Instance,
Analog_Value_Write_Property, Analog_Value_Count,
Analog_Value_Index_To_Instance, Analog_Value_Name);
Binary_Input_Init();
Init_Object(OBJECT_BINARY_INPUT, Binary_Input_Property_Lists,
Binary_Input_Encode_Property_APDU, Binary_Input_Valid_Instance, NULL,
Binary_Input_Count, Binary_Input_Index_To_Instance, Binary_Input_Name);
Binary_Output_Init();
Init_Object(OBJECT_BINARY_OUTPUT, Binary_Output_Property_Lists,
Binary_Output_Encode_Property_APDU, Binary_Output_Valid_Instance,
Binary_Output_Write_Property, Binary_Output_Count,
Binary_Output_Index_To_Instance, Binary_Output_Name);
Binary_Value_Init();
Init_Object(OBJECT_BINARY_VALUE, Binary_Value_Property_Lists,
Binary_Value_Encode_Property_APDU, Binary_Value_Valid_Instance,
Binary_Value_Write_Property, Binary_Value_Count,
Binary_Value_Index_To_Instance, Binary_Value_Name);
Life_Safety_Point_Init();
Init_Object(OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Property_Lists,
Life_Safety_Point_Encode_Property_APDU,
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Write_Property,
Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance,
Life_Safety_Point_Name);
Load_Control_Init();
Init_Object(OBJECT_LOAD_CONTROL, Load_Control_Property_Lists,
Load_Control_Encode_Property_APDU, Load_Control_Valid_Instance,
Load_Control_Write_Property, Load_Control_Count,
Load_Control_Index_To_Instance, Load_Control_Name);
Multistate_Output_Init();
Init_Object(OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Property_Lists,
Multistate_Output_Encode_Property_APDU,
Multistate_Output_Valid_Instance, Multistate_Output_Write_Property,
Multistate_Output_Count, Multistate_Output_Index_To_Instance,
Multistate_Output_Name);
#if defined(BACFILE)
bacfile_init();
Init_Object(OBJECT_FILE, BACfile_Property_Lists,
bacfile_encode_property_apdu, bacfile_valid_instance,
bacfile_write_property, bacfile_count, bacfile_index_to_instance,
bacfile_name);
#endif
}
static void Init_Service_Handlers(
void)
{
Device_Init();
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_HAS, handler_who_has);
@@ -219,7 +121,6 @@ int main(
printf("BACnet Server Demo\n" "BACnet Stack Version %s\n"
"BACnet Device ID: %u\n" "Max APDU: %d\n", BACnet_Version,
Device_Object_Instance_Number(), MAX_APDU);
Init_Objects();
Init_Service_Handlers();
dlenv_init();
atexit(cleanup);
-2
View File
@@ -87,8 +87,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -54,8 +54,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -90,8 +90,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -90,8 +90,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* Note: this applications doesn't need to handle who-is
it is confusing for the user! */
/* set the handler for all the services we don't implement
-2
View File
@@ -170,8 +170,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -133,8 +133,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
-2
View File
@@ -131,8 +131,6 @@ static void Init_Service_Handlers(
void)
{
Device_Init();
handler_read_property_object_set(OBJECT_DEVICE,
Device_Encode_Property_APDU, Device_Valid_Object_Instance_Number);
/* we need to handle who-is
to support dynamic device binding to us */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
+8 -11
View File
@@ -28,15 +28,15 @@
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "rp.h"
#ifndef MAX_ANALOG_INPUTS
#define MAX_ANALOG_INPUTS 7
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
@@ -71,18 +71,15 @@ extern "C" {
uint32_t Analog_Input_Units(
uint32_t instance);
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Analog_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
float Analog_Input_Present_Value(
uint32_t object_instance);
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value);
void Analog_Input_Init(
void);
+8 -11
View File
@@ -29,8 +29,13 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_ANALOG_OUTPUTS
#define MAX_ANALOG_OUTPUTS 4
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -84,18 +89,10 @@ extern "C" {
void Analog_Output_Init(
void);
int Analog_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Analog_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+4 -10
View File
@@ -30,6 +30,7 @@
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#include "rp.h"
#ifndef MAX_ANALOG_VALUES
#define MAX_ANALOG_VALUES 4
@@ -51,18 +52,11 @@ extern "C" {
char *Analog_Value_Name(
uint32_t object_instance);
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Analog_Value_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
bool Analog_Value_Present_Value_Set(
uint32_t object_instance,
+5 -10
View File
@@ -41,6 +41,8 @@
#include "apdu.h"
#include "arf.h"
#include "awf.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
extern "C" {
@@ -78,19 +80,12 @@ extern "C" {
void);
/* handling for read property service */
int bacfile_encode_property_apdu(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int bacfile_read_property(
BACNET_READ_PROPERTY_DATA *rpdata);
/* handling for write property service */
bool bacfile_write_property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef __cplusplus
}
+8 -11
View File
@@ -30,6 +30,10 @@
#include "bacdef.h"
#include "cov.h"
#ifndef MAX_BINARY_INPUTS
#define MAX_BINARY_INPUTS 5
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -81,18 +85,11 @@ extern "C" {
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list);
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Binary_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Binary_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
void Binary_Input_Init(
void);
BACNET_BINARY_PV Binary_Input_Present_Value(
@@ -100,7 +97,7 @@ extern "C" {
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
bool value);
BACNET_BINARY_PV value);
#ifdef TEST
#include "ctest.h"
+7 -10
View File
@@ -31,6 +31,10 @@
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_BINARY_OUTPUTS
#define MAX_BINARY_OUTPUTS 6
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -77,18 +81,11 @@ extern "C" {
uint32_t instance,
char *new_name);
int Binary_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Binary_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Binary_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
void Binary_Output_Level_Sync(
unsigned int index);
+4 -11
View File
@@ -29,13 +29,13 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_BINARY_VALUES
#define MAX_BINARY_VALUES 10
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -56,18 +56,11 @@ extern "C" {
void Binary_Value_Init(
void);
int Binary_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Binary_Value_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+19 -16
View File
@@ -39,8 +39,12 @@
#include "bacdef.h"
#include "bacenum.h"
#include "wp.h"
#include "rp.h"
#include "readrange.h"
typedef void (
*object_init_function) (
void);
typedef unsigned (
*object_count_function) (
void);
@@ -53,16 +57,14 @@ typedef char *(
(
uint32_t object_instance);
typedef bool(
*object_valid_instance_function) (
uint32_t object_instance);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Device_Object_Function_Set(
BACNET_OBJECT_TYPE object_type,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function);
void Device_Init(
void);
@@ -84,6 +86,12 @@ extern "C" {
int *object_type,
uint32_t * instance);
unsigned Device_Count(void);
uint32_t Device_Index_To_Instance(
unsigned index);
char *Device_Name(
uint32_t object_instance);
BACNET_DEVICE_STATUS Device_System_Status(
void);
int Device_Set_System_Status(
@@ -152,18 +160,13 @@ extern "C" {
int object_type,
uint32_t object_instance);
int Device_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Device_Objects_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
int Device_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
bool DeviceGetRRInfo(
uint32_t Object, /* Which particular object - obviously not important for device object */
+7 -19
View File
@@ -78,23 +78,13 @@ extern "C" {
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_read_property_function_set(
read_property_function pFunction);
int local_read_property(
uint8_t * value,
uint8_t * status,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *Source,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
void handler_rr_object_set(
BACNET_OBJECT_TYPE object_type,
rr_info_function pFunction1);
void handler_read_property_object_set(
BACNET_OBJECT_TYPE object_type,
read_property_function pFunction1,
object_valid_instance_function pFunction2);
void handler_read_property_ack(
uint8_t * service_request,
uint16_t service_len,
@@ -106,9 +96,7 @@ extern "C" {
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_write_property_object_set(
BACNET_OBJECT_TYPE object_type,
void handler_write_property_function_set(
write_property_function pFunction);
bool WPValidateString(
@@ -176,10 +164,10 @@ extern "C" {
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_read_property_multiple_list_set(
BACNET_OBJECT_TYPE object_type,
rpm_property_lists_function pFunction);
void handler_rpm_function_set(
read_property_function pFunction);
void handler_rpm_list_set(
rpm_object_property_lists_function pFunction);
void handler_read_property_multiple_ack(
uint8_t * service_request,
+4 -10
View File
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
@@ -54,18 +55,11 @@ extern "C" {
void Load_Control_Init(
void);
int Load_Control_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Load_Control_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Load_Control_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+4 -11
View File
@@ -29,6 +29,7 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifdef __cplusplus
@@ -55,20 +56,12 @@ extern "C" {
uint32_t object_instance,
int priority);
/* ReadProperty service support */
int Lighting_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Lighting_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
/* WriteProperty service support */
bool Lighting_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+8 -10
View File
@@ -29,8 +29,13 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_LIFE_SAFETY_POINTS
#define MAX_LIFE_SAFETY_POINTS 7
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -50,18 +55,11 @@ extern "C" {
void Life_Safety_Point_Init(
void);
int Life_Safety_Point_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Life_Safety_Point_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Life_Safety_Point_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+8 -10
View File
@@ -29,8 +29,13 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_MULTISTATE_INPUTS
#define MAX_MULTISTATE_INPUTS 1
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -49,18 +54,11 @@ extern "C" {
unsigned Multistate_Input_Instance_To_Index(
uint32_t instance);
int Multistate_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Multistate_Input_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Multistate_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
/* optional API */
bool Multistate_Input_Object_Instance_Add(
+8 -10
View File
@@ -29,8 +29,13 @@
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_MULTISTATE_OUTPUTS
#define MAX_MULTISTATE_OUTPUTS 4
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
@@ -51,18 +56,11 @@ extern "C" {
void Multistate_Output_Init(
void);
int Multistate_Output_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Multistate_Output_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Multistate_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef TEST
#include "ctest.h"
+3 -19
View File
@@ -46,29 +46,13 @@ typedef struct BACnet_Read_Property_Data {
int32_t array_index;
uint8_t *application_data;
int application_data_len;
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
} BACNET_READ_PROPERTY_DATA;
typedef int (
*read_property_function) (
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
typedef bool(
*object_valid_instance_function) (
uint32_t object_instance);
/* structure for linked list of object functions */
struct BACnet_Read_Property_Functions;
typedef struct BACnet_Read_Property_Functions {
BACNET_OBJECT_TYPE object_type;
read_property_function rp_object_property_value;
object_valid_instance_function rp_object_valid_instance;
struct BACnet_Read_Property_Functions *next;
} BACNET_RP_FUNCTIONS;
BACNET_READ_PROPERTY_DATA *rp_data);
#ifdef __cplusplus
extern "C" {
+16
View File
@@ -55,6 +55,22 @@ typedef void (
const int **pOptional,
const int **pProprietary);
struct property_list_t {
const int *pList;
unsigned count;
};
struct special_property_list_t {
struct property_list_t Required;
struct property_list_t Optional;
struct property_list_t Proprietary;
};
typedef void (
*rpm_object_property_lists_function) (
BACNET_OBJECT_TYPE object_type,
struct special_property_list_t *pPropertyList);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
+9 -10
View File
@@ -29,6 +29,12 @@
#include <stdint.h>
#include "bacdef.h"
#include "cov.h"
#include "rp.h"
#include "wp.h"
#ifndef MAX_TREND_LOGS
#define MAX_TREND_LOGS 8
#endif
#ifdef __cplusplus
extern "C" {
@@ -53,18 +59,11 @@ extern "C" {
char *Trend_Log_Name(
uint32_t object_instance);
int Trend_Log_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
int Trend_Log_Read_Property(
BACNET_READ_PROPERTY_DATA *rpdata);
bool Trend_Log_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
void Trend_Log_Init(
void);
+3 -3
View File
@@ -51,13 +51,13 @@ typedef struct BACnet_Write_Property_Data {
uint8_t application_data[MAX_APDU];
int application_data_len;
uint8_t priority; /* use BACNET_NO_PRIORITY if no priority */
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
} BACNET_WRITE_PROPERTY_DATA;
typedef bool(
*write_property_function) (
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
BACNET_WRITE_PROPERTY_DATA * wp_data);
#ifdef __cplusplus
extern "C" {
+1
View File
@@ -136,6 +136,7 @@ OBJECT_SRC = \
$(BACNET_OBJECT)/lc.c \
$(BACNET_OBJECT)/lsp.c \
$(BACNET_OBJECT)/mso.c \
$(BACNET_OBJECT)/trendlog.c \
$(BACNET_OBJECT)/bacfile.c
PORT_ARCNET_SRC = \
+1
View File
@@ -138,6 +138,7 @@ OBJECT_SRC = $(BACNET_OBJECT)\device.c \
$(BACNET_OBJECT)\lc.c \
$(BACNET_OBJECT)\lsp.c \
$(BACNET_OBJECT)\mso.c \
$(BACNET_OBJECT)\trendlog.c \
$(BACNET_OBJECT)\bacfile.c
PORT_SRC = $(BACNET_PORT)\bip-init.c \
+98
View File
@@ -0,0 +1,98 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef AI_H
#define AI_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#ifndef MAX_ANALOG_INPUTS
#define MAX_ANALOG_INPUTS 7
#endif
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Input_Valid_Instance(
uint32_t object_instance);
unsigned Analog_Input_Count(
void);
uint32_t Analog_Input_Index_To_Instance(
unsigned index);
unsigned Analog_Input_Instance_To_Index(
uint32_t instance);
bool Analog_Input_Object_Instance_Add(
uint32_t instance);
char *Analog_Input_Name(
uint32_t object_instance);
bool Analog_Input_Name_Set(
uint32_t object_instance,
char *new_name);
char *Analog_Input_Description(
uint32_t instance);
bool Analog_Input_Description_Set(
uint32_t instance,
char *new_name);
bool Analog_Input_Units_Set(
uint32_t instance,
uint32_t units);
uint32_t Analog_Input_Units(
uint32_t instance);
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
float Analog_Input_Present_Value(
uint32_t object_instance);
void Analog_Input_Present_Value_Set(
uint32_t object_instance,
float value);
void Analog_Input_Init(
void);
#ifdef TEST
#include "ctest.h"
void testAnalogInput(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+86
View File
@@ -0,0 +1,86 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef AV_H
#define AV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_ANALOG_VALUES
#define MAX_ANALOG_VALUES 4
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Analog_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Value_Valid_Instance(
uint32_t object_instance);
unsigned Analog_Value_Count(
void);
uint32_t Analog_Value_Index_To_Instance(
unsigned index);
char *Analog_Value_Name(
uint32_t object_instance);
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Present_Value_Set(
uint32_t object_instance,
float value,
uint8_t priority);
float Analog_Value_Present_Value(
uint32_t object_instance);
void Analog_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testAnalog_Value(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+114
View File
@@ -0,0 +1,114 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BI_H
#define BI_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "cov.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Binary_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Binary_Input_Valid_Instance(
uint32_t object_instance);
unsigned Binary_Input_Count(
void);
uint32_t Binary_Input_Index_To_Instance(
unsigned index);
unsigned Binary_Input_Instance_To_Index(
uint32_t instance);
bool Binary_Input_Object_Instance_Add(
uint32_t instance);
char *Binary_Input_Name(
uint32_t object_instance);
bool Binary_Input_Name_Set(
uint32_t object_instance,
char *new_name);
char *Binary_Input_Description(
uint32_t instance);
bool Binary_Input_Description_Set(
uint32_t instance,
char *new_name);
char *Binary_Input_Inactive_Text(
uint32_t instance);
bool Binary_Input_Inactive_Text_Set(
uint32_t instance,
char *new_name);
char *Binary_Input_Active_Text(
uint32_t instance);
bool Binary_Input_Active_Text_Set(
uint32_t instance,
char *new_name);
bool Binary_Input_Change_Of_Value(
uint32_t object_instance);
void Binary_Input_Change_Of_Value_Clear(
uint32_t object_instance);
bool Binary_Input_Encode_Value_List(
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list);
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Binary_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
void Binary_Input_Init(
void);
BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance);
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
bool value);
#ifdef TEST
#include "ctest.h"
void testBinaryInput(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+81
View File
@@ -0,0 +1,81 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BV_H
#define BV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_BINARY_VALUES
#define MAX_BINARY_VALUES 10
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Binary_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Binary_Value_Valid_Instance(
uint32_t object_instance);
unsigned Binary_Value_Count(
void);
uint32_t Binary_Value_Index_To_Instance(
unsigned index);
char *Binary_Value_Name(
uint32_t object_instance);
void Binary_Value_Init(
void);
int Binary_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
#ifdef TEST
#include "ctest.h"
void testBinary_Value(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+1 -1
View File
@@ -477,7 +477,7 @@ int Device_Encode_Property_APDU(
return apdu_len;
}
bool Device_Write_Property(
bool Device_Write_Property_APDU(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
+176
View File
@@ -0,0 +1,176 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef DEVICE_H
#define DEVICE_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacenum.h"
#include "wp.h"
#include "readrange.h"
typedef unsigned (
*object_count_function) (
void);
typedef uint32_t(
*object_index_to_instance_function)
(
unsigned index);
typedef char *(
*object_name_function)
(
uint32_t object_instance);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Device_Object_Function_Set(
BACNET_OBJECT_TYPE object_type,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function);
void Device_Init(
void);
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
uint32_t Device_Object_Instance_Number(
void);
bool Device_Set_Object_Instance_Number(
uint32_t object_id);
bool Device_Valid_Object_Instance_Number(
uint32_t object_id);
unsigned Device_Object_List_Count(
void);
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance);
BACNET_DEVICE_STATUS Device_System_Status(
void);
void Device_Set_System_Status(
BACNET_DEVICE_STATUS status);
const char *Device_Vendor_Name(
void);
uint16_t Device_Vendor_Identifier(
void);
const char *Device_Model_Name(
void);
bool Device_Set_Model_Name(
const char *name,
size_t length);
const char *Device_Firmware_Revision(
void);
const char *Device_Application_Software_Version(
void);
bool Device_Set_Application_Software_Version(
const char *name,
size_t length);
bool Device_Set_Object_Name(
const char *name,
size_t length);
const char *Device_Object_Name(
void);
const char *Device_Description(
void);
bool Device_Set_Description(
const char *name,
size_t length);
const char *Device_Location(
void);
bool Device_Set_Location(
const char *name,
size_t length);
/* some stack-centric constant values - no set methods */
uint8_t Device_Protocol_Version(
void);
uint8_t Device_Protocol_Revision(
void);
BACNET_SEGMENTATION Device_Segmentation_Supported(
void);
uint8_t Device_Database_Revision(
void);
void Device_Set_Database_Revision(
uint8_t revision);
bool Device_Valid_Object_Name(
const char *object_name,
int *object_type,
uint32_t * object_instance);
char *Device_Valid_Object_Id(
int object_type,
uint32_t object_instance);
int Device_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool DeviceGetRRInfo(
uint32_t Object, /* Which particular object - obviously not important for device object */
BACNET_PROPERTY_ID Property, /* Which property */
RR_PROP_INFO *pInfo, /* Where to put the information */
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+86
View File
@@ -0,0 +1,86 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef AV_H
#define AV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_ANALOG_VALUES
#define MAX_ANALOG_VALUES 4
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Analog_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Value_Valid_Instance(
uint32_t object_instance);
unsigned Analog_Value_Count(
void);
uint32_t Analog_Value_Index_To_Instance(
unsigned index);
char *Analog_Value_Name(
uint32_t object_instance);
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Analog_Value_Present_Value_Set(
uint32_t object_instance,
float value,
uint8_t priority);
float Analog_Value_Present_Value(
uint32_t object_instance);
void Analog_Value_Init(
void);
#ifdef TEST
#include "ctest.h"
void testAnalog_Value(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+81
View File
@@ -0,0 +1,81 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#ifndef BV_H
#define BV_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacerror.h"
#include "wp.h"
#ifndef MAX_BINARY_VALUES
#define MAX_BINARY_VALUES 10
#endif
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Binary_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Binary_Value_Valid_Instance(
uint32_t object_instance);
unsigned Binary_Value_Count(
void);
uint32_t Binary_Value_Index_To_Instance(
unsigned index);
char *Binary_Value_Name(
uint32_t object_instance);
void Binary_Value_Init(
void);
int Binary_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
#ifdef TEST
#include "ctest.h"
void testBinary_Value(
Test * pTest);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+176
View File
@@ -0,0 +1,176 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2005 Steve Karg
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
#ifndef DEVICE_H
#define DEVICE_H
#include <stdbool.h>
#include <stdint.h>
#include "bacdef.h"
#include "bacenum.h"
#include "wp.h"
#include "readrange.h"
typedef unsigned (
*object_count_function) (
void);
typedef uint32_t(
*object_index_to_instance_function)
(
unsigned index);
typedef char *(
*object_name_function)
(
uint32_t object_instance);
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void Device_Object_Function_Set(
BACNET_OBJECT_TYPE object_type,
object_count_function count_function,
object_index_to_instance_function index_function,
object_name_function name_function);
void Device_Init(
void);
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
uint32_t Device_Object_Instance_Number(
void);
bool Device_Set_Object_Instance_Number(
uint32_t object_id);
bool Device_Valid_Object_Instance_Number(
uint32_t object_id);
unsigned Device_Object_List_Count(
void);
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance);
BACNET_DEVICE_STATUS Device_System_Status(
void);
void Device_Set_System_Status(
BACNET_DEVICE_STATUS status);
const char *Device_Vendor_Name(
void);
uint16_t Device_Vendor_Identifier(
void);
const char *Device_Model_Name(
void);
bool Device_Set_Model_Name(
const char *name,
size_t length);
const char *Device_Firmware_Revision(
void);
const char *Device_Application_Software_Version(
void);
bool Device_Set_Application_Software_Version(
const char *name,
size_t length);
bool Device_Set_Object_Name(
const char *name,
size_t length);
const char *Device_Object_Name(
void);
const char *Device_Description(
void);
bool Device_Set_Description(
const char *name,
size_t length);
const char *Device_Location(
void);
bool Device_Set_Location(
const char *name,
size_t length);
/* some stack-centric constant values - no set methods */
uint8_t Device_Protocol_Version(
void);
uint8_t Device_Protocol_Revision(
void);
BACNET_SEGMENTATION Device_Segmentation_Supported(
void);
uint8_t Device_Database_Revision(
void);
void Device_Set_Database_Revision(
uint8_t revision);
bool Device_Valid_Object_Name(
const char *object_name,
int *object_type,
uint32_t * object_instance);
char *Device_Valid_Object_Id(
int object_type,
uint32_t object_instance);
int Device_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code);
bool DeviceGetRRInfo(
uint32_t Object, /* Which particular object - obviously not important for device object */
BACNET_PROPERTY_ID Property, /* Which property */
RR_PROP_INFO *pInfo, /* Where to put the information */
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+5 -2
View File
@@ -1269,8 +1269,11 @@ void testBACnetApplicationData_Safe(
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
octetstring_init(&input_value[i].type.Octet_String,
"This is a o-string", strlen("This is a o-string"));
{
uint8_t test_octet[5] = {"Karg"};
octetstring_init(&input_value[i].type.Octet_String,
test_octet, sizeof(test_octet));
}
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
+3 -3
View File
@@ -1956,7 +1956,7 @@ void testBACDCodeReal(
return;
}
static void testBACDCodeDouble(
void testBACDCodeDouble(
Test * pTest)
{
uint8_t double_array[8] = { 0 };
@@ -2743,7 +2743,7 @@ void testDoubleContextDecodes(
ct_test(pTest, outLen2 == -1);
}
static void testObjectIDContextDecodes(
void testObjectIDContextDecodes(
Test * pTest)
{
uint8_t apdu[MAX_APDU];
@@ -2784,7 +2784,7 @@ static void testObjectIDContextDecodes(
ct_test(pTest, outLen2 == -1);
}
static void testCharacterStringContextDecodes(
void testCharacterStringContextDecodes(
Test * pTest)
{
uint8_t apdu[MAX_APDU];