Added property-list property to Lighting Output and Channel objects (untested). Fixed some compiler warnings.
This commit is contained in:
@@ -42,6 +42,7 @@
|
|||||||
#include "config.h" /* the custom stuff */
|
#include "config.h" /* the custom stuff */
|
||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
|
#include "proplist.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#if defined (CHANNEL_LIGHTING_COMMAND) || defined (BACAPP_LIGHTING_COMMAND)
|
#if defined (CHANNEL_LIGHTING_COMMAND) || defined (BACAPP_LIGHTING_COMMAND)
|
||||||
@@ -74,22 +75,8 @@ struct bacnet_channel_object {
|
|||||||
|
|
||||||
struct bacnet_channel_object Channel[BACNET_CHANNELS_MAX];
|
struct bacnet_channel_object Channel[BACNET_CHANNELS_MAX];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* These arrays are used by the ReadPropertyMultiple handler
|
||||||
static const int Properties_Required[] = {
|
property-list property (as of protocol-revision 14) */
|
||||||
PROP_OBJECT_IDENTIFIER,
|
|
||||||
PROP_OBJECT_NAME,
|
|
||||||
PROP_OBJECT_TYPE,
|
|
||||||
PROP_PRESENT_VALUE,
|
|
||||||
PROP_LAST_PRIORITY,
|
|
||||||
PROP_WRITE_STATUS,
|
|
||||||
PROP_STATUS_FLAGS,
|
|
||||||
PROP_OUT_OF_SERVICE,
|
|
||||||
PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES,
|
|
||||||
PROP_CHANNEL_NUMBER,
|
|
||||||
PROP_CONTROL_GROUPS,
|
|
||||||
-1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const int Properties_Optional[] = {
|
static const int Properties_Optional[] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
@@ -114,7 +101,7 @@ void Channel_Property_Lists(const int **pRequired,
|
|||||||
const int **pProprietary)
|
const int **pProprietary)
|
||||||
{
|
{
|
||||||
if (pRequired)
|
if (pRequired)
|
||||||
*pRequired = Properties_Required;
|
*pRequired = property_list_required(OBJECT_CHANNEL);
|
||||||
if (pOptional)
|
if (pOptional)
|
||||||
*pOptional = Properties_Optional;
|
*pOptional = Properties_Optional;
|
||||||
if (pProprietary)
|
if (pProprietary)
|
||||||
@@ -1374,6 +1361,7 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
|
|||||||
bool state = false;
|
bool state = false;
|
||||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *pMember = NULL;
|
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE *pMember = NULL;
|
||||||
uint8_t *apdu = NULL;
|
uint8_t *apdu = NULL;
|
||||||
|
const int *pRequired = NULL, *pOptional = NULL, *pProprietary = NULL;
|
||||||
|
|
||||||
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||||
(rpdata->application_data_len == 0)) {
|
(rpdata->application_data_len == 0)) {
|
||||||
@@ -1512,6 +1500,14 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case PROP_PROPERTY_LIST:
|
||||||
|
Channel_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||||
|
apdu_len = property_list_encode(
|
||||||
|
rpdata,
|
||||||
|
pRequired,
|
||||||
|
pOptional,
|
||||||
|
pProprietary);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
@@ -1521,6 +1517,7 @@ int Channel_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
|
|||||||
/* only array properties can have array options */
|
/* only array properties can have array options */
|
||||||
if ((apdu_len >= 0)
|
if ((apdu_len >= 0)
|
||||||
&& (rpdata->object_property != PROP_PRIORITY_ARRAY)
|
&& (rpdata->object_property != PROP_PRIORITY_ARRAY)
|
||||||
|
&& (rpdata->object_property != PROP_PROPERTY_LIST)
|
||||||
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
|
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||||
|
|||||||
@@ -426,21 +426,6 @@ rr_info_function Device_Objects_RR_Info(
|
|||||||
return (pObject != NULL ? pObject->Object_RR_Info : NULL);
|
return (pObject != NULL ? pObject->Object_RR_Info : NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
/** For a given object type, returns the special property list.
|
||||||
* This function is used for ReadPropertyMultiple calls which want
|
* This function is used for ReadPropertyMultiple calls which want
|
||||||
* just Required, just Optional, or All properties.
|
* just Required, just Optional, or All properties.
|
||||||
@@ -1143,10 +1128,10 @@ int tm_isdst Daylight Savings flag.
|
|||||||
*/
|
*/
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
time(&tTemp);
|
time(&tTemp);
|
||||||
tblock = localtime(&tTemp);
|
tblock = (struct tm *)localtime(&tTemp);
|
||||||
#else
|
#else
|
||||||
if (gettimeofday(&tv, NULL) == 0) {
|
if (gettimeofday(&tv, NULL) == 0) {
|
||||||
tblock = localtime(&tv.tv_sec);
|
tblock = (struct tm *)localtime((const time_t *)&tv.tv_sec);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "wp.h"
|
#include "wp.h"
|
||||||
#include "lighting.h"
|
#include "lighting.h"
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
|
#include "proplist.h"
|
||||||
/* me! */
|
/* me! */
|
||||||
#include "lo.h"
|
#include "lo.h"
|
||||||
|
|
||||||
@@ -72,21 +73,8 @@ struct lighting_output_object {
|
|||||||
};
|
};
|
||||||
struct lighting_output_object Lighting_Output[MAX_LIGHTING_OUTPUTS];
|
struct lighting_output_object Lighting_Output[MAX_LIGHTING_OUTPUTS];
|
||||||
|
|
||||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
/* These arrays are used by the ReadPropertyMultiple handler and
|
||||||
static const int Properties_Required[] = {
|
property-list property (as of protocol-revision 14) */
|
||||||
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 Properties_Optional[] = {
|
static const int Properties_Optional[] = {
|
||||||
-1
|
-1
|
||||||
};
|
};
|
||||||
@@ -112,7 +100,7 @@ void Lighting_Output_Property_Lists(
|
|||||||
const int **pProprietary)
|
const int **pProprietary)
|
||||||
{
|
{
|
||||||
if (pRequired)
|
if (pRequired)
|
||||||
*pRequired = Properties_Required;
|
*pRequired = property_list_required(OBJECT_LIGHTING_OUTPUT);
|
||||||
if (pOptional)
|
if (pOptional)
|
||||||
*pOptional = Properties_Optional;
|
*pOptional = Properties_Optional;
|
||||||
if (pProprietary)
|
if (pProprietary)
|
||||||
@@ -963,6 +951,7 @@ int Lighting_Output_Read_Property(
|
|||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
bool state = false;
|
bool state = false;
|
||||||
uint8_t *apdu = NULL;
|
uint8_t *apdu = NULL;
|
||||||
|
const int *pRequired = NULL, *pOptional = NULL, *pProprietary = NULL;
|
||||||
|
|
||||||
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||||
(rpdata->application_data_len == 0)) {
|
(rpdata->application_data_len == 0)) {
|
||||||
@@ -1051,12 +1040,12 @@ int Lighting_Output_Read_Property(
|
|||||||
break;
|
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 (rpdata->array_index == 0)
|
if (rpdata->array_index == 0) {
|
||||||
apdu_len =
|
apdu_len =
|
||||||
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
|
||||||
/* if no index was specified, then try to encode the entire list */
|
/* if no index was specified, then try to encode the entire list */
|
||||||
/* into one packet. */
|
/* into one packet. */
|
||||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||||
for (i = 1; i <= BACNET_MAX_PRIORITY; i++) {
|
for (i = 1; i <= BACNET_MAX_PRIORITY; i++) {
|
||||||
if (Lighting_Output_Priority_Active(
|
if (Lighting_Output_Priority_Active(
|
||||||
rpdata->object_instance, i)) {
|
rpdata->object_instance, i)) {
|
||||||
@@ -1110,6 +1099,14 @@ int Lighting_Output_Read_Property(
|
|||||||
apdu_len = encode_application_unsigned(&apdu[0],
|
apdu_len = encode_application_unsigned(&apdu[0],
|
||||||
unsigned_value);
|
unsigned_value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_PROPERTY_LIST:
|
||||||
|
Lighting_Output_Property_Lists(&pRequired, &pOptional, &pProprietary);
|
||||||
|
apdu_len = property_list_encode(
|
||||||
|
rpdata,
|
||||||
|
pRequired,
|
||||||
|
pOptional,
|
||||||
|
pProprietary);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
@@ -1118,6 +1115,7 @@ int Lighting_Output_Read_Property(
|
|||||||
}
|
}
|
||||||
/* only array properties can have array options */
|
/* only array properties can have array options */
|
||||||
if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) &&
|
if ((apdu_len >= 0) && (rpdata->object_property != PROP_PRIORITY_ARRAY) &&
|
||||||
|
(rpdata->object_property != PROP_PROPERTY_LIST) &&
|
||||||
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||||
|
|||||||
@@ -28,10 +28,20 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "rpm.h"
|
#include "rp.h"
|
||||||
|
|
||||||
/** @file proplist.h Library of all required and optional object properties */
|
/** @file proplist.h Library of all required and optional object properties */
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -39,6 +49,10 @@ extern "C" {
|
|||||||
|
|
||||||
unsigned property_list_count(
|
unsigned property_list_count(
|
||||||
const int *pList);
|
const int *pList);
|
||||||
|
const int * property_list_optional(
|
||||||
|
BACNET_OBJECT_TYPE object_type);
|
||||||
|
const int * property_list_required(
|
||||||
|
BACNET_OBJECT_TYPE object_type);
|
||||||
void property_list_special(
|
void property_list_special(
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
struct special_property_list_t *pPropertyList);
|
struct special_property_list_t *pPropertyList);
|
||||||
@@ -49,6 +63,11 @@ extern "C" {
|
|||||||
unsigned property_list_special_count(
|
unsigned property_list_special_count(
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
BACNET_PROPERTY_ID special_property);
|
BACNET_PROPERTY_ID special_property);
|
||||||
|
int property_list_encode(
|
||||||
|
BACNET_READ_PROPERTY_DATA * rpdata,
|
||||||
|
const int *pListRequired,
|
||||||
|
const int *pListOptional,
|
||||||
|
const int *pListProprietary);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
|
#include "proplist.h"
|
||||||
/*
|
/*
|
||||||
* Bundle together commonly used data items for convenience when calling
|
* Bundle together commonly used data items for convenience when calling
|
||||||
* rpm helper functions.
|
* rpm helper functions.
|
||||||
@@ -69,17 +69,6 @@ typedef void (
|
|||||||
const int **pOptional,
|
const int **pOptional,
|
||||||
const int **pProprietary);
|
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 (
|
typedef void (
|
||||||
*rpm_object_property_lists_function) (
|
*rpm_object_property_lists_function) (
|
||||||
BACNET_OBJECT_TYPE object_type,
|
BACNET_OBJECT_TYPE object_type,
|
||||||
|
|||||||
+355
-148
@@ -34,7 +34,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bacenum.h"
|
#include "bacenum.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
|
#include "bacdcode.h"
|
||||||
|
#include "bacenum.h"
|
||||||
#include "rpm.h"
|
#include "rpm.h"
|
||||||
|
#include "rp.h"
|
||||||
#include "proplist.h"
|
#include "proplist.h"
|
||||||
|
|
||||||
/** @file proplist.c List of Required and Optional object properties */
|
/** @file proplist.c List of Required and Optional object properties */
|
||||||
@@ -754,6 +757,189 @@ unsigned property_list_count(
|
|||||||
return property_count;
|
return property_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that returns the list of all Optional properties
|
||||||
|
* of known standard objects.
|
||||||
|
*
|
||||||
|
* @param object_type - enumerated BACNET_OBJECT_TYPE
|
||||||
|
* @return returns a pointer to a '-1' terminated array of
|
||||||
|
* type 'int' that contain BACnet object properties for the given object
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
const int * property_list_optional(
|
||||||
|
BACNET_OBJECT_TYPE object_type)
|
||||||
|
{
|
||||||
|
const int * pList = NULL;
|
||||||
|
|
||||||
|
switch (object_type) {
|
||||||
|
case OBJECT_DEVICE:
|
||||||
|
pList = Device_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_ACCUMULATOR:
|
||||||
|
pList = Accumulator_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_INPUT:
|
||||||
|
pList = Analog_Input_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_OUTPUT:
|
||||||
|
pList = Analog_Output_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_VALUE:
|
||||||
|
pList = Analog_Value_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_AVERAGING:
|
||||||
|
pList = Averaging_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_INPUT:
|
||||||
|
pList = Binary_Input_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_OUTPUT:
|
||||||
|
pList = Binary_Output_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_VALUE:
|
||||||
|
pList = Binary_Value_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_CALENDAR:
|
||||||
|
pList = Calendar_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_CHANNEL:
|
||||||
|
pList = Channel_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_COMMAND:
|
||||||
|
pList = Command_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_CHARACTERSTRING_VALUE:
|
||||||
|
pList =
|
||||||
|
CharacterString_Value_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_LOAD_CONTROL:
|
||||||
|
pList = Load_Control_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_LIFE_SAFETY_POINT:
|
||||||
|
pList =
|
||||||
|
Life_Safety_Point_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_INPUT:
|
||||||
|
pList =
|
||||||
|
Multistate_Input_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_OUTPUT:
|
||||||
|
pList =
|
||||||
|
Multistate_Output_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_VALUE:
|
||||||
|
pList =
|
||||||
|
Multistate_Value_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_NOTIFICATION_CLASS:
|
||||||
|
pList =
|
||||||
|
Notification_Class_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_TRENDLOG:
|
||||||
|
pList = Trend_Log_Properties_Optional;
|
||||||
|
break;
|
||||||
|
case OBJECT_FILE:
|
||||||
|
pList = File_Properties_Optional;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that returns the list of Required properties
|
||||||
|
* of known standard objects.
|
||||||
|
*
|
||||||
|
* @param object_type - enumerated BACNET_OBJECT_TYPE
|
||||||
|
* @return returns a pointer to a '-1' terminated array of
|
||||||
|
* type 'int' that contain BACnet object properties for the given object
|
||||||
|
* type.
|
||||||
|
*/
|
||||||
|
const int * property_list_required(
|
||||||
|
BACNET_OBJECT_TYPE object_type)
|
||||||
|
{
|
||||||
|
const int * pList = NULL;
|
||||||
|
|
||||||
|
switch (object_type) {
|
||||||
|
case OBJECT_DEVICE:
|
||||||
|
pList = Device_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_ACCUMULATOR:
|
||||||
|
pList = Accumulator_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_INPUT:
|
||||||
|
pList = Analog_Input_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_OUTPUT:
|
||||||
|
pList = Analog_Output_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_ANALOG_VALUE:
|
||||||
|
pList = Analog_Value_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_AVERAGING:
|
||||||
|
pList = Averaging_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_INPUT:
|
||||||
|
pList = Binary_Input_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_OUTPUT:
|
||||||
|
pList = Binary_Output_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_BINARY_VALUE:
|
||||||
|
pList = Binary_Value_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_CALENDAR:
|
||||||
|
pList = Calendar_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_CHANNEL:
|
||||||
|
pList = Channel_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_COMMAND:
|
||||||
|
pList = Command_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_CHARACTERSTRING_VALUE:
|
||||||
|
pList =
|
||||||
|
CharacterString_Value_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_LOAD_CONTROL:
|
||||||
|
pList = Load_Control_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_LIFE_SAFETY_POINT:
|
||||||
|
pList =
|
||||||
|
Life_Safety_Point_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_INPUT:
|
||||||
|
pList =
|
||||||
|
Multistate_Input_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_OUTPUT:
|
||||||
|
pList =
|
||||||
|
Multistate_Output_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_MULTI_STATE_VALUE:
|
||||||
|
pList =
|
||||||
|
Multistate_Value_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_NOTIFICATION_CLASS:
|
||||||
|
pList =
|
||||||
|
Notification_Class_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_TRENDLOG:
|
||||||
|
pList = Trend_Log_Properties_Required;
|
||||||
|
break;
|
||||||
|
case OBJECT_FILE:
|
||||||
|
pList = File_Properties_Required;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pList = Default_Properties_Required;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pList;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function that returns the list of Required or Optional properties
|
* Function that returns the list of Required or Optional properties
|
||||||
* of known standard objects.
|
* of known standard objects.
|
||||||
@@ -770,158 +956,14 @@ void property_list_special(
|
|||||||
if (pPropertyList == NULL) {
|
if (pPropertyList == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pPropertyList->Required.pList = property_list_required(object_type);
|
||||||
|
pPropertyList->Optional.pList = property_list_optional(object_type);
|
||||||
pPropertyList->Proprietary.pList = NULL;
|
pPropertyList->Proprietary.pList = NULL;
|
||||||
switch (object_type) {
|
|
||||||
case OBJECT_DEVICE:
|
|
||||||
pPropertyList->Required.pList = Device_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Device_Properties_Optional;
|
|
||||||
break;
|
|
||||||
break;
|
|
||||||
case OBJECT_ACCUMULATOR:
|
|
||||||
pPropertyList->Required.pList = Accumulator_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Accumulator_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_ANALOG_INPUT:
|
|
||||||
pPropertyList->Required.pList = Analog_Input_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Analog_Input_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_ANALOG_OUTPUT:
|
|
||||||
pPropertyList->Required.pList = Analog_Output_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Analog_Output_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_ANALOG_VALUE:
|
|
||||||
pPropertyList->Required.pList = Analog_Value_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Analog_Value_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_AVERAGING:
|
|
||||||
pPropertyList->Required.pList = Averaging_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Averaging_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_BINARY_INPUT:
|
|
||||||
pPropertyList->Required.pList = Binary_Input_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Binary_Input_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_BINARY_OUTPUT:
|
|
||||||
pPropertyList->Required.pList = Binary_Output_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Binary_Output_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_BINARY_VALUE:
|
|
||||||
pPropertyList->Required.pList = Binary_Value_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Binary_Value_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_CALENDAR:
|
|
||||||
pPropertyList->Required.pList = Calendar_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Calendar_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_CHANNEL:
|
|
||||||
pPropertyList->Required.pList = Channel_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Channel_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_COMMAND:
|
|
||||||
pPropertyList->Required.pList = Command_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Command_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_CHARACTERSTRING_VALUE:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
CharacterString_Value_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
CharacterString_Value_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_LOAD_CONTROL:
|
|
||||||
pPropertyList->Required.pList = Load_Control_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Load_Control_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_LIFE_SAFETY_POINT:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
Life_Safety_Point_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
Life_Safety_Point_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_MULTI_STATE_INPUT:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
Multistate_Input_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
Multistate_Input_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_MULTI_STATE_OUTPUT:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
Multistate_Output_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
Multistate_Output_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_MULTI_STATE_VALUE:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
Multistate_Value_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
Multistate_Value_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_NOTIFICATION_CLASS:
|
|
||||||
pPropertyList->Required.pList =
|
|
||||||
Notification_Class_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList =
|
|
||||||
Notification_Class_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_TRENDLOG:
|
|
||||||
pPropertyList->Required.pList = Trend_Log_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = Trend_Log_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_FILE:
|
|
||||||
pPropertyList->Required.pList = File_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = File_Properties_Optional;
|
|
||||||
break;
|
|
||||||
case OBJECT_EVENT_ENROLLMENT:
|
|
||||||
case OBJECT_GROUP:
|
|
||||||
case OBJECT_LOOP:
|
|
||||||
case OBJECT_PROGRAM:
|
|
||||||
case OBJECT_SCHEDULE:
|
|
||||||
case OBJECT_LIFE_SAFETY_ZONE:
|
|
||||||
case OBJECT_PULSE_CONVERTER:
|
|
||||||
case OBJECT_EVENT_LOG:
|
|
||||||
case OBJECT_GLOBAL_GROUP:
|
|
||||||
case OBJECT_TREND_LOG_MULTIPLE:
|
|
||||||
case OBJECT_STRUCTURED_VIEW:
|
|
||||||
case OBJECT_ACCESS_DOOR:
|
|
||||||
case OBJECT_LIGHTING_OUTPUT:
|
|
||||||
case OBJECT_ACCESS_CREDENTIAL:
|
|
||||||
case OBJECT_ACCESS_POINT:
|
|
||||||
case OBJECT_ACCESS_RIGHTS:
|
|
||||||
case OBJECT_ACCESS_USER:
|
|
||||||
case OBJECT_ACCESS_ZONE:
|
|
||||||
case OBJECT_CREDENTIAL_DATA_INPUT:
|
|
||||||
case OBJECT_NETWORK_SECURITY:
|
|
||||||
case OBJECT_BITSTRING_VALUE:
|
|
||||||
case OBJECT_DATE_PATTERN_VALUE:
|
|
||||||
case OBJECT_DATE_VALUE:
|
|
||||||
case OBJECT_DATETIME_PATTERN_VALUE:
|
|
||||||
case OBJECT_DATETIME_VALUE:
|
|
||||||
case OBJECT_INTEGER_VALUE:
|
|
||||||
case OBJECT_LARGE_ANALOG_VALUE:
|
|
||||||
case OBJECT_OCTETSTRING_VALUE:
|
|
||||||
case OBJECT_POSITIVE_INTEGER_VALUE:
|
|
||||||
case OBJECT_TIME_PATTERN_VALUE:
|
|
||||||
case OBJECT_TIME_VALUE:
|
|
||||||
case OBJECT_NOTIFICATION_FORWARDER:
|
|
||||||
case OBJECT_ALERT_ENROLLMENT:
|
|
||||||
pPropertyList->Required.pList = Default_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = NULL;
|
|
||||||
pPropertyList->Proprietary.pList = NULL;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* proprietary objects */
|
|
||||||
pPropertyList->Required.pList = Default_Properties_Required;
|
|
||||||
pPropertyList->Optional.pList = NULL;
|
|
||||||
pPropertyList->Proprietary.pList = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Fetch the counts if available otherwise zero them */
|
/* Fetch the counts if available otherwise zero them */
|
||||||
pPropertyList->Required.count =
|
pPropertyList->Required.count =
|
||||||
pPropertyList->Required.pList ==
|
property_list_count(pPropertyList->Required.pList);
|
||||||
NULL ? 0 : property_list_count(pPropertyList->Required.pList);
|
|
||||||
|
|
||||||
pPropertyList->Optional.count =
|
pPropertyList->Optional.count =
|
||||||
pPropertyList->Optional.pList ==
|
property_list_count(pPropertyList->Optional.pList);
|
||||||
NULL ? 0 : property_list_count(pPropertyList->Optional.pList);
|
|
||||||
|
|
||||||
pPropertyList->Proprietary.count = 0;
|
pPropertyList->Proprietary.count = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -994,6 +1036,171 @@ unsigned property_list_special_count(
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ReadProperty handler for this property. For the given ReadProperty
|
||||||
|
* data, the application_data is loaded or the error flags are set.
|
||||||
|
*
|
||||||
|
* @param rpdata - ReadProperty data, including requested data and
|
||||||
|
* data for the reply, or error response.
|
||||||
|
*
|
||||||
|
* @return number of APDU bytes in the response, or
|
||||||
|
* BACNET_STATUS_ERROR on error.
|
||||||
|
*/
|
||||||
|
int property_list_encode(
|
||||||
|
BACNET_READ_PROPERTY_DATA * rpdata,
|
||||||
|
const int *pListRequired,
|
||||||
|
const int *pListOptional,
|
||||||
|
const int *pListProprietary)
|
||||||
|
{
|
||||||
|
int apdu_len = 0; /* return value */
|
||||||
|
uint8_t *apdu = NULL;
|
||||||
|
int max_apdu_len = 0;
|
||||||
|
unsigned count = 0;
|
||||||
|
unsigned required_count = 0;
|
||||||
|
unsigned optional_count = 0;
|
||||||
|
unsigned proprietary_count = 0;
|
||||||
|
int len = 0;
|
||||||
|
unsigned i = 0; /* loop index */
|
||||||
|
|
||||||
|
required_count = property_list_count(pListRequired);
|
||||||
|
if (required_count >= 3) {
|
||||||
|
/* less the 3 always required properties */
|
||||||
|
count -= 3;
|
||||||
|
} else {
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
optional_count = property_list_count(pListOptional);
|
||||||
|
proprietary_count = property_list_count(pListProprietary);
|
||||||
|
/* total of all counts */
|
||||||
|
count = required_count + optional_count + proprietary_count;
|
||||||
|
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||||
|
(rpdata->application_data_len == 0)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
apdu = rpdata->application_data;
|
||||||
|
max_apdu_len = rpdata->application_data_len;
|
||||||
|
switch (rpdata->object_property) {
|
||||||
|
case PROP_PROPERTY_LIST:
|
||||||
|
if (rpdata->array_index == 0) {
|
||||||
|
/* Array element zero is the number of elements in the array */
|
||||||
|
apdu_len =
|
||||||
|
encode_application_unsigned(&apdu[0], count);
|
||||||
|
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||||
|
/* if no index was specified, then try to encode the entire list */
|
||||||
|
/* into one packet. */
|
||||||
|
if (required_count > 3) {
|
||||||
|
for (i = 0; i < required_count; i++) {
|
||||||
|
if ((pListRequired[i] == PROP_OBJECT_TYPE) ||
|
||||||
|
(pListRequired[i] == PROP_OBJECT_IDENTIFIER) ||
|
||||||
|
(pListRequired[i] == PROP_OBJECT_NAME)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
len =
|
||||||
|
encode_application_enumerated(&apdu[apdu_len],
|
||||||
|
pListRequired[i]);
|
||||||
|
}
|
||||||
|
/* add it if we have room */
|
||||||
|
if ((apdu_len + len) < max_apdu_len) {
|
||||||
|
apdu_len += len;
|
||||||
|
} else {
|
||||||
|
rpdata->error_class = ERROR_CLASS_SERVICES;
|
||||||
|
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (optional_count) {
|
||||||
|
for (i = 0; i < optional_count; i++) {
|
||||||
|
len =
|
||||||
|
encode_application_enumerated(&apdu[apdu_len],
|
||||||
|
pListOptional[i]);
|
||||||
|
/* add it if we have room */
|
||||||
|
if ((apdu_len + len) < max_apdu_len) {
|
||||||
|
apdu_len += len;
|
||||||
|
} else {
|
||||||
|
rpdata->error_class = ERROR_CLASS_SERVICES;
|
||||||
|
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proprietary_count) {
|
||||||
|
for (i = 0; i < proprietary_count; i++) {
|
||||||
|
len =
|
||||||
|
encode_application_enumerated(&apdu[apdu_len],
|
||||||
|
pListProprietary[i]);
|
||||||
|
/* add it if we have room */
|
||||||
|
if ((apdu_len + len) < max_apdu_len) {
|
||||||
|
apdu_len += len;
|
||||||
|
} else {
|
||||||
|
rpdata->error_class = ERROR_CLASS_SERVICES;
|
||||||
|
rpdata->error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (rpdata->array_index <= count) {
|
||||||
|
count = 0;
|
||||||
|
if (required_count > 3) {
|
||||||
|
for (i = 0; i < required_count; i++) {
|
||||||
|
if ((pListRequired[i] == PROP_OBJECT_TYPE) ||
|
||||||
|
(pListRequired[i] == PROP_OBJECT_IDENTIFIER) ||
|
||||||
|
(pListRequired[i] == PROP_OBJECT_NAME)) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (count == rpdata->array_index) {
|
||||||
|
apdu_len = encode_application_enumerated(
|
||||||
|
&apdu[apdu_len],
|
||||||
|
pListRequired[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((apdu_len == 0) && (optional_count > 0)) {
|
||||||
|
for (i = 0; i < optional_count; i++) {
|
||||||
|
count++;
|
||||||
|
if (count == rpdata->array_index) {
|
||||||
|
apdu_len = encode_application_enumerated(
|
||||||
|
&apdu[apdu_len],
|
||||||
|
pListOptional[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((apdu_len == 0) && (proprietary_count > 0)) {
|
||||||
|
for (i = 0; i < proprietary_count; i++) {
|
||||||
|
count++;
|
||||||
|
if (count == rpdata->array_index) {
|
||||||
|
apdu_len = encode_application_enumerated(
|
||||||
|
&apdu[apdu_len],
|
||||||
|
pListProprietary[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||||
|
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||||
|
apdu_len = BACNET_STATUS_ERROR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apdu_len;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user