Removed the object-table function macros from each demo object header file since it was very difficult to maintain when new functions are added. Added device-client.c file which is a small device object just for simple clients. Updated most Makefiles of client demo applications to utilize device-client.c file.
Added two device object table functions for COV support. Corrected demo COV handler interaction with TSM, COV flags, and multiple subscriptions for the same object.
This commit is contained in:
@@ -8,7 +8,8 @@ TARGET = bacdcc
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -51,13 +51,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -123,7 +116,7 @@ void MyDeviceCommunicationControlSimpleAckHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -12,7 +12,7 @@ BORLAND_DIR_Not_Defined:
|
||||
!endif
|
||||
|
||||
# target
|
||||
PRODUCT = bacdcc
|
||||
PRODUCT = bacdcc ..\handler\device-client.c
|
||||
PRODUCT_EXE = $(PRODUCT).exe
|
||||
|
||||
# tools
|
||||
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
<Unit filename="main.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Unit filename="..\object\device-client.c">
|
||||
<Option compilerVar="CC" />
|
||||
</Unit>
|
||||
<Extensions>
|
||||
<code_completion />
|
||||
<envvars />
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/** @file epics/bacepics.c Command line tool to build a full VTS3 EPICS file,
|
||||
/** @file epics/bacepics.c Command line tool to build a full VTS3 EPICS file,
|
||||
* including the heading information. */
|
||||
|
||||
#include <stddef.h>
|
||||
@@ -69,13 +69,6 @@
|
||||
* 3) Postpends the tail information to complete the EPICS file.
|
||||
*/
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -299,7 +292,7 @@ void MyReadPropertyMultipleAckHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
|
||||
#if BAC_ROUTING
|
||||
uint32_t Object_Instance;
|
||||
@@ -335,12 +328,12 @@ static void Init_Service_Handlers(
|
||||
}
|
||||
|
||||
|
||||
/** Determine if this is a writable property, and, if so,
|
||||
/** Determine if this is a writable property, and, if so,
|
||||
* note that in the EPICS output.
|
||||
* This function may need a lot of customization for different implementations;
|
||||
* This function may need a lot of customization for different implementations;
|
||||
* but as a starting point, take the Device object-instance and -name as writable.
|
||||
* For the EPICS output to VTS3, printing 'w' after the property is sufficient,
|
||||
* but to aid readability for human eyes, printing as "Writable".
|
||||
* For the EPICS output to VTS3, printing 'w' after the property is sufficient,
|
||||
* but to aid readability for human eyes, printing as "Writable".
|
||||
*
|
||||
* @param object_type [in] The BACnet Object type of this object.
|
||||
* @note object_instance [in] The ID number for this object.
|
||||
@@ -348,7 +341,7 @@ static void Init_Service_Handlers(
|
||||
* Value, and Error information.
|
||||
*/
|
||||
void CheckIsWritableProperty(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
/* uint32_t object_instance, */
|
||||
BACNET_PROPERTY_REFERENCE * rpm_property)
|
||||
{
|
||||
@@ -639,11 +632,11 @@ void PrintReadPropertyData(
|
||||
break;
|
||||
|
||||
default:
|
||||
/* First, if this is a date type, it needs a different format
|
||||
/* First, if this is a date type, it needs a different format
|
||||
* for VTS, so pretty print it. */
|
||||
if (ShowValues && (object_value.value->tag == BACNET_APPLICATION_TAG_DATE))
|
||||
{
|
||||
/* This would be PROP_LOCAL_DATE, or OBJECT_DATETIME_VALUE,
|
||||
/* This would be PROP_LOCAL_DATE, or OBJECT_DATETIME_VALUE,
|
||||
* or OBJECT_DATE_VALUE */
|
||||
PrettyPrintPropertyValue(stdout, &object_value);
|
||||
} else {
|
||||
@@ -684,7 +677,7 @@ void PrintReadPropertyData(
|
||||
/* Closing brace for this multi-valued array */
|
||||
fprintf(stdout, " }");
|
||||
}
|
||||
CheckIsWritableProperty(object_type, /* object_instance, */
|
||||
CheckIsWritableProperty(object_type, /* object_instance, */
|
||||
rpm_property);
|
||||
fprintf(stdout, "\r\n");
|
||||
}
|
||||
@@ -714,7 +707,7 @@ void Print_Property_Identifier(
|
||||
|
||||
/** Build a list of properties to request with RPM.
|
||||
* @param rpm_object [out] The structure holding our linked list of properties to request.
|
||||
* @param propList [in] Simple list of properties (ptr to array), terminated with -1
|
||||
* @param propList [in] Simple list of properties (ptr to array), terminated with -1
|
||||
*/
|
||||
void BuildPropRequest( BACNET_READ_ACCESS_DATA *rpm_object, int32_t *propList )
|
||||
{
|
||||
@@ -870,8 +863,8 @@ EPICS_STATES ProcessRPMData(
|
||||
free(old_value);
|
||||
}
|
||||
} else if ( myState == GET_HEADING_RESPONSE ) {
|
||||
InitIdValues[i++] = rpm_property->value;
|
||||
/* copy this pointer.
|
||||
InitIdValues[i++] = rpm_property->value;
|
||||
/* copy this pointer.
|
||||
* On error, the pointer will be null
|
||||
* We won't free these values*/
|
||||
} else {
|
||||
@@ -892,7 +885,7 @@ EPICS_STATES ProcessRPMData(
|
||||
|
||||
/* Now determine the next state */
|
||||
if ( myState == GET_HEADING_RESPONSE )
|
||||
nextState = PRINT_HEADING;
|
||||
nextState = PRINT_HEADING;
|
||||
/* press ahead with or without the data */
|
||||
else if (bSuccess && (myState == GET_ALL_RESPONSE))
|
||||
nextState = NEXT_OBJECT;
|
||||
@@ -1038,7 +1031,7 @@ void PrintHeading( )
|
||||
char *relation = "for"; /* Text for Gateways */
|
||||
if ( Target_Address.net != 0 )
|
||||
relation = "provided by"; /* Text for child routed devices */
|
||||
|
||||
|
||||
printf("PICS 0\r\n");
|
||||
printf("BACnet Protocol Implementation Conformance Statement\r\n\r\n");
|
||||
|
||||
@@ -1046,14 +1039,14 @@ void PrintHeading( )
|
||||
printf("-- BACnet/IP Interface for BACnet-stack Devices\r\n");
|
||||
printf("-- http://sourceforge.net/projects/bacnet/ \r\n");
|
||||
printf("-- \r\n-- \r\n\r\n");
|
||||
/* InitIdValues , , , */
|
||||
|
||||
/* InitIdValues , , , */
|
||||
|
||||
value = InitIdValues[INIT_VENDOR_NAME];
|
||||
if ( value != NULL )
|
||||
printf("Vendor Name: \"%s\"\r\n", characterstring_value( &value->type.Character_String) );
|
||||
else
|
||||
printf("Vendor Name: \"bacnet-stack\"\r\n");
|
||||
|
||||
|
||||
value = InitIdValues[INIT_MODEL_NAME];
|
||||
/* Best we can do with Product Name and Model Number is use the same text */
|
||||
if ( value != NULL ) {
|
||||
@@ -1079,11 +1072,11 @@ void PrintHeading( )
|
||||
printf(" DM-DOB-B\r\n");
|
||||
printf(" DM-DCC-B\r\n");
|
||||
printf(" DM-RD-B\r\n");
|
||||
#ifdef BAC_ROUTING
|
||||
#ifdef BAC_ROUTING
|
||||
/* Next line only for the gateway (ie, if not addressing a subNet) */
|
||||
if ( Target_Address.net == 0 )
|
||||
printf(" NM-RC-B\r\n");
|
||||
#endif
|
||||
#endif
|
||||
printf("}\r\n\r\n");
|
||||
/* You might add some of:
|
||||
* -- DS-COV-A DS-COV-B
|
||||
@@ -1104,7 +1097,7 @@ void PrintHeading( )
|
||||
printf(" Who-Is Initiate Execute\r\n");
|
||||
printf(" I-Am Initiate\r\n");
|
||||
printf(" ReinitializeDevice Execute\r\n");
|
||||
#ifdef BAC_ROUTING
|
||||
#ifdef BAC_ROUTING
|
||||
if ( Target_Address.net == 0 )
|
||||
{
|
||||
printf(" -- Note: The following Routing Services are Supported:\r\n");
|
||||
@@ -1113,7 +1106,7 @@ void PrintHeading( )
|
||||
printf(" -- Initialize-Routing-Table Execute\r\n");
|
||||
printf(" -- Initialize-Routing-Table-Ack Initiate\r\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
printf("}\r\n\r\n");
|
||||
/* You might want to add some of:
|
||||
* -- AcknowledgeAlarm Initiate Execute
|
||||
@@ -1132,10 +1125,10 @@ void PrintHeading( )
|
||||
printf("Standard Object-Types Supported:\r\n");
|
||||
printf("{\r\n");
|
||||
value = InitIdValues[INIT_OBJ_TYPES];
|
||||
/* We have to process this bit string and determine which Object Types we have,
|
||||
/* We have to process this bit string and determine which Object Types we have,
|
||||
* and show them
|
||||
*/
|
||||
if ( ( value != NULL ) && (value->tag == BACNET_APPLICATION_TAG_BIT_STRING) )
|
||||
if ( ( value != NULL ) && (value->tag == BACNET_APPLICATION_TAG_BIT_STRING) )
|
||||
{
|
||||
int i, len = bitstring_bits_used(&value->type.Bit_String);
|
||||
for ( i = 0; i < len; i++) {
|
||||
@@ -1148,8 +1141,8 @@ void PrintHeading( )
|
||||
printf(" Binary Input\r\n");
|
||||
printf(" Binary Value\r\n");
|
||||
printf(" Device\r\n");
|
||||
printf(" Multi-state Input\r\n");
|
||||
printf(" Multi-state Value\r\n");
|
||||
printf(" Multi-state Input\r\n");
|
||||
printf(" Multi-state Value\r\n");
|
||||
printf(" Structured View\r\n");
|
||||
printf(" Characterstring Value\r\n");
|
||||
printf(" Datetime Value\r\n");
|
||||
@@ -1163,7 +1156,7 @@ void PrintHeading( )
|
||||
* -- Multi-state Output
|
||||
* -- Trend Log Createable Deleteable
|
||||
* -- Load Control
|
||||
* -- Bitstring Value
|
||||
* -- Bitstring Value
|
||||
* -- Date Pattern Value
|
||||
* -- Date Value
|
||||
* -- Datetime Pattern Value
|
||||
@@ -1172,7 +1165,7 @@ void PrintHeading( )
|
||||
* -- Time Pattern Value
|
||||
* -- Time Value
|
||||
*/
|
||||
|
||||
|
||||
printf("Data Link Layer Option:\r\n");
|
||||
printf("{\r\n");
|
||||
printf(" BACnet/IP, 'DIX' Ethernet\r\n");
|
||||
@@ -1187,8 +1180,8 @@ void PrintHeading( )
|
||||
printf("{\r\n");
|
||||
printf(" Maximum APDU size in octets: 1476\r\n");
|
||||
printf("}\r\n\r\n");
|
||||
|
||||
printf("List of Objects in Test Device:\r\n");
|
||||
|
||||
printf("List of Objects in Test Device:\r\n");
|
||||
/* Print Opening brace, then kick off the Device Object */
|
||||
printf("{\r\n");
|
||||
printf(" {\r\n"); /* And opening brace for the first object */
|
||||
@@ -1342,7 +1335,7 @@ int main(
|
||||
myState = GET_HEADING_INFO;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case GET_HEADING_INFO:
|
||||
last_seconds = current_seconds;
|
||||
StartNextObject(rpm_object, &myObject);
|
||||
@@ -1414,7 +1407,7 @@ int main(
|
||||
elapsed_seconds = 0;
|
||||
invoke_id = 0;
|
||||
if ( myState == GET_HEADING_RESPONSE )
|
||||
myState = PRINT_HEADING;
|
||||
myState = PRINT_HEADING;
|
||||
/* just press ahead without the data */
|
||||
else if (Error_Detected) {
|
||||
/* The normal case for Device Object */
|
||||
@@ -1442,7 +1435,7 @@ int main(
|
||||
invoke_id = 0;
|
||||
elapsed_seconds = 0;
|
||||
if ( myState == GET_HEADING_RESPONSE )
|
||||
myState = PRINT_HEADING;
|
||||
myState = PRINT_HEADING;
|
||||
/* just press ahead without the data */
|
||||
else
|
||||
myState = GET_ALL_REQUEST; /* Let's try again */
|
||||
@@ -1451,7 +1444,7 @@ int main(
|
||||
elapsed_seconds = 0;
|
||||
invoke_id = 0;
|
||||
if ( myState == GET_HEADING_RESPONSE )
|
||||
myState = PRINT_HEADING;
|
||||
myState = PRINT_HEADING;
|
||||
/* just press ahead without the data */
|
||||
else
|
||||
myState = NEXT_OBJECT; /* Give up and move on to the next. */
|
||||
|
||||
@@ -59,20 +59,6 @@
|
||||
#ifdef BACNET_TEST_VMAC
|
||||
#include "vmac.h"
|
||||
#endif
|
||||
#include "ai.h"
|
||||
#include "ao.h"
|
||||
#include "av.h"
|
||||
#include "bi.h"
|
||||
#include "bo.h"
|
||||
#include "bv.h"
|
||||
#include "lc.h"
|
||||
#include "lsp.h"
|
||||
#include "mso.h"
|
||||
#include "ms-input.h"
|
||||
#include "trendlog.h"
|
||||
#if defined(BACFILE)
|
||||
#include "bacfile.h"
|
||||
#endif
|
||||
|
||||
/** @file gateway/main.c Example virtual gateway application using the BACnet Stack. */
|
||||
|
||||
@@ -139,10 +125,10 @@ static void Init_Service_Handlers(
|
||||
Routing_Device_Init(first_object_instance);
|
||||
|
||||
/* we need to handle who-is to support dynamic device binding
|
||||
* For the gateway, we will use the unicast variety so we can
|
||||
* get back through switches to different subnets.
|
||||
* For the gateway, we will use the unicast variety so we can
|
||||
* get back through switches to different subnets.
|
||||
* Don't need the routed versions, since the npdu handler calls
|
||||
* each device in turn.
|
||||
* each device in turn.
|
||||
*/
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
||||
handler_who_is_unicast);
|
||||
|
||||
@@ -53,6 +53,7 @@ typedef struct BACnet_COV_Subscription {
|
||||
uint32_t subscriberProcessIdentifier;
|
||||
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
||||
bool issueConfirmedNotifications; /* optional */
|
||||
uint8_t invokeID; /* for confirmed COV */
|
||||
uint32_t lifetime; /* optional */
|
||||
bool send_requested;
|
||||
} BACNET_COV_SUBSCRIPTION;
|
||||
@@ -223,6 +224,7 @@ void handler_cov_init(
|
||||
OBJECT_ANALOG_INPUT;
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
|
||||
COV_Subscriptions[index].issueConfirmedNotifications = false;
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
COV_Subscriptions[index].lifetime = 0;
|
||||
COV_Subscriptions[index].send_requested = false;
|
||||
}
|
||||
@@ -261,6 +263,10 @@ static bool cov_list_subscribe(
|
||||
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
||||
COV_Subscriptions[index].send_requested = true;
|
||||
}
|
||||
if (COV_Subscriptions[index].invokeID) {
|
||||
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -283,6 +289,7 @@ static bool cov_list_subscribe(
|
||||
cov_data->subscriberProcessIdentifier;
|
||||
COV_Subscriptions[index].issueConfirmedNotifications =
|
||||
cov_data->issueConfirmedNotifications;
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
||||
COV_Subscriptions[index].send_requested = true;
|
||||
} else if (!existing_entry) {
|
||||
@@ -335,6 +342,7 @@ static bool cov_send_request(
|
||||
if (cov_subscription->issueConfirmedNotifications) {
|
||||
invoke_id = tsm_next_free_invokeID();
|
||||
if (invoke_id) {
|
||||
cov_subscription->invokeID = invoke_id;
|
||||
len =
|
||||
ccov_notify_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
|
||||
invoke_id, &cov_data);
|
||||
@@ -385,19 +393,13 @@ static bool cov_send_request(
|
||||
*
|
||||
* @param elapsed_seconds [in] How many seconds have elapsed since last called.
|
||||
*/
|
||||
void handler_cov_task(
|
||||
void handler_cov_timer_seconds(
|
||||
uint32_t elapsed_seconds)
|
||||
{
|
||||
int index = 0, index2 = 0;
|
||||
int index = 0;
|
||||
uint32_t lifetime_seconds = 0;
|
||||
uint16_t object_type = 0, object_type2 = 0;
|
||||
uint32_t object_instance = 0, object_instance2 = 0;
|
||||
bool status = false;
|
||||
BACNET_PROPERTY_VALUE value_list[2];
|
||||
|
||||
value_list[0].next = &value_list[1];
|
||||
value_list[1].next = NULL;
|
||||
/* existing? - match Object ID and Process ID */
|
||||
/* handle the subscription timeouts */
|
||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||
if (COV_Subscriptions[index].valid) {
|
||||
/* handle timeouts */
|
||||
@@ -413,44 +415,102 @@ void handler_cov_task(
|
||||
}
|
||||
if (COV_Subscriptions[index].lifetime == 0) {
|
||||
COV_Subscriptions[index].valid = false;
|
||||
if (COV_Subscriptions[index].issueConfirmedNotifications) {
|
||||
if (COV_Subscriptions[index].invokeID) {
|
||||
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* handle COV notifications */
|
||||
object_type =
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void handler_cov_task(void)
|
||||
{
|
||||
int index = 0;
|
||||
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
|
||||
uint32_t object_instance = 0;
|
||||
bool status = false;
|
||||
BACNET_PROPERTY_VALUE value_list[2];
|
||||
|
||||
/* configure the linked list for the two properties */
|
||||
value_list[0].next = &value_list[1];
|
||||
value_list[1].next = NULL;
|
||||
/* mark any subscriptions where the value has changed */
|
||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||
if (COV_Subscriptions[index].valid) {
|
||||
object_type = (BACNET_OBJECT_TYPE)
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.type;
|
||||
object_instance =
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
|
||||
status =
|
||||
Device_Encode_Value_List(object_type, object_instance,
|
||||
&value_list[0]);
|
||||
status = Device_COV(object_type, object_instance);
|
||||
if (status) {
|
||||
COV_Subscriptions[index].send_requested = true;
|
||||
}
|
||||
if (COV_Subscriptions[index].send_requested) {
|
||||
cov_send_request(&COV_Subscriptions[index], &value_list[0]);
|
||||
COV_Subscriptions[index].send_requested = false;
|
||||
}
|
||||
}
|
||||
/* clear the COV flag after checking all subscriptions (dup objects) */
|
||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||
if (COV_Subscriptions[index].valid) {
|
||||
object_type = (BACNET_OBJECT_TYPE)
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.type;
|
||||
object_instance =
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
|
||||
status = Device_COV(object_type, object_instance);
|
||||
if (status) {
|
||||
Device_COV_Clear(object_type, object_instance);
|
||||
}
|
||||
if (status && ((index + 1) < MAX_COV_SUBCRIPTIONS)) {
|
||||
/* if more than one subscription for this object instance */
|
||||
for (index2 = index + 1; index2 < MAX_COV_SUBCRIPTIONS;
|
||||
index2++) {
|
||||
object_type2 =
|
||||
COV_Subscriptions[index2].monitoredObjectIdentifier.
|
||||
type;
|
||||
object_instance2 =
|
||||
COV_Subscriptions[index2].monitoredObjectIdentifier.
|
||||
instance;
|
||||
if ((COV_Subscriptions[index].lifetime) &&
|
||||
(COV_Subscriptions[index].valid) &&
|
||||
(object_type == object_type2) &&
|
||||
(object_instance == object_instance2)) {
|
||||
cov_send_request(&COV_Subscriptions[index2],
|
||||
&value_list[0]);
|
||||
COV_Subscriptions[index2].send_requested = false;
|
||||
}
|
||||
}
|
||||
/* confirmed notification house keeping */
|
||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||
if (COV_Subscriptions[index].valid) {
|
||||
if (COV_Subscriptions[index].issueConfirmedNotifications) {
|
||||
if (COV_Subscriptions[index].invokeID) {
|
||||
if (tsm_invoke_id_free(COV_Subscriptions[index].invokeID)) {
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
} else if (tsm_invoke_id_failed(
|
||||
COV_Subscriptions[index].invokeID)) {
|
||||
tsm_free_invoke_id(COV_Subscriptions[index].invokeID);
|
||||
COV_Subscriptions[index].invokeID = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* send any COVs that are requested */
|
||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||
if (COV_Subscriptions[index].valid) {
|
||||
if (COV_Subscriptions[index].send_requested) {
|
||||
if (COV_Subscriptions[index].issueConfirmedNotifications) {
|
||||
if (COV_Subscriptions[index].invokeID != 0) {
|
||||
/* already sending - be patient! */
|
||||
continue;
|
||||
}
|
||||
if (!tsm_transaction_available()) {
|
||||
/* no free transactions - be patient! */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
object_type = (BACNET_OBJECT_TYPE)
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.type;
|
||||
object_instance =
|
||||
COV_Subscriptions[index].monitoredObjectIdentifier.instance;
|
||||
(void)Device_Encode_Value_List(object_type, object_instance,
|
||||
&value_list[0]);
|
||||
status = cov_send_request(
|
||||
&COV_Subscriptions[index],
|
||||
&value_list[0]);
|
||||
if (status) {
|
||||
COV_Subscriptions[index].send_requested = false;
|
||||
} else {
|
||||
/* must be out of PDU space - stop for now */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool cov_subscribe(
|
||||
@@ -460,10 +520,10 @@ static bool cov_subscribe(
|
||||
BACNET_ERROR_CODE * error_code)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
uint16_t object_type = 0;
|
||||
BACNET_OBJECT_TYPE object_type = MAX_BACNET_OBJECT_TYPE;
|
||||
uint32_t object_instance = 0;
|
||||
|
||||
object_type = cov_data->monitoredObjectIdentifier.type;
|
||||
object_type = (BACNET_OBJECT_TYPE)cov_data->monitoredObjectIdentifier.type;
|
||||
object_instance = cov_data->monitoredObjectIdentifier.instance;
|
||||
status = Device_Valid_Object_Id(object_type, object_instance);
|
||||
if (status) {
|
||||
@@ -518,7 +578,7 @@ void handler_cov_subscribe(
|
||||
bool error = false;
|
||||
|
||||
/* initialize a common abort code */
|
||||
cov_data.error_code = ABORT_REASON_SEGMENTATION_NOT_SUPPORTED;
|
||||
cov_data.error_code = ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||
/* encode the NPDU portion of the packet */
|
||||
datalink_get_my_address(&my_address);
|
||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||
|
||||
@@ -45,20 +45,66 @@ void handler_unconfirmed_private_transfer(
|
||||
BACNET_ADDRESS * src)
|
||||
{
|
||||
BACNET_PRIVATE_TRANSFER_DATA private_data;
|
||||
BACNET_OBJECT_PROPERTY_VALUE object_value; /* for bacapp printing */
|
||||
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
|
||||
int len = 0;
|
||||
uint8_t *application_data;
|
||||
int application_data_len;
|
||||
bool first_value = true;
|
||||
bool print_brace = false;
|
||||
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr, "Received Unconfirmed Private Transfer Request!\n");
|
||||
#endif
|
||||
(void) src;
|
||||
len =
|
||||
ptransfer_decode_service_request(service_request, service_len,
|
||||
&private_data);
|
||||
len = ptransfer_decode_service_request(
|
||||
service_request, service_len, &private_data);
|
||||
if (len >= 0) {
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stderr,
|
||||
"UnconfirmedPrivateTransfer: " "vendorID=%u serviceNumber=%u\n",
|
||||
private_data.vendorID, private_data.serviceNumber);
|
||||
printf("PrivateTransfer:vendorID=%u\r\n",
|
||||
(unsigned)private_data.vendorID);
|
||||
printf("PrivateTransfer:serviceNumber=%lu\r\n",
|
||||
(unsigned long)private_data.serviceNumber);
|
||||
#endif
|
||||
application_data = private_data.serviceParameters;
|
||||
application_data_len = private_data.serviceParametersLen;
|
||||
for (;;) {
|
||||
len =
|
||||
bacapp_decode_application_data(application_data,
|
||||
(uint8_t) application_data_len, &value);
|
||||
if (first_value && (len < application_data_len)) {
|
||||
first_value = false;
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stdout, "{");
|
||||
#endif
|
||||
print_brace = true;
|
||||
}
|
||||
/* private transfer doesn't provide any clues */
|
||||
object_value.object_type = MAX_BACNET_OBJECT_TYPE;
|
||||
object_value.object_instance = BACNET_MAX_INSTANCE;
|
||||
object_value.object_property = MAX_BACNET_PROPERTY_ID;
|
||||
object_value.array_index = BACNET_ARRAY_ALL;
|
||||
object_value.value = &value;
|
||||
bacapp_print_value(stdout, &object_value);
|
||||
if (len > 0) {
|
||||
if (len < application_data_len) {
|
||||
application_data += len;
|
||||
application_data_len -= len;
|
||||
/* there's more! */
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stdout, ",");
|
||||
#endif
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if PRINT_ENABLED
|
||||
if (print_brace)
|
||||
fprintf(stdout, "}");
|
||||
fprintf(stdout, "\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ TARGET = baciamr
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -46,15 +46,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
/* static uint8_t Rx_Buf[MAX_MPDU] = { 0 }; */
|
||||
|
||||
/* global variables used in this file */
|
||||
#define MAX_ROUTER_DNETS 64
|
||||
static int Target_Router_Networks[MAX_ROUTER_DNETS] = { -1 };
|
||||
@@ -90,7 +81,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ TARGET = bacinitr
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -48,12 +48,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -220,7 +214,7 @@ static void My_NPDU_Handler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -143,9 +143,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define ANALOG_INPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count, \
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance, \
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property, NULL, \
|
||||
Analog_Input_Property_Lists, NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -100,10 +100,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define ANALOG_OUTPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_ANALOG_OUTPUT, Analog_Output_Init, Analog_Output_Count, \
|
||||
Analog_Output_Index_To_Instance, Analog_Output_Valid_Instance, \
|
||||
Analog_Output_Object_Name, Analog_Output_Read_Property, \
|
||||
Analog_Output_Write_Property, Analog_Output_Property_Lists, \
|
||||
NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -132,10 +132,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define ANALOG_VALUE_OBJ_FUNCTIONS \
|
||||
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count, \
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance, \
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property, \
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists, NULL, \
|
||||
NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -98,8 +98,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define FILE_OBJ_FUNCTIONS \
|
||||
OBJECT_FILE, bacfile_init, bacfile_count, bacfile_index_to_instance, \
|
||||
bacfile_valid_instance, bacfile_object_name, bacfile_read_property, \
|
||||
bacfile_write_property, BACfile_Property_Lists, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -183,7 +183,7 @@ bool Binary_Input_Out_Of_Service(
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool Binary_Input_Change_Of_Value(
|
||||
bool Binary_Input_Change_Of_Value(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
bool status = false;
|
||||
@@ -197,7 +197,7 @@ static bool Binary_Input_Change_Of_Value(
|
||||
return status;
|
||||
}
|
||||
|
||||
static void Binary_Input_Change_Of_Value_Clear(
|
||||
void Binary_Input_Change_Of_Value_Clear(
|
||||
uint32_t object_instance)
|
||||
{
|
||||
unsigned index;
|
||||
@@ -249,7 +249,6 @@ bool Binary_Input_Encode_Value_List(
|
||||
value_list->priority = BACNET_NO_PRIORITY;
|
||||
}
|
||||
status = Binary_Input_Change_Of_Value(object_instance);
|
||||
Binary_Input_Change_Of_Value_Clear(object_instance);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,10 @@ extern "C" {
|
||||
bool Binary_Input_Encode_Value_List(
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_VALUE * value_list);
|
||||
bool Binary_Input_Change_Of_Value(
|
||||
uint32_t instance);
|
||||
void Binary_Input_Change_Of_Value_Clear(
|
||||
uint32_t instance);
|
||||
|
||||
int Binary_Input_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata);
|
||||
@@ -110,9 +114,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define BINARY_INPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count, \
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance, \
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property, NULL, \
|
||||
Binary_Input_Property_Lists, NULL, NULL, Binary_Input_Encode_Value_List
|
||||
|
||||
#endif
|
||||
|
||||
@@ -109,10 +109,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define BINARY_OUTPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count, \
|
||||
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance, \
|
||||
Binary_Output_Object_Name, Binary_Output_Read_Property, \
|
||||
Binary_Output_Write_Property, Binary_Output_Property_Lists, \
|
||||
NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,10 +71,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define BINARY_VALUE_OBJ_FUNCTIONS \
|
||||
OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count, \
|
||||
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance, \
|
||||
Binary_Value_Object_Name, Binary_Value_Read_Property, \
|
||||
Binary_Value_Write_Property, Binary_Value_Property_Lists, NULL, \
|
||||
NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,908 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*********************************************************************/
|
||||
|
||||
/** @file device-client.c Lightweight base "class" for handling all
|
||||
* BACnet objects belonging to a BACnet device, as well as
|
||||
* Device-specific properties. This Device instance is designed to
|
||||
* meet minimal functionality for simple clients. */
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include <time.h> /* for timezone, localtime */
|
||||
#include "bacdef.h"
|
||||
#include "bacdcode.h"
|
||||
#include "bacenum.h"
|
||||
#include "bacapp.h"
|
||||
#include "config.h" /* the custom stuff */
|
||||
#include "apdu.h"
|
||||
#include "rp.h" /* ReadProperty handling */
|
||||
#include "version.h"
|
||||
#include "handlers.h"
|
||||
#include "datalink.h"
|
||||
#include "address.h"
|
||||
/* include the device object */
|
||||
#include "device.h" /* me */
|
||||
|
||||
/* 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
|
||||
into the read-property encoding. */
|
||||
|
||||
static uint32_t Object_Instance_Number = 260001;
|
||||
static BACNET_CHARACTER_STRING My_Object_Name;
|
||||
static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
|
||||
static char *Vendor_Name = BACNET_VENDOR_NAME;
|
||||
static uint16_t Vendor_Identifier = BACNET_VENDOR_ID;
|
||||
static char *Model_Name = "GNU";
|
||||
static char *Application_Software_Version = "1.0";
|
||||
static char *Location = "USA";
|
||||
static char *Description = "command line client";
|
||||
/* static uint8_t Protocol_Version = 1; - constant, not settable */
|
||||
/* static uint8_t Protocol_Revision = 4; - constant, not settable */
|
||||
/* Protocol_Services_Supported - dynamically generated */
|
||||
/* Protocol_Object_Types_Supported - in RP encoding */
|
||||
/* Object_List - dynamically generated */
|
||||
/* static BACNET_SEGMENTATION Segmentation_Supported = SEGMENTATION_NONE; */
|
||||
/* static uint8_t Max_Segments_Accepted = 0; */
|
||||
/* VT_Classes_Supported */
|
||||
/* Active_VT_Sessions */
|
||||
/* static BACNET_TIME Local_Time; rely on OS, if there is one */
|
||||
/* static BACNET_DATE Local_Date; rely on OS, if there is one */
|
||||
/* NOTE: BACnet UTC Offset is inverse of common practice.
|
||||
If your UTC offset is -5hours of GMT,
|
||||
then BACnet UTC offset is +5hours.
|
||||
BACnet UTC offset is expressed in minutes. */
|
||||
/* static int32_t UTC_Offset = 5 * 60; */
|
||||
/* static bool Daylight_Savings_Status = false; rely on OS */
|
||||
/* List_Of_Session_Keys */
|
||||
/* Time_Synchronization_Recipients */
|
||||
/* Max_Master - rely on MS/TP subsystem, if there is one */
|
||||
/* Max_Info_Frames - rely on MS/TP subsystem, if there is one */
|
||||
/* Device_Address_Binding - required, but relies on binding cache */
|
||||
static uint32_t Database_Revision = 0;
|
||||
/* Configuration_Files */
|
||||
/* Last_Restore_Time */
|
||||
/* Backup_Failure_Timeout */
|
||||
/* Active_COV_Subscriptions */
|
||||
/* Slave_Proxy_Enable */
|
||||
/* Manual_Slave_Address_Binding */
|
||||
/* Auto_Slave_Discovery */
|
||||
/* Slave_Address_Binding */
|
||||
/* Profile_Name */
|
||||
|
||||
/* local forward (semi-private) and external prototypes */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata);
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{OBJECT_DEVICE,
|
||||
NULL /* Init - don't init Device or it will recourse! */,
|
||||
Device_Count,
|
||||
Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number,
|
||||
Device_Object_Name,
|
||||
Device_Read_Property_Local,
|
||||
NULL /* Write_Property */,
|
||||
NULL /* Property_Lists */,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{MAX_BACNET_OBJECT_TYPE,
|
||||
NULL /* Init */,
|
||||
NULL /* Count */,
|
||||
NULL /* Index_To_Instance */,
|
||||
NULL /* Valid_Instance */,
|
||||
NULL /* Object_Name */,
|
||||
NULL /* Read_Property */,
|
||||
NULL /* Write_Property */,
|
||||
NULL /* Property_Lists */,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */}
|
||||
};
|
||||
|
||||
/** Glue function to let the Device object, when called by a handler,
|
||||
* lookup which Object type needs to be invoked.
|
||||
* @ingroup ObjHelpers
|
||||
* @param Object_Type [in] The type of BACnet Object the handler wants to access.
|
||||
* @return Pointer to the group of object helper functions that implement this
|
||||
* type of Object.
|
||||
*/
|
||||
static struct object_functions *Device_Objects_Find_Functions(
|
||||
BACNET_OBJECT_TYPE Object_Type)
|
||||
{
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
/* handle each object type */
|
||||
if (pObject->Object_Type == Object_Type) {
|
||||
return (pObject);
|
||||
}
|
||||
|
||||
pObject++;
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
unsigned Device_Count(
|
||||
void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t Device_Index_To_Instance(
|
||||
unsigned index)
|
||||
{
|
||||
index = index;
|
||||
return Object_Instance_Number;
|
||||
}
|
||||
|
||||
/* methods to manipulate the data */
|
||||
|
||||
/** Return the Object Instance number for our (single) Device Object.
|
||||
* This is a key function, widely invoked by the handler code, since
|
||||
* it provides "our" (ie, local) address.
|
||||
* @ingroup ObjIntf
|
||||
* @return The Instance number used in the BACNET_OBJECT_ID for the Device.
|
||||
*/
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void)
|
||||
{
|
||||
#ifdef BAC_ROUTING
|
||||
return Routed_Device_Object_Instance_Number();
|
||||
#else
|
||||
return Object_Instance_Number;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
bool status = true; /* return value */
|
||||
|
||||
if (object_id <= BACNET_MAX_INSTANCE) {
|
||||
/* Make the change and update the database revision */
|
||||
Object_Instance_Number = object_id;
|
||||
Device_Inc_Database_Revision();
|
||||
} else
|
||||
status = false;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Valid_Object_Instance_Number(
|
||||
uint32_t object_id)
|
||||
{
|
||||
/* BACnet allows for a wildcard instance number */
|
||||
return ((Object_Instance_Number == object_id) ||
|
||||
(object_id == BACNET_MAX_INSTANCE));
|
||||
}
|
||||
|
||||
bool Device_Object_Name(
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (object_instance == Object_Instance_Number) {
|
||||
status = characterstring_copy(object_name, &My_Object_Name);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Device_Set_Object_Name(
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (!characterstring_same(&My_Object_Name, object_name)) {
|
||||
/* Make the change and update the database revision */
|
||||
status = characterstring_copy(&My_Object_Name, object_name);
|
||||
Device_Inc_Database_Revision();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BACNET_DEVICE_STATUS Device_System_Status(
|
||||
void)
|
||||
{
|
||||
return System_Status;
|
||||
}
|
||||
|
||||
int Device_Set_System_Status(
|
||||
BACNET_DEVICE_STATUS status,
|
||||
bool local)
|
||||
{
|
||||
int result = 0; /*return value - 0 = ok, -1 = bad value, -2 = not allowed */
|
||||
|
||||
/* We limit the options available depending on whether the source is
|
||||
* internal or external. */
|
||||
if (local) {
|
||||
switch (status) {
|
||||
case STATUS_OPERATIONAL:
|
||||
case STATUS_OPERATIONAL_READ_ONLY:
|
||||
case STATUS_DOWNLOAD_REQUIRED:
|
||||
case STATUS_DOWNLOAD_IN_PROGRESS:
|
||||
case STATUS_NON_OPERATIONAL:
|
||||
System_Status = status;
|
||||
break;
|
||||
|
||||
/* Don't support backup at present so don't allow setting */
|
||||
case STATUS_BACKUP_IN_PROGRESS:
|
||||
result = -2;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (status) {
|
||||
/* Allow these for the moment as a way to easily alter
|
||||
* overall device operation. The lack of password protection
|
||||
* or other authentication makes allowing writes to this
|
||||
* property a risky facility to provide.
|
||||
*/
|
||||
case STATUS_OPERATIONAL:
|
||||
case STATUS_OPERATIONAL_READ_ONLY:
|
||||
case STATUS_NON_OPERATIONAL:
|
||||
System_Status = status;
|
||||
break;
|
||||
|
||||
/* Don't allow outsider set this - it should probably
|
||||
* be set if the device config is incomplete or
|
||||
* corrupted or perhaps after some sort of operator
|
||||
* wipe operation.
|
||||
*/
|
||||
case STATUS_DOWNLOAD_REQUIRED:
|
||||
/* Don't allow outsider set this - it should be set
|
||||
* internally at the start of a multi packet download
|
||||
* perhaps indirectly via PT or WF to a config file.
|
||||
*/
|
||||
case STATUS_DOWNLOAD_IN_PROGRESS:
|
||||
/* Don't support backup at present so don't allow setting */
|
||||
case STATUS_BACKUP_IN_PROGRESS:
|
||||
result = -2;
|
||||
break;
|
||||
|
||||
default:
|
||||
result = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
const char *Device_Vendor_Name(
|
||||
void)
|
||||
{
|
||||
return Vendor_Name;
|
||||
}
|
||||
|
||||
/** Returns the Vendor ID for this Device.
|
||||
* See the assignments at http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm
|
||||
* @return The Vendor ID of this Device.
|
||||
*/
|
||||
uint16_t Device_Vendor_Identifier(
|
||||
void)
|
||||
{
|
||||
return Vendor_Identifier;
|
||||
}
|
||||
|
||||
void Device_Set_Vendor_Identifier(
|
||||
uint16_t vendor_id)
|
||||
{
|
||||
Vendor_Identifier = vendor_id;
|
||||
}
|
||||
|
||||
const char *Device_Model_Name(
|
||||
void)
|
||||
{
|
||||
return Model_Name;
|
||||
}
|
||||
|
||||
bool Device_Set_Model_Name(
|
||||
const char *name,
|
||||
size_t length)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (length < sizeof(Model_Name)) {
|
||||
memmove(Model_Name, name, length);
|
||||
Model_Name[length] = 0;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const char *Device_Firmware_Revision(
|
||||
void)
|
||||
{
|
||||
return BACnet_Version;
|
||||
}
|
||||
|
||||
const char *Device_Application_Software_Version(
|
||||
void)
|
||||
{
|
||||
return Application_Software_Version;
|
||||
}
|
||||
|
||||
bool Device_Set_Application_Software_Version(
|
||||
const char *name,
|
||||
size_t length)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (length < sizeof(Application_Software_Version)) {
|
||||
memmove(Application_Software_Version, name, length);
|
||||
Application_Software_Version[length] = 0;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const char *Device_Description(
|
||||
void)
|
||||
{
|
||||
return Description;
|
||||
}
|
||||
|
||||
bool Device_Set_Description(
|
||||
const char *name,
|
||||
size_t length)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (length < sizeof(Description)) {
|
||||
memmove(Description, name, length);
|
||||
Description[length] = 0;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const char *Device_Location(
|
||||
void)
|
||||
{
|
||||
return Location;
|
||||
}
|
||||
|
||||
bool Device_Set_Location(
|
||||
const char *name,
|
||||
size_t length)
|
||||
{
|
||||
bool status = false; /*return value */
|
||||
|
||||
if (length < sizeof(Location)) {
|
||||
memmove(Location, name, length);
|
||||
Location[length] = 0;
|
||||
status = true;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Version(
|
||||
void)
|
||||
{
|
||||
return BACNET_PROTOCOL_VERSION;
|
||||
}
|
||||
|
||||
uint8_t Device_Protocol_Revision(
|
||||
void)
|
||||
{
|
||||
return BACNET_PROTOCOL_REVISION;
|
||||
}
|
||||
|
||||
BACNET_SEGMENTATION Device_Segmentation_Supported(
|
||||
void)
|
||||
{
|
||||
return SEGMENTATION_NONE;
|
||||
}
|
||||
|
||||
uint32_t Device_Database_Revision(
|
||||
void)
|
||||
{
|
||||
return Database_Revision;
|
||||
}
|
||||
|
||||
void Device_Set_Database_Revision(
|
||||
uint32_t revision)
|
||||
{
|
||||
Database_Revision = revision;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shortcut for incrementing database revision as this is potentially
|
||||
* the most common operation if changing object names and ids is
|
||||
* implemented.
|
||||
*/
|
||||
void Device_Inc_Database_Revision(
|
||||
void)
|
||||
{
|
||||
Database_Revision++;
|
||||
}
|
||||
|
||||
/** Get the total count of objects supported by this Device Object.
|
||||
* @note Since many network clients depend on the object list
|
||||
* for discovery, it must be consistent!
|
||||
* @return The count of objects, for all supported Object types.
|
||||
*/
|
||||
unsigned Device_Object_List_Count(
|
||||
void)
|
||||
{
|
||||
unsigned count = 0; /* number of objects */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Count) {
|
||||
count += pObject->Object_Count();
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/** Lookup the Object at the given array index in the Device's Object List.
|
||||
* Even though we don't keep a single linear array of objects in the Device,
|
||||
* this method acts as though we do and works through a virtual, concatenated
|
||||
* array of all of our object type arrays.
|
||||
*
|
||||
* @param array_index [in] The desired array index (1 to N)
|
||||
* @param object_type [out] The object's type, if found.
|
||||
* @param instance [out] The object's instance number, if found.
|
||||
* @return True if found, else false.
|
||||
*/
|
||||
bool Device_Object_List_Identifier(
|
||||
unsigned array_index,
|
||||
int *object_type,
|
||||
uint32_t * instance)
|
||||
{
|
||||
bool status = false;
|
||||
unsigned count = 0;
|
||||
unsigned object_index = 0;
|
||||
unsigned temp_index = 0;
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* array index zero is length - so invalid */
|
||||
if (array_index == 0) {
|
||||
return status;
|
||||
}
|
||||
object_index = array_index - 1;
|
||||
/* initialize the default return values */
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Count) {
|
||||
object_index -= count;
|
||||
count = pObject->Object_Count();
|
||||
if (object_index < count) {
|
||||
/* Use the iterator function if available otherwise
|
||||
* look for the index to instance to get the ID */
|
||||
if (pObject->Object_Iterator) {
|
||||
/* First find the first object */
|
||||
temp_index = pObject->Object_Iterator(~(unsigned) 0);
|
||||
/* Then step through the objects to find the nth */
|
||||
while (object_index != 0) {
|
||||
temp_index = pObject->Object_Iterator(temp_index);
|
||||
object_index--;
|
||||
}
|
||||
/* set the object_index up before falling through to next bit */
|
||||
object_index = temp_index;
|
||||
}
|
||||
if (pObject->Object_Index_To_Instance) {
|
||||
*object_type = pObject->Object_Type;
|
||||
*instance =
|
||||
pObject->Object_Index_To_Instance(object_index);
|
||||
status = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Determine if we have an object with the given object_name.
|
||||
* If the object_type and object_instance pointers are not null,
|
||||
* and the lookup succeeds, they will be given the resulting values.
|
||||
* @param object_name [in] The desired Object Name to look for.
|
||||
* @param object_type [out] The BACNET_OBJECT_TYPE of the matching Object.
|
||||
* @param object_instance [out] The object instance number of the matching Object.
|
||||
* @return True on success or else False if not found.
|
||||
*/
|
||||
bool Device_Valid_Object_Name(
|
||||
BACNET_CHARACTER_STRING * object_name1,
|
||||
int *object_type,
|
||||
uint32_t * object_instance)
|
||||
{
|
||||
bool found = false;
|
||||
int type = 0;
|
||||
uint32_t instance;
|
||||
unsigned max_objects = 0, i = 0;
|
||||
bool check_id = false;
|
||||
BACNET_CHARACTER_STRING object_name2;
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
max_objects = Device_Object_List_Count();
|
||||
for (i = 0; i < max_objects; i++) {
|
||||
check_id = Device_Object_List_Identifier(i, &type, &instance);
|
||||
if (check_id) {
|
||||
pObject = Device_Objects_Find_Functions(type);
|
||||
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
|
||||
(pObject->Object_Name(instance, &object_name2) &&
|
||||
characterstring_same(object_name1, &object_name2))) {
|
||||
found = true;
|
||||
if (object_type) {
|
||||
*object_type = type;
|
||||
}
|
||||
if (object_instance) {
|
||||
*object_instance = instance;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/** Determine if we have an object of this type and instance number.
|
||||
* @param object_type [in] The desired BACNET_OBJECT_TYPE
|
||||
* @param object_instance [in] The object instance number to be looked up.
|
||||
* @return True if found, else False if no such Object in this device.
|
||||
*/
|
||||
bool Device_Valid_Object_Id(
|
||||
int object_type,
|
||||
uint32_t object_instance)
|
||||
{
|
||||
bool status = false; /* return value */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
pObject = Device_Objects_Find_Functions(object_type);
|
||||
if ((pObject != NULL) && (pObject->Object_Valid_Instance != NULL)) {
|
||||
status = pObject->Object_Valid_Instance(object_instance);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** Copy a child object's object_name value, given its ID.
|
||||
* @param object_type [in] The BACNET_OBJECT_TYPE of the child Object.
|
||||
* @param object_instance [in] The object instance number of the child Object.
|
||||
* @param object_name [out] The Object Name found for this child Object.
|
||||
* @return True on success or else False if not found.
|
||||
*/
|
||||
bool Device_Object_Name_Copy(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
{
|
||||
struct object_functions *pObject = NULL;
|
||||
bool found = false;
|
||||
|
||||
pObject = Device_Objects_Find_Functions(object_type);
|
||||
if ((pObject != NULL) && (pObject->Object_Name != NULL)) {
|
||||
found = pObject->Object_Name(object_instance, object_name);
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error or
|
||||
BACNET_STATUS_ABORT for abort message */
|
||||
int Device_Read_Property_Local(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
{
|
||||
int apdu_len = 0; /* return value */
|
||||
int len = 0; /* apdu len intermediate value */
|
||||
BACNET_BIT_STRING bit_string;
|
||||
BACNET_CHARACTER_STRING char_string;
|
||||
unsigned i = 0;
|
||||
int object_type = 0;
|
||||
uint32_t instance = 0;
|
||||
unsigned count = 0;
|
||||
uint8_t *apdu = NULL;
|
||||
struct object_functions *pObject = NULL;
|
||||
bool found = false;
|
||||
|
||||
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
|
||||
(rpdata->application_data_len == 0)) {
|
||||
return 0;
|
||||
}
|
||||
apdu = rpdata->application_data;
|
||||
switch (rpdata->object_property) {
|
||||
case PROP_OBJECT_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
|
||||
Object_Instance_Number);
|
||||
break;
|
||||
case PROP_OBJECT_NAME:
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &My_Object_Name);
|
||||
break;
|
||||
case PROP_OBJECT_TYPE:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
|
||||
break;
|
||||
case PROP_DESCRIPTION:
|
||||
characterstring_init_ansi(&char_string, Description);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_SYSTEM_STATUS:
|
||||
apdu_len = encode_application_enumerated(&apdu[0], System_Status);
|
||||
break;
|
||||
case PROP_VENDOR_NAME:
|
||||
characterstring_init_ansi(&char_string, Vendor_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_VENDOR_IDENTIFIER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], Vendor_Identifier);
|
||||
break;
|
||||
case PROP_MODEL_NAME:
|
||||
characterstring_init_ansi(&char_string, Model_Name);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_FIRMWARE_REVISION:
|
||||
characterstring_init_ansi(&char_string, BACnet_Version);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_APPLICATION_SOFTWARE_VERSION:
|
||||
characterstring_init_ansi(&char_string,
|
||||
Application_Software_Version);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_LOCATION:
|
||||
characterstring_init_ansi(&char_string, Location);
|
||||
apdu_len =
|
||||
encode_application_character_string(&apdu[0], &char_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_VERSION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Version());
|
||||
break;
|
||||
case PROP_PROTOCOL_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
Device_Protocol_Revision());
|
||||
break;
|
||||
case PROP_PROTOCOL_SERVICES_SUPPORTED:
|
||||
/* Note: list of services that are executed, not initiated. */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
|
||||
/* automatic lookup based on handlers set */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i,
|
||||
apdu_service_supported((BACNET_SERVICES_SUPPORTED) i));
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
|
||||
/* Note: this is the list of objects that can be in this device,
|
||||
not a list of objects that this device can access */
|
||||
bitstring_init(&bit_string);
|
||||
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
|
||||
/* initialize all the object types to not-supported */
|
||||
bitstring_set_bit(&bit_string, (uint8_t) i, false);
|
||||
}
|
||||
/* set the object types with objects to supported */
|
||||
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if ((pObject->Object_Count) && (pObject->Object_Count() > 0)) {
|
||||
bitstring_set_bit(&bit_string, pObject->Object_Type, true);
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
|
||||
break;
|
||||
case PROP_OBJECT_LIST:
|
||||
count = Device_Object_List_Count();
|
||||
/* Array element zero is the number of objects in the list */
|
||||
if (rpdata->array_index == 0)
|
||||
apdu_len = encode_application_unsigned(&apdu[0], count);
|
||||
/* if no index was specified, then try to encode the entire list */
|
||||
/* into one packet. Note that more than likely you will have */
|
||||
/* to return an error if the number of encoded objects exceeds */
|
||||
/* your maximum APDU size. */
|
||||
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
|
||||
for (i = 1; i <= count; i++) {
|
||||
found =
|
||||
Device_Object_List_Identifier(i, &object_type,
|
||||
&instance);
|
||||
if (found) {
|
||||
len =
|
||||
encode_application_object_id(&apdu[apdu_len],
|
||||
object_type, instance);
|
||||
apdu_len += len;
|
||||
/* assume next one is the same size as this one */
|
||||
/* can we all fit into the APDU? Don't check for last entry */
|
||||
if ((i != count) && (apdu_len + len) >= MAX_APDU) {
|
||||
/* Abort response */
|
||||
rpdata->error_code =
|
||||
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
|
||||
apdu_len = BACNET_STATUS_ABORT;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* error: internal error? */
|
||||
rpdata->error_class = ERROR_CLASS_SERVICES;
|
||||
rpdata->error_code = ERROR_CODE_OTHER;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
found =
|
||||
Device_Object_List_Identifier(rpdata->array_index,
|
||||
&object_type, &instance);
|
||||
if (found) {
|
||||
apdu_len =
|
||||
encode_application_object_id(&apdu[0], object_type,
|
||||
instance);
|
||||
} else {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROP_MAX_APDU_LENGTH_ACCEPTED:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_SEGMENTATION_SUPPORTED:
|
||||
apdu_len =
|
||||
encode_application_enumerated(&apdu[0],
|
||||
Device_Segmentation_Supported());
|
||||
break;
|
||||
case PROP_APDU_TIMEOUT:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
|
||||
break;
|
||||
case PROP_NUMBER_OF_APDU_RETRIES:
|
||||
apdu_len = encode_application_unsigned(&apdu[0], apdu_retries());
|
||||
break;
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
/* FIXME: the real max apdu remaining should be passed into function */
|
||||
apdu_len = address_list_encode(&apdu[0], MAX_APDU);
|
||||
break;
|
||||
case PROP_DATABASE_REVISION:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], Database_Revision);
|
||||
break;
|
||||
#if defined(BACDL_MSTP)
|
||||
case PROP_MAX_INFO_FRAMES:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0],
|
||||
dlmstp_max_info_frames());
|
||||
break;
|
||||
case PROP_MAX_MASTER:
|
||||
apdu_len =
|
||||
encode_application_unsigned(&apdu[0], dlmstp_max_master());
|
||||
break;
|
||||
#endif
|
||||
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
|
||||
break;
|
||||
default:
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
/* only array properties can have array options */
|
||||
if ((apdu_len >= 0) && (rpdata->object_property != PROP_OBJECT_LIST) &&
|
||||
(rpdata->array_index != BACNET_ARRAY_ALL)) {
|
||||
rpdata->error_class = ERROR_CLASS_PROPERTY;
|
||||
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
|
||||
apdu_len = BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/** Looks up the requested Object and Property, and encodes its Value in an APDU.
|
||||
* @ingroup ObjIntf
|
||||
* If the Object or Property can't be found, sets the error class and code.
|
||||
*
|
||||
* @param rpdata [in,out] Structure with the desired Object and Property info
|
||||
* on entry, and APDU message on return.
|
||||
* @return The length of the APDU on success, else BACNET_STATUS_ERROR
|
||||
*/
|
||||
int Device_Read_Property(
|
||||
BACNET_READ_PROPERTY_DATA * rpdata)
|
||||
{
|
||||
int apdu_len = BACNET_STATUS_ERROR;
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
rpdata->error_class = ERROR_CLASS_OBJECT;
|
||||
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
pObject = Device_Objects_Find_Functions(rpdata->object_type);
|
||||
if (pObject != NULL) {
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(rpdata->object_instance)) {
|
||||
if (pObject->Object_Read_Property) {
|
||||
apdu_len = pObject->Object_Read_Property(rpdata);
|
||||
}
|
||||
} else {
|
||||
rpdata->error_class = ERROR_CLASS_OBJECT;
|
||||
rpdata->error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||
}
|
||||
} else {
|
||||
rpdata->error_class = ERROR_CLASS_OBJECT;
|
||||
rpdata->error_code = ERROR_CODE_UNSUPPORTED_OBJECT_TYPE;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/** Initialize the Device Object.
|
||||
Initialize the group of object helper functions for any supported Object.
|
||||
Initialize each of the Device Object child Object instances.
|
||||
* @ingroup ObjIntf
|
||||
* @param object_table [in,out] array of structure with object functions.
|
||||
* Each Child Object must provide some implementation of each of these
|
||||
* functions in order to properly support the default handlers.
|
||||
*/
|
||||
void Device_Init(
|
||||
object_functions_t * object_table)
|
||||
{
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
characterstring_init_ansi(&My_Object_Name, "SimpleClient");
|
||||
/* we don't use the object table passed in */
|
||||
(void) object_table;
|
||||
pObject = &Object_Table[0];
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Init) {
|
||||
pObject->Object_Init();
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
}
|
||||
@@ -83,87 +83,209 @@ extern int Routed_Device_Read_Property_Local(
|
||||
extern bool Routed_Device_Write_Property_Local(
|
||||
BACNET_WRITE_PROPERTY_DATA * wp_data);
|
||||
|
||||
/* may be overridden by outside table */
|
||||
static object_functions_t *Object_Table;
|
||||
|
||||
static object_functions_t Object_Table[] = {
|
||||
{
|
||||
OBJECT_DEVICE, NULL, Device_Count, /* don't init - recursive! */
|
||||
Device_Index_To_Instance, Device_Valid_Object_Instance_Number,
|
||||
Device_Object_Name, Device_Read_Property_Local,
|
||||
Device_Write_Property_Local, Device_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name, Analog_Input_Read_Property,
|
||||
Analog_Input_Write_Property, Analog_Input_Property_Lists,
|
||||
NULL, NULL, NULL, Analog_Input_Intrinsic_Reporting}, {
|
||||
OBJECT_ANALOG_VALUE, Analog_Value_Init, Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance, Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name, Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property, Analog_Value_Property_Lists,
|
||||
NULL, NULL, NULL, Analog_Value_Intrinsic_Reporting}, {
|
||||
OBJECT_BINARY_INPUT, Binary_Input_Init, Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance, Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name, Binary_Input_Read_Property,
|
||||
NULL, Binary_Input_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_BINARY_VALUE, Binary_Value_Init, Binary_Value_Count,
|
||||
Binary_Value_Index_To_Instance, Binary_Value_Valid_Instance,
|
||||
Binary_Value_Object_Name, Binary_Value_Read_Property,
|
||||
Binary_Value_Write_Property, Binary_Value_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
static object_functions_t My_Object_Table[] = {
|
||||
{OBJECT_DEVICE,
|
||||
NULL /* Init - don't init Device or it will recourse! */,
|
||||
Device_Count,
|
||||
Device_Index_To_Instance,
|
||||
Device_Valid_Object_Instance_Number,
|
||||
Device_Object_Name,
|
||||
Device_Read_Property_Local,
|
||||
Device_Write_Property_Local,
|
||||
Device_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_ANALOG_INPUT,
|
||||
Analog_Input_Init,
|
||||
Analog_Input_Count,
|
||||
Analog_Input_Index_To_Instance,
|
||||
Analog_Input_Valid_Instance,
|
||||
Analog_Input_Object_Name,
|
||||
Analog_Input_Read_Property,
|
||||
Analog_Input_Write_Property,
|
||||
Analog_Input_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
Analog_Input_Intrinsic_Reporting},
|
||||
{OBJECT_ANALOG_VALUE,
|
||||
Analog_Value_Init,
|
||||
Analog_Value_Count,
|
||||
Analog_Value_Index_To_Instance,
|
||||
Analog_Value_Valid_Instance,
|
||||
Analog_Value_Object_Name,
|
||||
Analog_Value_Read_Property,
|
||||
Analog_Value_Write_Property,
|
||||
Analog_Value_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
Analog_Value_Intrinsic_Reporting},
|
||||
{OBJECT_BINARY_INPUT,
|
||||
Binary_Input_Init,
|
||||
Binary_Input_Count,
|
||||
Binary_Input_Index_To_Instance,
|
||||
Binary_Input_Valid_Instance,
|
||||
Binary_Input_Object_Name,
|
||||
Binary_Input_Read_Property,
|
||||
NULL /* Write Property */,
|
||||
Binary_Input_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
Binary_Input_Encode_Value_List,
|
||||
Binary_Input_Change_Of_Value,
|
||||
Binary_Input_Change_Of_Value_Clear,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_BINARY_VALUE,
|
||||
Binary_Value_Init,
|
||||
Binary_Value_Count,
|
||||
Binary_Value_Index_To_Instance,
|
||||
Binary_Value_Valid_Instance,
|
||||
Binary_Value_Object_Name,
|
||||
Binary_Value_Read_Property,
|
||||
Binary_Value_Write_Property,
|
||||
Binary_Value_Property_Lists,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init,
|
||||
Notification_Class_Count,
|
||||
Notification_Class_Index_To_Instance,
|
||||
Notification_Class_Valid_Instance,
|
||||
Notification_Class_Object_Name, Notification_Class_Read_Property,
|
||||
Notification_Class_Write_Property,
|
||||
Notification_Class_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
{OBJECT_NOTIFICATION_CLASS,
|
||||
Notification_Class_Init,
|
||||
Notification_Class_Count,
|
||||
Notification_Class_Index_To_Instance,
|
||||
Notification_Class_Valid_Instance,
|
||||
Notification_Class_Object_Name,
|
||||
Notification_Class_Read_Property,
|
||||
Notification_Class_Write_Property,
|
||||
Notification_Class_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
#endif
|
||||
OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init,
|
||||
Life_Safety_Point_Count,
|
||||
Life_Safety_Point_Index_To_Instance,
|
||||
Life_Safety_Point_Valid_Instance,
|
||||
Life_Safety_Point_Object_Name, Life_Safety_Point_Read_Property,
|
||||
Life_Safety_Point_Write_Property, Life_Safety_Point_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count,
|
||||
Load_Control_Index_To_Instance, Load_Control_Valid_Instance,
|
||||
Load_Control_Object_Name, Load_Control_Read_Property,
|
||||
Load_Control_Write_Property, Load_Control_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init,
|
||||
Multistate_Output_Count,
|
||||
Multistate_Output_Index_To_Instance,
|
||||
Multistate_Output_Valid_Instance,
|
||||
Multistate_Output_Object_Name, Multistate_Output_Read_Property,
|
||||
Multistate_Output_Write_Property, Multistate_Output_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init,
|
||||
Multistate_Input_Count,
|
||||
Multistate_Input_Index_To_Instance,
|
||||
Multistate_Input_Valid_Instance,
|
||||
Multistate_Input_Object_Name, Multistate_Input_Read_Property,
|
||||
Multistate_Input_Write_Property, Multistate_Input_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count,
|
||||
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance,
|
||||
Trend_Log_Object_Name, Trend_Log_Read_Property,
|
||||
Trend_Log_Write_Property, Trend_Log_Property_Lists,
|
||||
TrendLogGetRRInfo, NULL, NULL, NULL}, {
|
||||
{OBJECT_LIFE_SAFETY_POINT,
|
||||
Life_Safety_Point_Init,
|
||||
Life_Safety_Point_Count,
|
||||
Life_Safety_Point_Index_To_Instance,
|
||||
Life_Safety_Point_Valid_Instance,
|
||||
Life_Safety_Point_Object_Name,
|
||||
Life_Safety_Point_Read_Property,
|
||||
Life_Safety_Point_Write_Property,
|
||||
Life_Safety_Point_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_LOAD_CONTROL,
|
||||
Load_Control_Init,
|
||||
Load_Control_Count,
|
||||
Load_Control_Index_To_Instance,
|
||||
Load_Control_Valid_Instance,
|
||||
Load_Control_Object_Name,
|
||||
Load_Control_Read_Property,
|
||||
Load_Control_Write_Property,
|
||||
Load_Control_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_MULTI_STATE_OUTPUT,
|
||||
Multistate_Output_Init,
|
||||
Multistate_Output_Count,
|
||||
Multistate_Output_Index_To_Instance,
|
||||
Multistate_Output_Valid_Instance,
|
||||
Multistate_Output_Object_Name,
|
||||
Multistate_Output_Read_Property,
|
||||
Multistate_Output_Write_Property,
|
||||
Multistate_Output_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_MULTI_STATE_INPUT,
|
||||
Multistate_Input_Init,
|
||||
Multistate_Input_Count,
|
||||
Multistate_Input_Index_To_Instance,
|
||||
Multistate_Input_Valid_Instance,
|
||||
Multistate_Input_Object_Name,
|
||||
Multistate_Input_Read_Property,
|
||||
Multistate_Input_Write_Property,
|
||||
Multistate_Input_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
{OBJECT_TRENDLOG,
|
||||
Trend_Log_Init,
|
||||
Trend_Log_Count,
|
||||
Trend_Log_Index_To_Instance,
|
||||
Trend_Log_Valid_Instance,
|
||||
Trend_Log_Object_Name,
|
||||
Trend_Log_Read_Property,
|
||||
Trend_Log_Write_Property,
|
||||
Trend_Log_Property_Lists,
|
||||
TrendLogGetRRInfo,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
#if defined(BACFILE)
|
||||
OBJECT_FILE, bacfile_init, bacfile_count,
|
||||
bacfile_index_to_instance, bacfile_valid_instance,
|
||||
bacfile_object_name, bacfile_read_property,
|
||||
bacfile_write_property, BACfile_Property_Lists,
|
||||
NULL, NULL, NULL, NULL}, {
|
||||
{OBJECT_FILE,
|
||||
bacfile_init,
|
||||
bacfile_count,
|
||||
bacfile_index_to_instance,
|
||||
bacfile_valid_instance,
|
||||
bacfile_object_name,
|
||||
bacfile_read_property,
|
||||
bacfile_write_property,
|
||||
BACfile_Property_Lists,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */},
|
||||
#endif
|
||||
MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL}
|
||||
{MAX_BACNET_OBJECT_TYPE,
|
||||
NULL /* Init */,
|
||||
NULL /* Count */,
|
||||
NULL /* Index_To_Instance */,
|
||||
NULL /* Valid_Instance */,
|
||||
NULL /* Object_Name */,
|
||||
NULL /* Read_Property */,
|
||||
NULL /* Write_Property */,
|
||||
NULL /* Property_Lists */,
|
||||
NULL /* ReadRangeInfo */,
|
||||
NULL /* Iterator */,
|
||||
NULL /* Value_Lists */,
|
||||
NULL /* COV */,
|
||||
NULL /* COV Clear */,
|
||||
NULL /* Intrinsic Reporting */}
|
||||
};
|
||||
|
||||
|
||||
/** Glue function to let the Device object, when called by a handler,
|
||||
* lookup which Object type needs to be invoked.
|
||||
* @ingroup ObjHelpers
|
||||
@@ -176,13 +298,12 @@ static struct object_functions *Device_Objects_Find_Functions(
|
||||
{
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
pObject = &Object_Table[0];
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
/* handle each object type */
|
||||
if (pObject->Object_Type == Object_Type) {
|
||||
return (pObject);
|
||||
}
|
||||
|
||||
pObject++;
|
||||
}
|
||||
|
||||
@@ -341,16 +462,16 @@ static const int Device_Properties_Required[] = {
|
||||
PROP_SEGMENTATION_SUPPORTED,
|
||||
PROP_APDU_TIMEOUT,
|
||||
PROP_NUMBER_OF_APDU_RETRIES,
|
||||
#if defined(BACDL_MSTP)
|
||||
PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES,
|
||||
#endif
|
||||
PROP_DEVICE_ADDRESS_BINDING,
|
||||
PROP_DATABASE_REVISION,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int Device_Properties_Optional[] = {
|
||||
#if defined(BACDL_MSTP)
|
||||
PROP_MAX_MASTER,
|
||||
PROP_MAX_INFO_FRAMES,
|
||||
#endif
|
||||
PROP_DESCRIPTION,
|
||||
PROP_LOCAL_TIME,
|
||||
PROP_UTC_OFFSET,
|
||||
@@ -744,7 +865,7 @@ unsigned Device_Object_List_Count(
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
/* initialize the default return values */
|
||||
pObject = &Object_Table[0];
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Count) {
|
||||
count += pObject->Object_Count();
|
||||
@@ -782,7 +903,7 @@ bool Device_Object_List_Identifier(
|
||||
}
|
||||
object_index = array_index - 1;
|
||||
/* initialize the default return values */
|
||||
pObject = &Object_Table[0];
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Count) {
|
||||
object_index -= count;
|
||||
@@ -887,7 +1008,7 @@ bool Device_Valid_Object_Id(
|
||||
* @return True on success or else False if not found.
|
||||
*/
|
||||
bool Device_Object_Name_Copy(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_CHARACTER_STRING * object_name)
|
||||
{
|
||||
@@ -1087,7 +1208,7 @@ int Device_Read_Property_Local(
|
||||
}
|
||||
/* set the object types with objects to supported */
|
||||
|
||||
pObject = &Object_Table[0];
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if ((pObject->Object_Count) && (pObject->Object_Count() > 0)) {
|
||||
bitstring_set_bit(&bit_string, pObject->Object_Type, true);
|
||||
@@ -1206,7 +1327,7 @@ int Device_Read_Property_Local(
|
||||
* If the Object or Property can't be found, sets the error class and code.
|
||||
*
|
||||
* @param rpdata [in,out] Structure with the desired Object and Property info
|
||||
* on entry, and APDU message on return.
|
||||
* on entry, and APDU message on return.
|
||||
* @return The length of the APDU on success, else BACNET_STATUS_ERROR
|
||||
*/
|
||||
int Device_Read_Property(
|
||||
@@ -1483,6 +1604,43 @@ bool Device_Encode_Value_List(
|
||||
return (status);
|
||||
}
|
||||
|
||||
bool Device_COV(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance)
|
||||
{
|
||||
bool status = false; /* Ever the pessamist! */
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
pObject = Device_Objects_Find_Functions(object_type);
|
||||
if (pObject != NULL) {
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(object_instance)) {
|
||||
if (pObject->Object_COV) {
|
||||
status = pObject->Object_COV(
|
||||
object_instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
void Device_COV_Clear(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance)
|
||||
{
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
pObject = Device_Objects_Find_Functions(object_type);
|
||||
if (pObject != NULL) {
|
||||
if (pObject->Object_Valid_Instance &&
|
||||
pObject->Object_Valid_Instance(object_instance)) {
|
||||
if (pObject->Object_COV_Clear) {
|
||||
pObject->Object_COV_Clear(object_instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
void Device_local_reporting(
|
||||
@@ -1548,10 +1706,12 @@ void Device_Init(
|
||||
struct object_functions *pObject = NULL;
|
||||
|
||||
characterstring_init_ansi(&My_Object_Name, "SimpleServer");
|
||||
/* we don't use the object table passed in
|
||||
since there is extra stuff we don't need in there. */
|
||||
(void) object_table;
|
||||
pObject = &Object_Table[0];
|
||||
if (object_table) {
|
||||
Object_Table = object_table;
|
||||
} else {
|
||||
Object_Table = &My_Object_Table[0];
|
||||
}
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Init) {
|
||||
pObject->Object_Init();
|
||||
@@ -1625,7 +1785,7 @@ void Routing_Device_Init(
|
||||
Add_Routed_Device(first_object_instance, &My_Object_Name, Description);
|
||||
|
||||
/* Now substitute our routed versions of the main object functions. */
|
||||
pDevObject = &Object_Table[0];
|
||||
pDevObject = Object_Table;
|
||||
pDevObject->Object_Index_To_Instance = Routed_Device_Index_To_Instance;
|
||||
pDevObject->Object_Valid_Instance =
|
||||
Routed_Device_Valid_Object_Instance_Number;
|
||||
|
||||
@@ -70,7 +70,7 @@ typedef uint32_t(
|
||||
* @param object_name [in,out] Pointer to a character_string structure that
|
||||
* will hold a copy of the object name if this is a valid object_instance.
|
||||
* @return True if the object_instance is valid and object_name has been
|
||||
* filled with a copy of the Object's name.
|
||||
* filled with a copy of the Object's name.
|
||||
*/
|
||||
typedef bool(
|
||||
*object_name_function)
|
||||
@@ -113,6 +113,23 @@ typedef bool(
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_VALUE * value_list);
|
||||
|
||||
/** Look in the table of objects for this instance to see if value changed.
|
||||
* @ingroup ObjHelpers
|
||||
* @param [in] The object instance number to be looked up.
|
||||
* @return True if the object instance has changed.
|
||||
*/
|
||||
typedef bool(
|
||||
*object_cov_function) (
|
||||
uint32_t object_instance);
|
||||
|
||||
/** Look in the table of objects for this instance to clear the changed flag.
|
||||
* @ingroup ObjHelpers
|
||||
* @param [in] The object instance number to be looked up.
|
||||
*/
|
||||
typedef void(
|
||||
*object_cov_clear_function) (
|
||||
uint32_t object_instance);
|
||||
|
||||
/** Intrinsic Reporting funcionality.
|
||||
* @ingroup ObjHelpers
|
||||
* @param [in] Object instance.
|
||||
@@ -127,7 +144,7 @@ typedef void (
|
||||
* Each Object must provide some implementation of each of these helpers
|
||||
* in order to properly support the handlers. Eg, the ReadProperty handler
|
||||
* handler_read_property() relies on the instance of Object_Read_Property
|
||||
* for each Object type.
|
||||
* for each Object type, or configure the function as NULL.
|
||||
* In both appearance and operation, this group of functions acts like
|
||||
* they are member functions of a C++ Object base class.
|
||||
*/
|
||||
@@ -144,6 +161,8 @@ typedef struct object_functions {
|
||||
rr_info_function Object_RR_Info;
|
||||
object_iterate_function Object_Iterator;
|
||||
object_value_list_function Object_Value_List;
|
||||
object_cov_function Object_COV;
|
||||
object_cov_clear_function Object_COV_Clear;
|
||||
object_intrinsic_reporting_function Object_Intrinsic_Reporting;
|
||||
} object_functions_t;
|
||||
|
||||
@@ -224,13 +243,19 @@ extern "C" {
|
||||
void Device_Objects_Property_List(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
struct special_property_list_t *pPropertyList);
|
||||
|
||||
/* functions to support COV */
|
||||
bool Device_Encode_Value_List(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance,
|
||||
BACNET_PROPERTY_VALUE * value_list);
|
||||
bool Device_Value_List_Supported(
|
||||
BACNET_OBJECT_TYPE object_type);
|
||||
bool Device_COV(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance);
|
||||
void Device_COV_Clear(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
uint32_t object_instance);
|
||||
|
||||
uint32_t Device_Object_Instance_Number(
|
||||
void);
|
||||
@@ -401,11 +426,7 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define DEVICE_OBJ_FUNCTIONS \
|
||||
OBJECT_DEVICE, NULL, Device_Count, Device_Index_To_Instance, \
|
||||
Device_Valid_Object_Instance_Number, Device_Object_Name, \
|
||||
Device_Read_Property_Local, Device_Write_Property_Local, \
|
||||
Device_Property_Lists, DeviceGetRRInfo, NULL, NULL
|
||||
|
||||
/** @defgroup ObjFrmwk Object Framework
|
||||
* The modules in this section describe the BACnet-stack's framework for
|
||||
* BACnet-defined Objects (Device, Analog Input, etc). There are two submodules
|
||||
@@ -415,11 +436,15 @@ extern "C" {
|
||||
* - The interface between the implemented Objects and the BAC-stack services,
|
||||
* specifically the handlers, which are mediated through function calls to
|
||||
* the Device object.
|
||||
*//** @defgroup ObjHelpers Object Helper Functions
|
||||
*/
|
||||
|
||||
/** @defgroup ObjHelpers Object Helper Functions
|
||||
* @ingroup ObjFrmwk
|
||||
* This section describes the function templates for the helper functions that
|
||||
* provide common object support.
|
||||
*//** @defgroup ObjIntf Handler-to-Object Interface Functions
|
||||
*/
|
||||
|
||||
/** @defgroup ObjIntf Handler-to-Object Interface Functions
|
||||
* @ingroup ObjFrmwk
|
||||
* This section describes the fairly limited set of functions that link the
|
||||
* BAC-stack handlers to the BACnet Object instances. All of these calls are
|
||||
|
||||
@@ -76,10 +76,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define LOAD_CONTROL_OBJ_FUNCTIONS \
|
||||
OBJECT_LOAD_CONTROL, Load_Control_Init, Load_Control_Count, \
|
||||
Load_Control_Index_To_Instance, Load_Control_Valid_Instance, \
|
||||
Load_Control_Object_Name, Load_Control_Read_Property, \
|
||||
Load_Control_Write_Property, Load_Control_Property_Lists, NULL, \
|
||||
NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,11 +69,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define LIFE_SAFETY_POINT_OBJ_FUNCTIONS \
|
||||
OBJECT_LIFE_SAFETY_POINT, Life_Safety_Point_Init, \
|
||||
Life_Safety_Point_Count, Life_Safety_Point_Index_To_Instance, \
|
||||
Life_Safety_Point_Valid_Instance, Life_Safety_Point_Object_Name, \
|
||||
Life_Safety_Point_Read_Property, \
|
||||
Life_Safety_Point_Write_Property, \
|
||||
Life_Safety_Point_Property_Lists, NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -96,11 +96,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define MULTI_STATE_INPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_MULTI_STATE_INPUT, Multistate_Input_Init, \
|
||||
Multistate_Input_Count, Multistate_Input_Index_To_Instance, \
|
||||
Multistate_Input_Valid_Instance, Multistate_Input_Object_Name, \
|
||||
Multistate_Input_Read_Property, \
|
||||
Multistate_Input_Write_Property, \
|
||||
Multistate_Input_Property_Lists, NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -71,11 +71,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define MULTI_STATE_OUTPUT_OBJ_FUNCTIONS \
|
||||
OBJECT_MULTI_STATE_OUTPUT, Multistate_Output_Init, \
|
||||
Multistate_Output_Count, Multistate_Output_Index_To_Instance, \
|
||||
Multistate_Output_Valid_Instance, Multistate_Output_Object_Name, \
|
||||
Multistate_Output_Read_Property, \
|
||||
Multistate_Output_Write_Property, \
|
||||
Multistate_Output_Property_Lists, NULL, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -138,10 +138,5 @@ BACnetRecipient ::= CHOICE {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define NOTIFICATION_CLASS_OBJ_FUNCTIONS \
|
||||
OBJECT_NOTIFICATION_CLASS, Notification_Class_Init, Notification_Class_Count, \
|
||||
Notification_Class_Index_To_Instance, Notification_Class_Valid_Instance, \
|
||||
Notification_Class_Object_Name, Notification_Class_Read_Property, \
|
||||
Notification_Class_Write_Property, Notification_Class_Property_Lists, \
|
||||
NULL, NULL, NULL
|
||||
|
||||
#endif /* NC_H */
|
||||
|
||||
@@ -197,10 +197,5 @@ extern "C" {
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#define TRENDLOG_OBJ_FUNCTIONS \
|
||||
OBJECT_TRENDLOG, Trend_Log_Init, Trend_Log_Count, \
|
||||
Trend_Log_Index_To_Instance, Trend_Log_Valid_Instance, \
|
||||
Trend_Log_Object_Name, Trend_Log_Read_Property, \
|
||||
Trend_Log_Write_Property, Trend_Log_Property_Lists, \
|
||||
TrendLogGetRRInfo, NULL, NULL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,37 +1,44 @@
|
||||
#Makefile to build BACnet Application for the Linux Port
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
|
||||
TARGET = ptransfer
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -f core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET} $(TARGET).map
|
||||
|
||||
include: .depend
|
||||
#Makefile to build BACnet Application using GCC compiler
|
||||
|
||||
# tools - only if you need them.
|
||||
# Most platforms have this already defined
|
||||
# CC = gcc
|
||||
# AR = ar
|
||||
# MAKE = make
|
||||
# SIZE = size
|
||||
#
|
||||
# Assumes rm and cp are available
|
||||
|
||||
# Executable file name
|
||||
TARGET = ptransfer
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
all: ${BACNET_LIB_TARGET} Makefile ${TARGET_BIN}
|
||||
|
||||
${TARGET_BIN}: ${OBJS} Makefile ${BACNET_LIB_TARGET}
|
||||
${CC} ${PFLAGS} ${OBJS} ${LFLAGS} -o $@
|
||||
size $@
|
||||
cp $@ ../../bin
|
||||
|
||||
lib: ${BACNET_LIB_TARGET}
|
||||
|
||||
${BACNET_LIB_TARGET}:
|
||||
( cd ${BACNET_LIB_DIR} ; $(MAKE) clean ; $(MAKE) )
|
||||
|
||||
.c.o:
|
||||
${CC} -c ${CFLAGS} $*.c -o $@
|
||||
|
||||
depend:
|
||||
rm -f .depend
|
||||
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||
|
||||
clean:
|
||||
rm -rf core ${TARGET_BIN} ${OBJS} ${BACNET_LIB_TARGET}
|
||||
|
||||
include: .depend
|
||||
|
||||
@@ -68,13 +68,6 @@ uint8_t Send_Private_Transfer_Request(
|
||||
char block_number,
|
||||
DATABLOCK * block);
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -132,7 +125,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ TARGET = bacarf
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -50,13 +50,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -186,7 +179,7 @@ static void LocalIAmHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ TARGET = bacrp
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -53,13 +53,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -150,7 +143,7 @@ void My_Read_Property_Ack_Handler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacrpm
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -54,13 +54,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -195,7 +188,7 @@ void My_Read_Property_Multiple_Ack_Handler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -80,13 +80,6 @@
|
||||
#define _stricmp stricmp
|
||||
#endif
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -144,7 +137,7 @@ void MyRejectHandler(
|
||||
static void Init_Objects(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
}
|
||||
|
||||
static void Init_Service_Handlers(
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacrd
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -51,13 +51,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -121,7 +114,7 @@ void MyReinitializeDeviceSimpleAckHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ TARGET = bacscov
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -54,13 +54,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -121,7 +114,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -45,7 +45,8 @@ BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
|
||||
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -118,6 +118,9 @@ static void Init_Service_Handlers(
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
/* handle the data coming back from private requests */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
|
||||
handler_unconfirmed_private_transfer);
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM,
|
||||
handler_alarm_ack);
|
||||
@@ -202,15 +205,16 @@ int main(
|
||||
dlenv_maintenance_timer(elapsed_seconds);
|
||||
Load_Control_State_Machine_Handler();
|
||||
elapsed_milliseconds = elapsed_seconds * 1000;
|
||||
if (dcc_communication_enabled()) {
|
||||
handler_cov_task(elapsed_seconds);
|
||||
}
|
||||
handler_cov_timer_seconds(elapsed_seconds);
|
||||
tsm_timer_milliseconds(elapsed_milliseconds);
|
||||
trend_log_timer(elapsed_seconds);
|
||||
#if defined(INTRINSIC_REPORTING)
|
||||
Device_local_reporting();
|
||||
#endif
|
||||
}
|
||||
if (dcc_communication_enabled()) {
|
||||
handler_cov_task();
|
||||
}
|
||||
/* scan cache address */
|
||||
address_binding_tmr += elapsed_seconds;
|
||||
if (address_binding_tmr >= 60) {
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacts
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -46,13 +46,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -93,7 +86,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacucov
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -50,17 +50,10 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -14,7 +14,8 @@ TARGET = bacupt
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -54,13 +54,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -124,74 +117,10 @@ void MyRejectHandler(
|
||||
}
|
||||
}
|
||||
|
||||
void MyUnconfirmedPrivateTransferHandler(
|
||||
uint8_t * service_request,
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src)
|
||||
{
|
||||
BACNET_PRIVATE_TRANSFER_DATA private_data;
|
||||
BACNET_OBJECT_PROPERTY_VALUE object_value; /* for bacapp printing */
|
||||
BACNET_APPLICATION_DATA_VALUE value; /* for decode value data */
|
||||
int len = 0;
|
||||
uint8_t *application_data;
|
||||
int application_data_len;
|
||||
bool first_value = true;
|
||||
bool print_brace = false;
|
||||
|
||||
len = ptransfer_decode_service_request(
|
||||
service_request, service_len, &private_data);
|
||||
if (len >= 0) {
|
||||
printf("PrivateTransfer:vendorID=%u\r\n",
|
||||
(unsigned)private_data.vendorID);
|
||||
printf("PrivateTransfer:serviceNumber=%lu\r\n",
|
||||
(unsigned long)private_data.serviceNumber);
|
||||
application_data = private_data.serviceParameters;
|
||||
application_data_len = private_data.serviceParametersLen;
|
||||
for (;;) {
|
||||
len =
|
||||
bacapp_decode_application_data(application_data,
|
||||
(uint8_t) application_data_len, &value);
|
||||
if (first_value && (len < application_data_len)) {
|
||||
first_value = false;
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stdout, "{");
|
||||
#endif
|
||||
print_brace = true;
|
||||
}
|
||||
/* private transfer doesn't provide any clues */
|
||||
object_value.object_type = MAX_BACNET_OBJECT_TYPE;
|
||||
object_value.object_instance = BACNET_MAX_INSTANCE;
|
||||
object_value.object_property = MAX_BACNET_PROPERTY_ID;
|
||||
object_value.array_index = BACNET_ARRAY_ALL;
|
||||
object_value.value = &value;
|
||||
bacapp_print_value(stdout, &object_value);
|
||||
if (len > 0) {
|
||||
if (len < application_data_len) {
|
||||
application_data += len;
|
||||
application_data_len -= len;
|
||||
/* there's more! */
|
||||
#if PRINT_ENABLED
|
||||
fprintf(stdout, ",");
|
||||
#endif
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if PRINT_ENABLED
|
||||
if (print_brace)
|
||||
fprintf(stdout, "}");
|
||||
fprintf(stdout, "\r\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
@@ -204,9 +133,9 @@ static void Init_Service_Handlers(
|
||||
/* we must implement read property - it's required! */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||
handler_read_property);
|
||||
/* handle the data coming back from confirmed requests */
|
||||
/* handle the data coming back from requests */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
|
||||
MyUnconfirmedPrivateTransferHandler);
|
||||
handler_unconfirmed_private_transfer);
|
||||
/* handle any errors coming back */
|
||||
apdu_set_error_handler(SERVICE_CONFIRMED_READ_PROPERTY, MyErrorHandler);
|
||||
apdu_set_abort_handler(MyAbortHandler);
|
||||
|
||||
@@ -45,7 +45,8 @@ BUILD_DEFINE = -DMAX_PROPERTY_VALUES=64
|
||||
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(BUILD_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacwh
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -50,13 +50,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -96,7 +89,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ TARGET = bacwi
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -50,13 +50,6 @@
|
||||
#endif
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -97,7 +90,7 @@ void MyRejectHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* Note: this applications doesn't need to handle who-is
|
||||
it is confusing for the user! */
|
||||
/* set the handler for all the services we don't implement
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ TARGET = bacwir
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -51,12 +51,6 @@
|
||||
#endif
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -175,7 +169,7 @@ void My_NPDU_Handler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -42,7 +42,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacawf
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -50,13 +50,6 @@
|
||||
#include "txbuf.h"
|
||||
#include "dlenv.h"
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -140,7 +133,7 @@ static void LocalIAmHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -41,7 +41,8 @@ BACNET_DEFINES = -DPRINT_ENABLED=1 -DBACAPP_ALL
|
||||
BACDL_DEFINE=-DBACDL_BIP=1 -DUSE_INADDR=1
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -9,7 +9,8 @@ TARGET = bacwp
|
||||
|
||||
TARGET_BIN = ${TARGET}$(TARGET_EXT)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
../object/device-client.c
|
||||
|
||||
OBJS = ${SRCS:.c=.o}
|
||||
|
||||
|
||||
@@ -56,13 +56,6 @@
|
||||
#define MAX_PROPERTY_VALUES 64
|
||||
#endif
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -141,7 +134,7 @@ void MyWritePropertySimpleAckHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Init(&Object_Table[0]);
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is
|
||||
to support dynamic device binding to us */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
@@ -45,7 +45,8 @@ WRITEPROPS_DEFINE = -DMAX_PROPERTY_VALUES=64
|
||||
|
||||
DEFINES = $(BACNET_DEFINES) $(BACDL_DEFINE) $(WRITEPROPS_DEFINE)
|
||||
|
||||
SRCS = main.c
|
||||
SRCS = main.c \
|
||||
$(BACNET_OBJECT)\device-client.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
|
||||
@@ -215,7 +215,8 @@ extern "C" {
|
||||
uint16_t service_len,
|
||||
BACNET_ADDRESS * src,
|
||||
BACNET_CONFIRMED_SERVICE_DATA * service_data);
|
||||
void handler_cov_task(
|
||||
void handler_cov_task(void);
|
||||
void handler_cov_timer_seconds(
|
||||
uint32_t elapsed_seconds);
|
||||
void handler_cov_init(
|
||||
void);
|
||||
|
||||
@@ -59,26 +59,6 @@
|
||||
#include "bacfile.h"
|
||||
#endif
|
||||
|
||||
/* All included BACnet objects */
|
||||
static object_functions_t Object_Table[] = {
|
||||
{DEVICE_OBJ_FUNCTIONS},
|
||||
{ANALOG_INPUT_OBJ_FUNCTIONS},
|
||||
{ANALOG_OUTPUT_OBJ_FUNCTIONS},
|
||||
{ANALOG_VALUE_OBJ_FUNCTIONS},
|
||||
{BINARY_INPUT_OBJ_FUNCTIONS},
|
||||
{BINARY_OUTPUT_OBJ_FUNCTIONS},
|
||||
{BINARY_VALUE_OBJ_FUNCTIONS},
|
||||
{LIFE_SAFETY_POINT_OBJ_FUNCTIONS},
|
||||
{LOAD_CONTROL_OBJ_FUNCTIONS},
|
||||
{MULTI_STATE_OUTPUT_OBJ_FUNCTIONS},
|
||||
{MULTI_STATE_INPUT_OBJ_FUNCTIONS},
|
||||
{TRENDLOG_OBJ_FUNCTIONS},
|
||||
#if defined(BACFILE)
|
||||
{FILE_OBJ_FUNCTIONS},
|
||||
#endif
|
||||
{MAX_BACNET_OBJECT_TYPE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/* buffer used for receive */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
@@ -189,8 +169,7 @@ static void LocalIAmHandler(
|
||||
static void Init_Service_Handlers(
|
||||
void)
|
||||
{
|
||||
Device_Initialize_Object_Functions(&Object_Table[0]);
|
||||
Device_Init();
|
||||
Device_Init(NULL);
|
||||
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
|
||||
Reference in New Issue
Block a user