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
+483 -262
View File
@@ -1,7 +1,7 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
* Enhanced by John Stachler for ReadPropertyMultiple
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
* Inspired by John Stachler.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -37,37 +37,378 @@
#include "abort.h"
#include "rpm.h"
#include "handlers.h"
/* demo 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"
#if BACFILE
#include "bacfile.h"
#endif
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
static uint8_t Application_Buf[MAX_APDU] = { 0 };
/* copy encoded apdu data to tx buffer
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)
struct property_list_t
{
bool copy_status = false;
if ((*apdu_len + len) <= MAX_APDU) {
memcpy(&Handler_Transmit_Buffer[*apdu_len + npdu_len], &Temp_Buf[0], len);
*apdu_len += len;
copy_status = true;
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++;
}
}
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 copy_len = 0;
int decode_len = 0;
int application_data_len = 0;
int pdu_len = 0;
BACNET_NPDU_DATA npdu_data;
bool error = false;
bool done;
bool property_found;
int bytes_sent;
BACNET_ERROR_CLASS error_class = ERROR_CLASS_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;
BACNET_PROPERTY_ID object_property, temp_object_property;
int32_t array_index = 0;
uint8 index;
uint8 num_properties;
/* jps_debug - see if we are utilizing all the buffer */
/* memset(&Handler_Transmit_Buffer[0], 0xff, MAX_MPDU);*/
@@ -87,7 +426,7 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
datalink_get_my_address(&my_address);
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
npdu_len = npdu_encode_pdu(
&Handler_Transmit_Buffer[0],
&Handler_Transmit_Buffer[0],
src, &my_address, &npdu_data);
#if PRINT_ENABLED
if (service_len <= 0)
@@ -123,7 +462,33 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
&service_request[decode_len],
service_len - decode_len,
&object_type, &object_instance);
/* error - end of object? */
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;
} else {
decode_len += len;
@@ -131,282 +496,138 @@ void handler_read_property_multiple(uint8_t * service_request, uint16_t service_
len = rpm_ack_encode_apdu_object_begin(
&Temp_Buf[0],
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(
&Handler_Transmit_Buffer[npdu_len],
service_data->invoke_id,
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED,
true);
break;
goto RPM_ABORT;
}
/* do each property of this object of the RPM request */
done = true;
num_properties = 0;
property_found = false;
do
{
if (done) {
len = rpm_decode_object_property(
&service_request[decode_len],
service_len - decode_len,
&object_property,
&array_index);
if (len < 0) {
break;
} else {
index = 0;
decode_len += len;
temp_object_property = object_property;
}
len = rpm_decode_object_property(
&service_request[decode_len],
service_len - decode_len,
&object_property,
&array_index);
/* error - end of property list? */
if (len < 0) {
break;
} else {
decode_len += len;
}
/* handle the special properties */
if ((object_property == PROP_ALL) ||
(object_property == PROP_REQUIRED) ||
(object_property == PROP_OPTIONAL))
{
done = false;
switch(object_type)
struct special_property_list_t property_list;
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:
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;
}
if (property_found) {
num_properties++;
} else {
if (num_properties > 0) {
done = true;
/* check for another property */
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;
}
}
}
temp_object_property = RPM_Object_Property(
&property_list,
object_property,
index);
len = rpm_ack_encode_apdu_object_property(
&Temp_Buf[0],
temp_object_property,
array_index);
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;
}
application_data_len = Encode_Property_APDU(
&Application_Buf[0],
object_type,
object_instance,
temp_object_property,
array_index,
&error_class, &error_code);
if (application_data_len < 0) {
len = rpm_ack_encode_apdu_object_property_error(
&Temp_Buf[0],
error_class, error_code);
} else {
error = true;
done = true;
len = rpm_ack_encode_apdu_object_property_value(
&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 {
done = true;
property_found = true;
}
len = rpm_ack_encode_apdu_object_property(
&Temp_Buf[0],
temp_object_property,
array_index);
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;
}
len = encode_opening_tag(&Temp_Buf[0], 4);
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;
}
len = -1;
switch(object_type) {
case OBJECT_DEVICE:
if ((object_instance != Device_Object_Instance_Number()) &&
((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)) {
/* handle an individual property */
application_data_len = Encode_Property_APDU(
&Application_Buf[0],
object_type,
object_instance,
object_property,
array_index,
&error_class, &error_code);
if (application_data_len < 0) {
len = rpm_ack_encode_apdu_object_property_error(
&Temp_Buf[0],
error_class, error_code);
} else {
len = rpm_ack_encode_apdu_object_property_value(
&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);
break;
}
} 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;
goto RPM_ABORT;
}
}
} 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) {
break;
}
} while(1);
}
RPM_ABORT:
pdu_len = apdu_len + npdu_len;
bytes_sent = datalink_send_pdu(
src,
&npdu_data,
&Handler_Transmit_Buffer[0],
src,
&npdu_data,
&Handler_Transmit_Buffer[0],
pdu_len);
}
+9 -2
View File
@@ -77,10 +77,10 @@ extern "C" {
uint16_t service_len,
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_ACK_DATA * service_data);
void handler_atomic_write_file(uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data);
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data);
void handler_reinitialize_device(uint8_t * service_request,
uint16_t service_len,
@@ -101,6 +101,13 @@ extern "C" {
void handler_timesync_utc(uint8_t * service_request,
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
}
#endif /* __cplusplus */
+43
View File
@@ -35,6 +35,49 @@
#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 */
/* more complex, and then you need validate that the */
/* given instance exists */
+4 -1
View File
@@ -32,7 +32,10 @@
#ifdef __cplusplus
extern "C" {
#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);
unsigned Analog_Input_Count(void);
uint32_t Analog_Input_Index_To_Instance(unsigned index);
+46 -4
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 */
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)
{
unsigned i, j;
@@ -172,8 +214,8 @@ bool Analog_Output_Present_Value_Set(uint32_t object_instance,
/* 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
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;
}
@@ -196,8 +238,8 @@ bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
/* 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
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;
}
+4
View File
@@ -35,6 +35,10 @@
extern "C" {
#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);
unsigned Analog_Output_Count(void);
uint32_t Analog_Output_Index_To_Instance(unsigned index);
+46 -4
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 */
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)
{
unsigned i, j;
@@ -304,8 +346,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
Analog_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
@@ -329,8 +371,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* 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
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 {
+4 -1
View File
@@ -34,7 +34,10 @@
#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);
+43 -1
View File
@@ -52,6 +52,48 @@ static BACNET_FILE_LISTING BACnet_File_Listing[] = {
{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)
{
uint32_t index = 0;
@@ -393,7 +435,7 @@ bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA * data)
(void)fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
if (fwrite(octetstring_value(&data->fileData),
octetstring_length(&data->fileData),1,pFile) != 1) {
}
fclose(pFile);
}
+4
View File
@@ -46,6 +46,10 @@
extern "C" {
#endif /* __cplusplus */
void BACfile_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
char *bacfile_name(uint32_t instance);
bool bacfile_valid_instance(uint32_t object_instance);
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 <stdint.h>
@@ -37,6 +37,46 @@
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 */
/* more complex, and then you need validate that the */
/* given instance exists */
+4
View File
@@ -33,6 +33,10 @@
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);
+42
View File
@@ -47,6 +47,48 @@ static BACNET_BINARY_PV
/* without changing the physical output */
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)
{
unsigned i, j;
+4
View File
@@ -35,6 +35,10 @@
extern "C" {
#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);
unsigned Binary_Output_Count(void);
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 */
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)
{
unsigned i, j;
@@ -195,9 +236,6 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
state = Binary_Value_Out_Of_Service[object_index];
apdu_len = encode_tagged_boolean(&apdu[0], state);
break;
case PROP_POLARITY:
apdu_len = encode_tagged_enumerated(&apdu[0], polarity);
break;
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
+4
View File
@@ -35,6 +35,10 @@
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);
+18 -97
View File
@@ -48,7 +48,7 @@
#endif
/* 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_NAME,
@@ -76,7 +76,7 @@ static int Device_Properties_Required[] =
-1
};
static int Device_Properties_Optional[] =
static const int Device_Properties_Optional[] =
{
PROP_DESCRIPTION,
PROP_LOCAL_TIME,
@@ -87,11 +87,26 @@ static int Device_Properties_Optional[] =
-1
};
static int Device_Properties_Proprietary[] =
static const int Device_Properties_Proprietary[] =
{
-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
properties that are writable or that may change.
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;
}
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
#include <assert.h>
#include <string.h>
+6 -15
View File
@@ -44,6 +44,11 @@
extern "C" {
#endif /* __cplusplus */
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);
@@ -76,7 +81,7 @@ extern "C" {
const char *Device_Location(void);
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_Revision(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,
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
}
#endif /* __cplusplus */
+63 -14
View File
@@ -24,6 +24,7 @@
*********************************************************************/
/* Load Control Objects - customize for your use */
/* from 135-2004-Addendum e */
#include <stdbool.h>
#include <stdint.h>
@@ -105,20 +106,20 @@ static bool Start_Time_Property_Written[MAX_LOAD_CONTROLS];
static float Full_Duty_Baseline[MAX_LOAD_CONTROLS];
#define MAX_SHED_LEVELS 3
/* Represents the shed levels for the LEVEL choice of
BACnetShedLevel that have meaning for this particular
/* Represents the shed levels for the LEVEL choice of
BACnetShedLevel that have meaning for this particular
Load Control object. */
/* The elements of the array are required to be writable,
allowing local configuration of how this Load Control
/* The elements of the array are required to be writable,
allowing local configuration of how this Load Control
object will participate in load shedding for the
facility. This array is not required to be resizable
through BACnet write services. The size of this array
shall be equal to the size of the Shed_Level_Descriptions
array. The behavior of this object when the Shed_Levels
facility. This array is not required to be resizable
through BACnet write services. The size of this array
shall be equal to the size of the Shed_Level_Descriptions
array. The behavior of this object when the Shed_Levels
array contains duplicate entries is a local matter. */
static unsigned Shed_Levels[MAX_LOAD_CONTROLS][MAX_SHED_LEVELS];
/* represents a description of the shed levels that the
/* represents a description of the shed levels that the
Load Control object can take on. It is the same for
all the load control objects in this example device. */
static char *Shed_Level_Descriptions[MAX_SHED_LEVELS] = {
@@ -136,6 +137,54 @@ 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,
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)
{
unsigned i, j;
@@ -673,15 +722,15 @@ int Load_Control_Encode_Property_APDU(uint8_t * apdu,
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
/* IN_ALARM - Logical FALSE (0) if the Event_State property
/* IN_ALARM - Logical FALSE (0) if the Event_State property
has a value of NORMAL, otherwise logical TRUE (1). */
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
/* FAULT - Logical TRUE (1) if the Reliability property is
present and does not have a value of NO_FAULT_DETECTED,
/* FAULT - Logical TRUE (1) if the Reliability property is
present and does not have a value of NO_FAULT_DETECTED,
otherwise logical FALSE (0). */
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
/* OVERRIDDEN - Logical TRUE (1) if the point has been
overridden by some mechanism local to the BACnet Device,
/* OVERRIDDEN - Logical TRUE (1) if the point has been
overridden by some mechanism local to the BACnet Device,
otherwise logical FALSE (0). */
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
/* OUT_OF_SERVICE - This bit shall always be Logical FALSE (0). */
+4
View File
@@ -35,6 +35,10 @@
extern "C" {
#endif /* __cplusplus */
void Load_Control_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary);
void Load_Control_State_Machine_Handler(void);
bool Load_Control_Valid_Instance(uint32_t object_instance);
+45 -1
View File
@@ -50,6 +50,50 @@ static BACNET_LIFE_SAFETY_OPERATION
/* without changing the physical output */
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)
{
static bool initialized = false;
@@ -159,7 +203,7 @@ int Life_Safety_Point_Encode_Property_APDU(uint8_t * apdu,
unsigned object_index = 0;
bool state = false;
BACNET_RELIABILITY reliability = RELIABILITY_NO_FAULT_DETECTED;
(void) array_index; /* currently not used */
Life_Safety_Point_Init();
switch (property) {
+4
View File
@@ -35,6 +35,10 @@
extern "C" {
#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);
unsigned Life_Safety_Point_Count(void);
uint32_t Life_Safety_Point_Index_To_Instance(unsigned index);
+46 -4
View File
@@ -52,6 +52,48 @@ static uint8_t
/* without changing the physical output */
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)
{
unsigned i, j;
@@ -315,8 +357,8 @@ bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
(uint8_t) level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
@@ -342,8 +384,8 @@ bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* 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
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 {
+4
View File
@@ -35,6 +35,10 @@
extern "C" {
#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);
unsigned Multistate_Output_Count(void);
uint32_t Multistate_Output_Index_To_Instance(unsigned index);
+7 -5
View File
@@ -19,7 +19,7 @@ BACNET_PORT = ../../ports/linux
BACNET_OBJECT = ../object
BACNET_HANDLER = ../handler
BACNET_ROOT = ../..
INCLUDES = -I$(BACNET_ROOT) -I$(BACNET_PORT) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER)
INCLUDES = -I$(BACNET_ROOT) -I$(BACNET_PORT) -I$(BACNET_OBJECT) -I$(BACNET_HANDLER)
CFLAGS = -Wall -g $(INCLUDES) $(DEFINES)
@@ -38,6 +38,7 @@ SRCS = main.c \
$(BACNET_HANDLER)/noserv.c \
$(BACNET_HANDLER)/h_whois.c \
$(BACNET_HANDLER)/h_rp.c \
$(BACNET_HANDLER)/h_rpm.c \
$(BACNET_HANDLER)/h_wp.c \
$(BACNET_HANDLER)/h_arf.c \
$(BACNET_HANDLER)/h_awf.c \
@@ -71,6 +72,7 @@ SRCS = main.c \
$(BACNET_ROOT)/whohas.c \
$(BACNET_ROOT)/ihave.c \
$(BACNET_ROOT)/rp.c \
$(BACNET_ROOT)/rpm.c \
$(BACNET_ROOT)/wp.c \
$(BACNET_ROOT)/arf.c \
$(BACNET_ROOT)/awf.c \
@@ -86,17 +88,17 @@ SRCS = main.c \
OBJS = ${SRCS:.c=.o}
all: ${TARGET}
${TARGET}: ${OBJS}
${CC} -pthread -o $@ ${OBJS}
${CC} -pthread -o $@ ${OBJS}
.c.o:
${CC} -c ${CFLAGS} $*.c -o $@
depend:
rm -f .depend
${CC} -MM ${CFLAGS} *.c >> .depend
clean:
rm -rf core ${TARGET} $(OBJS) *.bak ports/linux/*.bak *.1 *.ini
+12 -9
View File
@@ -14,11 +14,6 @@
<Compiler>
<Add option="-Wall" />
<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="..\handler" />
<Add directory="..\object" />
@@ -54,7 +49,7 @@
<Add option="-O" />
<Add option="-Wall" />
<Add option="-fexceptions" />
<Add option="-DBACDL_MSTP=1" />
<Add option="-DBACDL_BIP=1" />
<Add option="-DBIP_DEBUG=1" />
<Add option="-DUSE_INADDR=1" />
<Add option="-DPRINT_ENABLED=1" />
@@ -138,6 +133,9 @@
<Unit filename="..\handler\h_rp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\handler\h_rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\handler\h_ts.c">
<Option compilerVar="CC" />
</Unit>
@@ -150,6 +148,7 @@
<Unit filename="..\handler\h_wp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\handler\handlers.h" />
<Unit filename="..\handler\noserv.c">
<Option compilerVar="CC" />
</Unit>
@@ -218,6 +217,9 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\indtext.h" />
<Unit filename="..\..\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\npdu.c">
<Option compilerVar="CC" />
</Unit>
@@ -228,9 +230,6 @@
<Unit filename="..\..\ports\win32\dlmstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\ports\win32\mstp.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\ports\win32\mstp.h" />
<Unit filename="..\..\ports\win32\net.h" />
<Unit filename="..\..\ports\win32\rs485.c">
@@ -249,6 +248,10 @@
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\rp.h" />
<Unit filename="..\..\rpm.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="..\..\rpm.h" />
<Unit filename="..\..\timesync.c">
<Option compilerVar="CC" />
</Unit>
+2
View File
@@ -67,6 +67,8 @@ static void Init_Service_Handlers(void)
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_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,
handler_write_property);
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ATOMIC_READ_FILE,
+4 -2
View File
@@ -32,6 +32,7 @@ SRCS = main.c \
..\..\demo\handler\noserv.c \
..\..\demo\handler\h_whois.c \
..\..\demo\handler\h_rp.c \
..\..\demo\handler\h_rpm.c \
..\..\demo\handler\h_wp.c \
..\..\demo\handler\h_arf.c \
..\..\demo\handler\h_awf.c \
@@ -52,6 +53,7 @@ SRCS = main.c \
..\..\whohas.c \
..\..\ihave.c \
..\..\rp.c \
..\..\rpm.c \
..\..\wp.c \
..\..\arf.c \
..\..\awf.c \
@@ -153,8 +155,8 @@ clean :
# Compiler configuration file
$(BCC_CFG) :
Copy &&|
$(CFLAGS)
-c
$(CFLAGS)
-c
-y #include line numbers in OBJ's
-v #include debug info
-w+ #turn on all warnings
+4 -4
View File
@@ -112,7 +112,7 @@ int rpm_decode_object_id(uint8_t * apdu,
return -1;
len += decode_object_id(&apdu[len], &type, object_instance);
if (object_type)
*object_type = type;
*object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: sequence of ReadAccessSpecification */
if (!decode_is_opening_tag_number(&apdu[len], 1))
return -1;
@@ -162,7 +162,7 @@ int rpm_decode_object_property(uint8_t * apdu,
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
if (object_property)
*object_property = property;
*object_property = (BACNET_PROPERTY_ID)property;
/* Tag 1: Optional propertyArrayIndex */
if (len < apdu_len) {
option_len =
@@ -317,7 +317,7 @@ int rpm_ack_decode_object_id(uint8_t * apdu,
return -1;
len += decode_object_id(&apdu[len], &type, object_instance);
if (object_type)
*object_type = type;
*object_type = (BACNET_OBJECT_TYPE)type;
/* Tag 1: listOfResults */
if (!decode_is_opening_tag_number(&apdu[len], 1))
return -1;
@@ -360,7 +360,7 @@ int rpm_ack_decode_object_property(uint8_t * apdu,
return -1;
len += decode_enumerated(&apdu[len], len_value_type, &property);
if (object_property)
*object_property = property;
*object_property = (BACNET_PROPERTY_ID)property;
/* Tag 3: Optional propertyArrayIndex */
tag_len = decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value_type);
+6 -1
View File
@@ -79,10 +79,15 @@ extern "C" {
unsigned apdu_len,
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,
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,
uint8_t * application_data, unsigned application_data_len);