Integrated ReadPropertyMultiple with the demo/server application. Compiles, but untested.

This commit is contained in:
skarg
2007-07-19 00:21:38 +00:00
parent a8555ef196
commit 5b07b5b920
30 changed files with 1047 additions and 431 deletions
+477 -256
View File
@@ -1,7 +1,7 @@
/************************************************************************** /**************************************************************************
* *
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net> * Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
* Enhanced by John Stachler for ReadPropertyMultiple * Inspired by John Stachler.
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@@ -37,37 +37,378 @@
#include "abort.h" #include "abort.h"
#include "rpm.h" #include "rpm.h"
#include "handlers.h" #include "handlers.h"
/* demo objects */
#include "device.h" #include "device.h"
#include "ai.h" #include "ai.h"
#include "ao.h" #include "ao.h"
#include "av.h"
#include "bi.h" #include "bi.h"
#include "bo.h"
#include "bv.h"
#include "lc.h"
#include "lsp.h"
#include "mso.h"
#if BACFILE
#include "bacfile.h"
#endif
static uint8_t Temp_Buf[MAX_APDU] = { 0 }; static uint8_t Temp_Buf[MAX_APDU] = { 0 };
static uint8_t Application_Buf[MAX_APDU] = { 0 };
/* copy encoded apdu data to tx buffer struct property_list_t
this is needed to make sure we do not go past our apdu buffer size */
bool copy_apdu_data_buffer(int *apdu_len, uint8 len, uint8 npdu_len)
{ {
bool copy_status = false; const int *pList;
unsigned count;
};
if ((*apdu_len + len) <= MAX_APDU) { struct special_property_list_t
memcpy(&Handler_Transmit_Buffer[*apdu_len + npdu_len], &Temp_Buf[0], len); {
*apdu_len += len; struct property_list_t Required;
copy_status = true; 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++;
}
} }
return copy_status; return property_count;
} }
void handler_read_property_multiple(uint8_t * service_request, uint16_t service_len, BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data) /* 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)
{
pPropertyList->Required.pList = NULL;
pPropertyList->Optional.pList = NULL;
pPropertyList->Proprietary.pList = NULL;
switch (object_type) {
case OBJECT_ANALOG_INPUT:
Analog_Input_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_OUTPUT:
Analog_Output_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_ANALOG_VALUE:
Analog_Value_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_INPUT:
Binary_Input_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_OUTPUT:
Binary_Output_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_BINARY_VALUE:
Binary_Value_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LIFE_SAFETY_POINT:
Life_Safety_Point_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_LOAD_CONTROL:
Load_Control_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
case OBJECT_MULTI_STATE_OUTPUT:
break;
#if BACFILE
case OBJECT_FILE:
BACfile_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
#endif
case OBJECT_DEVICE:
Device_Property_Lists(
&pPropertyList->Required.pList,
&pPropertyList->Optional.pList,
&pPropertyList->Proprietary.pList);
break;
default:
break;
}
/* fill the count */
pPropertyList->Required.count =
property_list_count(pPropertyList->Required.pList);
pPropertyList->Optional.count =
property_list_count(pPropertyList->Optional.pList);
pPropertyList->Proprietary.count =
property_list_count(pPropertyList->Proprietary.pList);
return;
}
static int RPM_Object_Property(
struct special_property_list_t *pPropertyList,
BACNET_PROPERTY_ID special_property,
unsigned index)
{
int property = -1; /* return value */
unsigned required, optional, proprietary;
required = pPropertyList->Required.count;
optional = pPropertyList->Optional.count;
proprietary = pPropertyList->Proprietary.count;
if (special_property == PROP_ALL) {
if (index < required) {
property = pPropertyList->Required.pList[index];
} else if (index < (required + optional)) {
property = pPropertyList->Optional.pList[index];
} else if (index < (required + optional + proprietary)) {
property = pPropertyList->Proprietary.pList[index];
}
} else if (special_property == PROP_REQUIRED) {
if (index < required) {
property = pPropertyList->Required.pList[index];
}
} else if (special_property == PROP_OPTIONAL) {
if (index < optional) {
property = pPropertyList->Optional.pList[index];
}
}
return property;
}
static unsigned RPM_Object_Property_Count(
struct special_property_list_t *pPropertyList,
BACNET_PROPERTY_ID special_property)
{
unsigned count = 0; /* return value */
if (special_property == PROP_ALL) {
count = pPropertyList->Required.count +
pPropertyList->Optional.count +
pPropertyList->Proprietary.count;
} else if (special_property == PROP_REQUIRED) {
count = pPropertyList->Required.count;
} else if (special_property == PROP_OPTIONAL) {
count = pPropertyList->Optional.count;
}
return count;
}
/* copy len bytes from src to offset of dest if there is enough space. */
int apdu_copy(uint8_t *dest, uint8_t *src, int offset, int len, int max)
{
int i;
int copy_len = 0;
if (len <= (max-offset)) {
for (i = 0; i < len; i++) {
dest[offset+i] = src[i];
copy_len++;
}
}
return copy_len;
}
/* 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;
switch(object_type) {
case OBJECT_DEVICE:
if ((object_instance == Device_Object_Instance_Number()) ||
(object_instance == BACNET_MAX_INSTANCE)) {
apdu_len = Device_Encode_Property_APDU(
&apdu[0],
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(object_instance)) {
apdu_len = Analog_Input_Encode_Property_APDU(
&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_ANALOG_OUTPUT:
if (!Analog_Output_Valid_Instance(object_instance)) {
apdu_len = Analog_Output_Encode_Property_APDU(
&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(object_instance)) {
apdu_len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(object_instance)) {
apdu_len = Binary_Input_Encode_Property_APDU(
&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_BINARY_OUTPUT:
if (Binary_Output_Valid_Instance(object_instance)) {
apdu_len = Binary_Output_Encode_Property_APDU(
&apdu[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(object_instance)) {
apdu_len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_LIFE_SAFETY_POINT:
if (Life_Safety_Point_Valid_Instance(object_instance)) {
apdu_len = Life_Safety_Point_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_LOAD_CONTROL:
if (Load_Control_Valid_Instance(object_instance)) {
apdu_len = Load_Control_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
case OBJECT_MULTI_STATE_OUTPUT:
if (Multistate_Output_Valid_Instance(object_instance)) {
apdu_len = Multistate_Output_Encode_Property_APDU(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
#if BACFILE
case OBJECT_FILE:
if (bacfile_valid_instance(object_instance)) {
apdu_len = bacfile_encode_property_apdu(&Temp_Buf[0],
object_instance,
property,
array_index,
error_class, error_code);
} else {
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
}
break;
#endif
default:
*error_class = ERROR_CLASS_OBJECT;
*error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
break;
}
return apdu_len;
}
void handler_read_property_multiple(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{ {
int len = 0; int len = 0;
int copy_len = 0;
int decode_len = 0; int decode_len = 0;
int application_data_len = 0;
int pdu_len = 0; int pdu_len = 0;
BACNET_NPDU_DATA npdu_data; BACNET_NPDU_DATA npdu_data;
bool error = false;
bool done;
bool property_found;
int bytes_sent; int bytes_sent;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT; BACNET_ERROR_CLASS error_class = ERROR_CLASS_OBJECT;
BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT; BACNET_ERROR_CODE error_code = ERROR_CODE_UNKNOWN_OBJECT;
@@ -78,8 +419,6 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
int npdu_len; int npdu_len;
BACNET_PROPERTY_ID object_property, temp_object_property; BACNET_PROPERTY_ID object_property, temp_object_property;
int32_t array_index = 0; int32_t array_index = 0;
uint8 index;
uint8 num_properties;
/* jps_debug - see if we are utilizing all the buffer */ /* jps_debug - see if we are utilizing all the buffer */
/* memset(&Handler_Transmit_Buffer[0], 0xff, MAX_MPDU);*/ /* memset(&Handler_Transmit_Buffer[0], 0xff, MAX_MPDU);*/
@@ -123,7 +462,33 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
&service_request[decode_len], &service_request[decode_len],
service_len - decode_len, service_len - decode_len,
&object_type, &object_instance); &object_type, &object_instance);
/* error - end of object? */
if (len < 0) { if (len < 0) {
len = rpm_ack_decode_object_end(
&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
len = rpm_ack_encode_apdu_object_end(&Temp_Buf[0]);
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RPM_ABORT;
}
} else {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_OTHER, true);
goto RPM_ABORT;
}
break; break;
} else { } else {
decode_len += len; decode_len += len;
@@ -131,278 +496,134 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
len = rpm_ack_encode_apdu_object_begin( len = rpm_ack_encode_apdu_object_begin(
&Temp_Buf[0], &Temp_Buf[0],
object_type, object_instance); object_type, object_instance);
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) { copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu( apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len], &Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
break; goto RPM_ABORT;
} }
/* do each property of this object of the RPM request */ /* do each property of this object of the RPM request */
done = true;
num_properties = 0;
property_found = false;
do do
{ {
if (done) { len = rpm_decode_object_property(
len = rpm_decode_object_property( &service_request[decode_len],
&service_request[decode_len], service_len - decode_len,
service_len - decode_len, &object_property,
&object_property, &array_index);
&array_index); /* error - end of property list? */
if (len < 0) { if (len < 0) {
break; break;
} else { } else {
index = 0; decode_len += len;
decode_len += len;
temp_object_property = object_property;
}
} }
/* handle the special properties */ /* handle the special properties */
if ((object_property == PROP_ALL) || if ((object_property == PROP_ALL) ||
(object_property == PROP_REQUIRED) || (object_property == PROP_REQUIRED) ||
(object_property == PROP_OPTIONAL)) (object_property == PROP_OPTIONAL))
{ {
done = false; struct special_property_list_t property_list;
switch(object_type) unsigned property_count = 0;
unsigned index = 0;
RPM_Property_List(object_type, &property_list);
property_count = RPM_Object_Property_Count(
&property_list,
object_property);
for (index = 0; index < property_count; index++)
{ {
case OBJECT_DEVICE: temp_object_property = RPM_Object_Property(
property_found = Device_Property( &property_list,
&index, &temp_object_property, object_property,
object_property); index);
break; len = rpm_ack_encode_apdu_object_property(
&Temp_Buf[0],
case OBJECT_ANALOG_INPUT: temp_object_property,
property_found = Analog_Input_Property( array_index);
&index, &temp_object_property, copy_len = apdu_copy(
object_property); &Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
break; apdu_len, len,
sizeof(Handler_Transmit_Buffer));
case OBJECT_BINARY_INPUT: if (!copy_len) {
property_found = Binary_Input_Property( apdu_len = abort_encode_apdu(
&index, &temp_object_property, &Handler_Transmit_Buffer[npdu_len],
object_property); service_data->invoke_id,
break; ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true);
goto RPM_ABORT;
case OBJECT_ANALOG_OUTPUT: }
property_found = Analog_Output_Property( application_data_len = Encode_Property_APDU(
&index, &temp_object_property, &Application_Buf[0],
object_property); object_type,
break; object_instance,
} temp_object_property,
if (property_found) { array_index,
num_properties++; &error_class, &error_code);
} else { if (application_data_len < 0) {
if (num_properties > 0) { len = rpm_ack_encode_apdu_object_property_error(
done = true; &Temp_Buf[0],
/* check for another property */ error_class, error_code);
len = rpm_decode_object_property(
&service_request[decode_len],
service_len - decode_len,
&object_property,
&array_index);
if (len < 0) {
/* check for closing tag */
len = rpm_ack_decode_object_end(
&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
}
break;
} else {
decode_len += len;
temp_object_property = object_property;
property_found = true;
if ((object_property == PROP_ALL) ||
(object_property == PROP_REQUIRED) ||
(object_property == PROP_OPTIONAL))
{
done = false;
index = 0;
switch(object_type)
{
case OBJECT_DEVICE:
property_found =
Device_Property(&index,
&temp_object_property,
object_property);
break;
case OBJECT_ANALOG_INPUT:
property_found =
Analog_Input_Property(&index,
&temp_object_property,
object_property);
break;
case OBJECT_BINARY_INPUT:
property_found =
Binary_Input_Property(&index,
&temp_object_property,
object_property);
break;
case OBJECT_ANALOG_OUTPUT:
property_found =
Analog_Output_Property(&index,
&temp_object_property,
object_property);
break;
}
}
}
} else { } else {
error = true; len = rpm_ack_encode_apdu_object_property_value(
done = true; &Temp_Buf[0],
&Application_Buf[0],
application_data_len);
}
copy_len = apdu_copy(
&Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
apdu_len, len,
sizeof(Handler_Transmit_Buffer));
if (!copy_len) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
goto RPM_ABORT;
} }
} }
} else { } else {
done = true; /* handle an individual property */
property_found = true; application_data_len = Encode_Property_APDU(
} &Application_Buf[0],
len = rpm_ack_encode_apdu_object_property( object_type,
&Temp_Buf[0], object_instance,
temp_object_property, object_property,
array_index); array_index,
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) { &error_class, &error_code);
apdu_len = abort_encode_apdu( if (application_data_len < 0) {
&Handler_Transmit_Buffer[npdu_len], len = rpm_ack_encode_apdu_object_property_error(
service_data->invoke_id, &Temp_Buf[0],
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); error_class, error_code);
break; } else {
} len = rpm_ack_encode_apdu_object_property_value(
len = encode_opening_tag(&Temp_Buf[0], 4); &Temp_Buf[0],
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) { &Application_Buf[0],
apdu_len = abort_encode_apdu(&Handler_Transmit_Buffer[npdu_len], service_data->invoke_id, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, true); application_data_len);
break; }
} copy_len = apdu_copy(
len = -1; &Handler_Transmit_Buffer[npdu_len], &Temp_Buf[0],
switch(object_type) { apdu_len, len,
case OBJECT_DEVICE: sizeof(Handler_Transmit_Buffer));
if ((object_instance != Device_Object_Instance_Number()) && if (!copy_len) {
((object_instance != BACNET_MAX_INSTANCE) &&
(temp_object_property != PROP_OBJECT_IDENTIFIER))) {
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNKNOWN_OBJECT;
} else if (!property_found) {
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_UNKNOWN_PROPERTY;
} else {
len = Device_Encode_Property_APDU(
&Temp_Buf[0],
temp_object_property,
array_index,
&error_class, &error_code);
}
break;
case OBJECT_ANALOG_INPUT:
if (!Analog_Input_Valid_Instance(object_instance)) {
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNKNOWN_OBJECT;
} else if (!property_found) {
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_UNKNOWN_PROPERTY;
} else {
len = Analog_Input_Encode_Property_APDU(
&Temp_Buf[0],
object_instance,
temp_object_property,
array_index,
&error_class, &error_code);
}
break;
case OBJECT_BINARY_INPUT:
if (!Binary_Input_Valid_Instance(object_instance)) {
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNKNOWN_OBJECT;
} else if (!property_found) {
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_UNKNOWN_PROPERTY;
} else {
len = Binary_Input_Encode_Property_APDU(
&Temp_Buf[0],
object_instance,
temp_object_property,
array_index,
&error_class, &error_code);
}
break;
case OBJECT_ANALOG_OUTPUT:
if (!Analog_Output_Valid_Instance(object_instance)) {
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNKNOWN_OBJECT;
} else if (!property_found) {
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_UNKNOWN_PROPERTY;
} else {
len = Analog_Output_Encode_Property_APDU(
&Temp_Buf[0],
object_instance,
temp_object_property,
array_index,
&error_class, &error_code);
}
break;
default:
len = -1;
error_class = ERROR_CLASS_OBJECT;
error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
break;
}
if (len < 0) {
len = rpm_ack_encode_apdu_object_property_error(
&Temp_Buf[0],
error_class, error_code);
apdu_len--;
error = true;
}
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
}
if (!error && property_found) {
len = encode_closing_tag(&Temp_Buf[0], 4);
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) {
apdu_len = abort_encode_apdu( apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len], &Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id, service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED, ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true); true);
break; goto RPM_ABORT;
}
} else {
error = false;
}
/* check for closing tag */
if (done) {
len = rpm_ack_decode_object_end(
&service_request[decode_len],
service_len - decode_len);
if (len == 1) {
decode_len++;
break;
} }
} }
} while(1); } while(1);
len = encode_closing_tag(&Temp_Buf[0], 1);
if (!copy_apdu_data_buffer(&apdu_len, len, npdu_len)) {
apdu_len = abort_encode_apdu(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
break;
}
if (decode_len >= service_len) { if (decode_len >= service_len) {
break; break;
} }
} while(1); } while(1);
} }
RPM_ABORT:
pdu_len = apdu_len + npdu_len; pdu_len = apdu_len + npdu_len;
bytes_sent = datalink_send_pdu( bytes_sent = datalink_send_pdu(
src, src,
+7
View File
@@ -101,6 +101,13 @@ extern "C" {
void handler_timesync_utc(uint8_t * service_request, void handler_timesync_utc(uint8_t * service_request,
uint16_t service_len, BACNET_ADDRESS * src); uint16_t service_len, BACNET_ADDRESS * src);
void handler_read_property_multiple(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
+43
View File
@@ -35,6 +35,49 @@
#define MAX_ANALOG_INPUTS 7 #define MAX_ANALOG_INPUTS 7
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Input_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Analog_Input_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Analog_Input_Properties_Proprietary[] =
{
9997,
9998,
9999,
-1
};
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Analog_Input_Properties_Required;
if (*pOptional)
*pOptional = Analog_Input_Properties_Optional;
if (*pProprietary)
*pProprietary = Analog_Input_Properties_Proprietary;
return;
}
/* we simply have 0-n object instances. Yours might be */ /* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */ /* more complex, and then you need validate that the */
/* given instance exists */ /* given instance exists */
+4 -1
View File
@@ -32,7 +32,10 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Analog_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Input_Valid_Instance(uint32_t object_instance); bool Analog_Input_Valid_Instance(uint32_t object_instance);
unsigned Analog_Input_Count(void); unsigned Analog_Input_Count(void);
uint32_t Analog_Input_Index_To_Instance(unsigned index); uint32_t Analog_Input_Index_To_Instance(unsigned index);
+42
View File
@@ -56,6 +56,48 @@ static bool Analog_Output_Out_Of_Service[MAX_ANALOG_OUTPUTS];
/* we need to have our arrays initialized before answering any calls */ /* we need to have our arrays initialized before answering any calls */
static bool Analog_Output_Initialized = false; static bool Analog_Output_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Analog_Output_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Analog_Output_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Analog_Output_Properties_Proprietary[] =
{
-1
};
void Analog_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Analog_Output_Properties_Required;
if (*pOptional)
*pOptional = Analog_Output_Properties_Optional;
if (*pProprietary)
*pProprietary = Analog_Output_Properties_Proprietary;
return;
}
void Analog_Output_Init(void) void Analog_Output_Init(void)
{ {
unsigned i, j; unsigned i, j;
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Analog_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Analog_Output_Valid_Instance(uint32_t object_instance); bool Analog_Output_Valid_Instance(uint32_t object_instance);
unsigned Analog_Output_Count(void); unsigned Analog_Output_Count(void);
uint32_t Analog_Output_Index_To_Instance(unsigned index); uint32_t Analog_Output_Index_To_Instance(unsigned index);
+42
View File
@@ -55,6 +55,48 @@ static bool Analog_Value_Out_Of_Service[MAX_ANALOG_VALUES];
/* we need to have our arrays initialized before answering any calls */ /* we need to have our arrays initialized before answering any calls */
static bool Analog_Value_Initialized = false; 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,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
-1
};
static const int Analog_Value_Properties_Optional[] =
{
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Analog_Value_Properties_Proprietary[] =
{
-1
};
void Analog_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Analog_Value_Properties_Required;
if (*pOptional)
*pOptional = Analog_Value_Properties_Optional;
if (*pProprietary)
*pProprietary = Analog_Value_Properties_Proprietary;
return;
}
void Analog_Value_Init(void) void Analog_Value_Init(void)
{ {
unsigned i, j; unsigned i, j;
+4 -1
View File
@@ -34,7 +34,10 @@
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #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); bool Analog_Value_Valid_Instance(uint32_t object_instance);
unsigned Analog_Value_Count(void); unsigned Analog_Value_Count(void);
uint32_t Analog_Value_Index_To_Instance(unsigned index); uint32_t Analog_Value_Index_To_Instance(unsigned index);
+42
View File
@@ -52,6 +52,48 @@ static BACNET_FILE_LISTING BACnet_File_Listing[] = {
{0, NULL} /* last file indication */ {0, NULL} /* last file indication */
}; };
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int bacfile_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_FILE_TYPE,
PROP_FILE_SIZE,
PROP_MODIFICATION_DATE,
PROP_ARCHIVE,
PROP_READ_ONLY,
PROP_FILE_ACCESS_METHOD,
-1
};
static const int bacfile_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int bacfile_Properties_Proprietary[] =
{
-1
};
void BACfile_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = bacfile_Properties_Required;
if (*pOptional)
*pOptional = bacfile_Properties_Optional;
if (*pProprietary)
*pProprietary = bacfile_Properties_Proprietary;
return;
}
char *bacfile_name(uint32_t instance) char *bacfile_name(uint32_t instance)
{ {
uint32_t index = 0; uint32_t index = 0;
+4
View File
@@ -46,6 +46,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void BACfile_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
char *bacfile_name(uint32_t instance); char *bacfile_name(uint32_t instance);
bool bacfile_valid_instance(uint32_t object_instance); bool bacfile_valid_instance(uint32_t object_instance);
uint32_t bacfile_count(void); uint32_t bacfile_count(void);
+41 -1
View File
@@ -23,7 +23,7 @@
* *
*********************************************************************/ *********************************************************************/
/* Analog Input Objects customize for your use */ /* Binary Input Objects customize for your use */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -37,6 +37,46 @@
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS]; static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Input_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
-1
};
static const int Binary_Input_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Binary_Input_Properties_Proprietary[] =
{
-1
};
void Binary_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Binary_Input_Properties_Required;
if (*pOptional)
*pOptional = Binary_Input_Properties_Optional;
if (*pProprietary)
*pProprietary = Binary_Input_Properties_Proprietary;
return;
}
/* we simply have 0-n object instances. Yours might be */ /* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */ /* more complex, and then you need validate that the */
/* given instance exists */ /* given instance exists */
+4
View File
@@ -33,6 +33,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #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); bool Binary_Input_Valid_Instance(uint32_t object_instance);
unsigned Binary_Input_Count(void); unsigned Binary_Input_Count(void);
uint32_t Binary_Input_Index_To_Instance(unsigned index); uint32_t Binary_Input_Index_To_Instance(unsigned index);
+42
View File
@@ -47,6 +47,48 @@ static BACNET_BINARY_PV
/* without changing the physical output */ /* without changing the physical output */
static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS]; static bool Binary_Output_Out_Of_Service[MAX_BINARY_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Output_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Binary_Output_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Binary_Output_Properties_Proprietary[] =
{
-1
};
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Binary_Output_Properties_Required;
if (*pOptional)
*pOptional = Binary_Output_Properties_Optional;
if (*pProprietary)
*pProprietary = Binary_Output_Properties_Proprietary;
return;
}
void Binary_Output_Init(void) void Binary_Output_Init(void)
{ {
unsigned i, j; unsigned i, j;
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Binary_Output_Valid_Instance(uint32_t object_instance); bool Binary_Output_Valid_Instance(uint32_t object_instance);
unsigned Binary_Output_Count(void); unsigned Binary_Output_Count(void);
uint32_t Binary_Output_Index_To_Instance(unsigned index); uint32_t Binary_Output_Index_To_Instance(unsigned index);
+41 -3
View File
@@ -47,6 +47,47 @@ static BACNET_BINARY_PV
/* without changing the physical output */ /* without changing the physical output */
static bool Binary_Value_Out_Of_Service[MAX_BINARY_VALUES]; static bool Binary_Value_Out_Of_Service[MAX_BINARY_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Value_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
-1
};
static const int Binary_Value_Properties_Optional[] =
{
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Binary_Value_Properties_Proprietary[] =
{
-1
};
void Binary_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Binary_Value_Properties_Required;
if (*pOptional)
*pOptional = Binary_Value_Properties_Optional;
if (*pProprietary)
*pProprietary = Binary_Value_Properties_Proprietary;
return;
}
void Binary_Value_Init(void) void Binary_Value_Init(void)
{ {
unsigned i, j; unsigned i, j;
@@ -195,9 +236,6 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
state = Binary_Value_Out_Of_Service[object_index]; state = Binary_Value_Out_Of_Service[object_index];
apdu_len = encode_tagged_boolean(&apdu[0], state); apdu_len = encode_tagged_boolean(&apdu[0], state);
break; break;
case PROP_POLARITY:
apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
break;
case PROP_PRIORITY_ARRAY: case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */ /* Array element zero is the number of elements in the array */
if (array_index == 0) if (array_index == 0)
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #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); bool Binary_Value_Valid_Instance(uint32_t object_instance);
unsigned Binary_Value_Count(void); unsigned Binary_Value_Count(void);
uint32_t Binary_Value_Index_To_Instance(unsigned index); uint32_t Binary_Value_Index_To_Instance(unsigned index);
+18 -97
View File
@@ -48,7 +48,7 @@
#endif #endif
/* These three arrays are used by the ReadPropertyMultiple handler */ /* These three arrays are used by the ReadPropertyMultiple handler */
static int Device_Properties_Required[] = static const int Device_Properties_Required[] =
{ {
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_NAME,
@@ -76,7 +76,7 @@ static int Device_Properties_Required[] =
-1 -1
}; };
static int Device_Properties_Optional[] = static const int Device_Properties_Optional[] =
{ {
PROP_DESCRIPTION, PROP_DESCRIPTION,
PROP_LOCAL_TIME, PROP_LOCAL_TIME,
@@ -87,11 +87,26 @@ static int Device_Properties_Optional[] =
-1 -1
}; };
static int Device_Properties_Proprietary[] = static const int Device_Properties_Proprietary[] =
{ {
-1 -1
}; };
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Device_Properties_Required;
if (*pOptional)
*pOptional = Device_Properties_Optional;
if (*pProprietary)
*pProprietary = Device_Properties_Proprietary;
return;
}
/* note: you really only need to define variables for /* note: you really only need to define variables for
properties that are writable or that may change. properties that are writable or that may change.
The properties that are constant can be hard coded The properties that are constant can be hard coded
@@ -945,100 +960,6 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
return status; return status;
} }
int int_list_count(const int *pList)
{
int property_count = 0;
while (*pList != -1) {
property_count++;
}
return property_count;
}
/* used to count the ALL, REQUIRED and OPTIONAL */
int Device_Special_Property_Count(BACNET_PROPERTY_ID special_property)
{
const int *pList = NULL;
int property_count = 0;
if (special_property == PROP_ALL) {
property_count =
int_list_count(Device_Properties_Required);
property_count +=
int_list_count(Device_Properties_Optional);
property_count +=
int_list_count(Device_Properties_Proprietary);
} else if (special_property == PROP_REQUIRED) {
property_count =
int_list_count(Device_Properties_Required);
} else if (special_property == PROP_OPTIONAL) {
property_count =
int_list_count(Device_Properties_Optional);
}
return property_count;
}
/* returns the property ID given by the index into the list
or MAX_BACNET_PROPERTY_ID if not found or out of bounds */
BACNET_PROPERTY_ID Device_Special_Property_By_Index(
BACNET_PROPERTY_ID special_property, /* ALL, OPTIONAL, REQUIRED */
int index)
{
BACNET_PROPERTY_ID property = MAX_BACNET_PROPERTY_ID;
int required = 0, optional = 0, proprietary = 0;
/* FIXME: we could use static vars to speed up access */
if (special_property == PROP_ALL) {
required =
property_list_count(Device_Properties_Required);
optional =
property_list_count(Device_Properties_Optional);
proprietary =
property_list_count(Device_Properties_Proprietary);
if (index < required) {
property = Device_Properties_Required[index];
} else if (index < (required + optional)) {
property = Device_Properties_Optional[index];
} else if (index < (required + optional + proprietary)) {
property = Device_Properties_Proprietary[index];
}
} else if (special_property == PROP_REQUIRED) {
required =
property_list_count(Device_Properties_Required);
if (index < required) {
property = Device_Properties_Required[index];
}
} else if (special_property == PROP_OPTIONAL) {
optional =
property_list_count(Device_Properties_Optional);
if (index < optional) {
property = Device_Properties_Optional[index];
}
}
return property;
}
/* added for rpm service support when requesting prop_all,
prop_required, or prop_optional */
bool Device_Property(uint8 *pIndex, BACNET_PROPERTY_ID *pProperty, BACNET_PROPERTY_ID special_property)
{
bool result = false;
BACNET_PROPERTY_ID property;
property = Device_Special_Property_By_Index(
special_property, *pIndex);
if (property != MAX_BACNET_PROPERTY_ID) {
(*pIndex)++;
*pProperty = property;
result = true;
}
return result;
}
#ifdef TEST #ifdef TEST
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
+6 -15
View File
@@ -44,6 +44,11 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Device_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
uint32_t Device_Object_Instance_Number(void); uint32_t Device_Object_Instance_Number(void);
bool Device_Set_Object_Instance_Number(uint32_t object_id); bool Device_Set_Object_Instance_Number(uint32_t object_id);
bool Device_Valid_Object_Instance_Number(uint32_t object_id); bool Device_Valid_Object_Instance_Number(uint32_t object_id);
@@ -76,7 +81,7 @@ extern "C" {
const char *Device_Location(void); const char *Device_Location(void);
bool Device_Set_Location(const char *name, size_t length); bool Device_Set_Location(const char *name, size_t length);
/* some stack-centric constant values - no set methods */ /* some stack-centric constant values - no set methods */
uint8_t Device_Protocol_Version(void); uint8_t Device_Protocol_Version(void);
uint8_t Device_Protocol_Revision(void); uint8_t Device_Protocol_Revision(void);
uint16_t Device_Max_APDU_Length_Accepted(void); uint16_t Device_Max_APDU_Length_Accepted(void);
@@ -104,20 +109,6 @@ extern "C" {
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data, bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code); BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code);
/* support for RPM */
int Device_Special_Property_Count(BACNET_PROPERTY_ID special_property);
/* returns the property ID given by the index into the list
or MAX_BACNET_PROPERTY_ID if not found or out of bounds */
BACNET_PROPERTY_ID Device_Special_Property_By_Index(
BACNET_PROPERTY_ID special_property, /* ALL, OPTIONAL, REQUIRED */
int index);
bool Device_Property(uint8 *pIndex, BACNET_PROPERTY_ID *pProperty,
BACNET_PROPERTY_ID special_property);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */
+49
View File
@@ -24,6 +24,7 @@
*********************************************************************/ *********************************************************************/
/* Load Control Objects - customize for your use */ /* Load Control Objects - customize for your use */
/* from 135-2004-Addendum e */
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -136,6 +137,54 @@ static float Shed_Level_Values[MAX_SHED_LEVELS] = {
/* we need to have our arrays initialized before answering any calls */ /* we need to have our arrays initialized before answering any calls */
static bool Load_Control_Initialized = false; 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,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_REQUESTED_SHED_LEVEL,
PROP_START_TIME,
PROP_SHED_DURATION,
PROP_DUTY_WINDOW,
PROP_ENABLE,
PROP_EXPECTED_SHED_LEVEL,
PROP_ACTUAL_SHED_LEVEL,
PROP_SHED_LEVELS,
PROP_SHED_LEVEL_DESCRIPTIONS,
-1
};
static const int Load_Control_Properties_Optional[] =
{
PROP_DESCRIPTION,
PROP_FULL_DUTY_BASELINE,
-1
};
static const int Load_Control_Properties_Proprietary[] =
{
-1
};
void Load_Control_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Load_Control_Properties_Required;
if (*pOptional)
*pOptional = Load_Control_Properties_Optional;
if (*pProprietary)
*pProprietary = Load_Control_Properties_Proprietary;
return;
}
void Load_Control_Init(void) void Load_Control_Init(void)
{ {
unsigned i, j; unsigned i, j;
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Load_Control_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
void Load_Control_State_Machine_Handler(void); void Load_Control_State_Machine_Handler(void);
bool Load_Control_Valid_Instance(uint32_t object_instance); bool Load_Control_Valid_Instance(uint32_t object_instance);
+44
View File
@@ -50,6 +50,50 @@ static BACNET_LIFE_SAFETY_OPERATION
/* without changing the physical output */ /* without changing the physical output */
static bool Life_Safety_Point_Out_Of_Service[MAX_LIFE_SAFETY_POINTS]; static bool Life_Safety_Point_Out_Of_Service[MAX_LIFE_SAFETY_POINTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Life_Safety_Point_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_RELIABILITY,
PROP_MODE,
PROP_ACCEPTED_MODES,
PROP_SILENCED,
PROP_OPERATION_EXPECTED,
-1
};
static const int Life_Safety_Point_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Life_Safety_Point_Properties_Proprietary[] =
{
-1
};
void Life_Safety_Point_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Life_Safety_Point_Properties_Required;
if (*pOptional)
*pOptional = Life_Safety_Point_Properties_Optional;
if (*pProprietary)
*pProprietary = Life_Safety_Point_Properties_Proprietary;
return;
}
void Life_Safety_Point_Init(void) void Life_Safety_Point_Init(void)
{ {
static bool initialized = false; static bool initialized = false;
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Life_Safety_Point_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Life_Safety_Point_Valid_Instance(uint32_t object_instance); bool Life_Safety_Point_Valid_Instance(uint32_t object_instance);
unsigned Life_Safety_Point_Count(void); unsigned Life_Safety_Point_Count(void);
uint32_t Life_Safety_Point_Index_To_Instance(unsigned index); uint32_t Life_Safety_Point_Index_To_Instance(unsigned index);
+42
View File
@@ -52,6 +52,48 @@ static uint8_t
/* without changing the physical output */ /* without changing the physical output */
static bool Multistate_Output_Out_Of_Service[MAX_MULTISTATE_OUTPUTS]; static bool Multistate_Output_Out_Of_Service[MAX_MULTISTATE_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Multistate_Output_Properties_Required[] =
{
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_NUMBER_OF_STATES,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Multistate_Output_Properties_Optional[] =
{
PROP_DESCRIPTION,
-1
};
static const int Multistate_Output_Properties_Proprietary[] =
{
-1
};
void Multistate_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (*pRequired)
*pRequired = Multistate_Output_Properties_Required;
if (*pOptional)
*pOptional = Multistate_Output_Properties_Optional;
if (*pProprietary)
*pProprietary = Multistate_Output_Properties_Proprietary;
return;
}
void Multistate_Output_Init(void) void Multistate_Output_Init(void)
{ {
unsigned i, j; unsigned i, j;
+4
View File
@@ -35,6 +35,10 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
void Multistate_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
bool Multistate_Output_Valid_Instance(uint32_t object_instance); bool Multistate_Output_Valid_Instance(uint32_t object_instance);
unsigned Multistate_Output_Count(void); unsigned Multistate_Output_Count(void);
uint32_t Multistate_Output_Index_To_Instance(unsigned index); uint32_t Multistate_Output_Index_To_Instance(unsigned index);
+2
View File
@@ -38,6 +38,7 @@ SRCS = main.c \
$(BACNET_HANDLER)/noserv.c \ $(BACNET_HANDLER)/noserv.c \
$(BACNET_HANDLER)/h_whois.c \ $(BACNET_HANDLER)/h_whois.c \
$(BACNET_HANDLER)/h_rp.c \ $(BACNET_HANDLER)/h_rp.c \
$(BACNET_HANDLER)/h_rpm.c \
$(BACNET_HANDLER)/h_wp.c \ $(BACNET_HANDLER)/h_wp.c \
$(BACNET_HANDLER)/h_arf.c \ $(BACNET_HANDLER)/h_arf.c \
$(BACNET_HANDLER)/h_awf.c \ $(BACNET_HANDLER)/h_awf.c \
@@ -71,6 +72,7 @@ SRCS = main.c \
$(BACNET_ROOT)/whohas.c \ $(BACNET_ROOT)/whohas.c \
$(BACNET_ROOT)/ihave.c \ $(BACNET_ROOT)/ihave.c \
$(BACNET_ROOT)/rp.c \ $(BACNET_ROOT)/rp.c \
$(BACNET_ROOT)/rpm.c \
$(BACNET_ROOT)/wp.c \ $(BACNET_ROOT)/wp.c \
$(BACNET_ROOT)/arf.c \ $(BACNET_ROOT)/arf.c \
$(BACNET_ROOT)/awf.c \ $(BACNET_ROOT)/awf.c \
+12 -9
View File
@@ -14,11 +14,6 @@
<Compiler> <Compiler>
<Add option="-Wall" /> <Add option="-Wall" />
<Add option="-g" /> <Add option="-g" />
<Add option="-DBACDL_BIP=1" />
<Add option="-DBIP_DEBUG=1" />
<Add option="-DUSE_INADDR=1" />
<Add option="-DPRINT_ENABLED=1" />
<Add option="-DBIG_ENDIAN=0" />
<Add directory="." /> <Add directory="." />
<Add directory="..\handler" /> <Add directory="..\handler" />
<Add directory="..\object" /> <Add directory="..\object" />
@@ -54,7 +49,7 @@
<Add option="-O" /> <Add option="-O" />
<Add option="-Wall" /> <Add option="-Wall" />
<Add option="-fexceptions" /> <Add option="-fexceptions" />
<Add option="-DBACDL_MSTP=1" /> <Add option="-DBACDL_BIP=1" />
<Add option="-DBIP_DEBUG=1" /> <Add option="-DBIP_DEBUG=1" />
<Add option="-DUSE_INADDR=1" /> <Add option="-DUSE_INADDR=1" />
<Add option="-DPRINT_ENABLED=1" /> <Add option="-DPRINT_ENABLED=1" />
@@ -138,6 +133,9 @@
<Unit filename="..\handler\h_rp.c"> <Unit filename="..\handler\h_rp.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="..\handler\h_rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\handler\h_ts.c"> <Unit filename="..\handler\h_ts.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
@@ -150,6 +148,7 @@
<Unit filename="..\handler\h_wp.c"> <Unit filename="..\handler\h_wp.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="..\handler\handlers.h" />
<Unit filename="..\handler\noserv.c"> <Unit filename="..\handler\noserv.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
@@ -218,6 +217,9 @@
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="..\..\indtext.h" /> <Unit filename="..\..\indtext.h" />
<Unit filename="..\..\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\npdu.c"> <Unit filename="..\..\npdu.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
@@ -228,9 +230,6 @@
<Unit filename="..\..\ports\win32\dlmstp.c"> <Unit filename="..\..\ports\win32\dlmstp.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="..\..\ports\win32\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\ports\win32\mstp.h" /> <Unit filename="..\..\ports\win32\mstp.h" />
<Unit filename="..\..\ports\win32\net.h" /> <Unit filename="..\..\ports\win32\net.h" />
<Unit filename="..\..\ports\win32\rs485.c"> <Unit filename="..\..\ports\win32\rs485.c">
@@ -249,6 +248,10 @@
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
<Unit filename="..\..\rp.h" /> <Unit filename="..\..\rp.h" />
<Unit filename="..\..\rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\rpm.h" />
<Unit filename="..\..\timesync.c"> <Unit filename="..\..\timesync.c">
<Option compilerVar="CC" /> <Option compilerVar="CC" />
</Unit> </Unit>
+2
View File
@@ -67,6 +67,8 @@ static void Init_Service_Handlers(void)
/* We must implement read property - it's required! */ /* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY, apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
handler_read_property); handler_read_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY_MULTIPLE,
handler_read_property_multiple);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY, apdu_set_confirmed_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
handler_write_property); handler_write_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE, apdu_set_confirmed_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
+2
View File
@@ -32,6 +32,7 @@ SRCS = main.c \
..\..\demo\handler\noserv.c \ ..\..\demo\handler\noserv.c \
..\..\demo\handler\h_whois.c \ ..\..\demo\handler\h_whois.c \
..\..\demo\handler\h_rp.c \ ..\..\demo\handler\h_rp.c \
..\..\demo\handler\h_rpm.c \
..\..\demo\handler\h_wp.c \ ..\..\demo\handler\h_wp.c \
..\..\demo\handler\h_arf.c \ ..\..\demo\handler\h_arf.c \
..\..\demo\handler\h_awf.c \ ..\..\demo\handler\h_awf.c \
@@ -52,6 +53,7 @@ SRCS = main.c \
..\..\whohas.c \ ..\..\whohas.c \
..\..\ihave.c \ ..\..\ihave.c \
..\..\rp.c \ ..\..\rp.c \
..\..\rpm.c \
..\..\wp.c \ ..\..\wp.c \
..\..\arf.c \ ..\..\arf.c \
..\..\awf.c \ ..\..\awf.c \
+4 -4
View File
@@ -112,7 +112,7 @@ int rpm_decode_object_id(uint8_t * apdu,
return -1; return -1;
len += decode_object_id(&apdu[len], &type, object_instance); len += decode_object_id(&apdu[len], &type, object_instance);
if (object_type) if (object_type)
*object_type = type; *object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: sequence of ReadAccessSpecification */ /* Tag 1: sequence of ReadAccessSpecification */
if (!decode_is_opening_tag_number(&apdu[len], 1)) if (!decode_is_opening_tag_number(&apdu[len], 1))
return -1; return -1;
@@ -162,7 +162,7 @@ int rpm_decode_object_property(uint8_t * apdu,
return -1; return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property); len += decode_enumerated(&apdu[len], len_value_type, &property);
if (object_property) if (object_property)
*object_property = property; *object_property = (BACNET_PROPERTY_ID)property;
/* Tag 1: Optional propertyArrayIndex */ /* Tag 1: Optional propertyArrayIndex */
if (len < apdu_len) { if (len < apdu_len) {
option_len = option_len =
@@ -317,7 +317,7 @@ int rpm_ack_decode_object_id(uint8_t * apdu,
return -1; return -1;
len += decode_object_id(&apdu[len], &type, object_instance); len += decode_object_id(&apdu[len], &type, object_instance);
if (object_type) if (object_type)
*object_type = type; *object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: listOfResults */ /* Tag 1: listOfResults */
if (!decode_is_opening_tag_number(&apdu[len], 1)) if (!decode_is_opening_tag_number(&apdu[len], 1))
return -1; return -1;
@@ -360,7 +360,7 @@ int rpm_ack_decode_object_property(uint8_t * apdu,
return -1; return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property); len += decode_enumerated(&apdu[len], len_value_type, &property);
if (object_property) if (object_property)
*object_property = property; *object_property = (BACNET_PROPERTY_ID)property;
/* Tag 3: Optional propertyArrayIndex */ /* Tag 3: Optional propertyArrayIndex */
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number, tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type); &len_value_type);
+6 -1
View File
@@ -79,10 +79,15 @@ extern "C" {
unsigned apdu_len, unsigned apdu_len,
BACNET_PROPERTY_ID * object_property, int32_t * array_index); BACNET_PROPERTY_ID * object_property, int32_t * array_index);
/* RPM Ack */ /* RPM Ack - reply from server */
int rpm_ack_encode_apdu_init(uint8_t * apdu, uint8_t invoke_id);
int rpm_ack_encode_apdu_object_begin(uint8_t * apdu, int rpm_ack_encode_apdu_object_begin(uint8_t * apdu,
BACNET_OBJECT_TYPE object_type, uint32_t object_instance); BACNET_OBJECT_TYPE object_type, uint32_t object_instance);
int rpm_ack_encode_apdu_object_property(uint8_t * apdu,
BACNET_PROPERTY_ID object_property, int32_t array_index);
int rpm_ack_encode_apdu_object_property_value(uint8_t * apdu, int rpm_ack_encode_apdu_object_property_value(uint8_t * apdu,
uint8_t * application_data, unsigned application_data_len); uint8_t * application_data, unsigned application_data_len);