Added ability of the SubscribeCOV demo to subscribe to multiple objects in the device.

This commit is contained in:
skarg
2011-11-22 22:47:22 +00:00
parent d3d2e9d030
commit abc8135eff
2 changed files with 96 additions and 43 deletions
+87 -36
View File
@@ -65,8 +65,12 @@ static uint32_t Target_Device_Process_Identifier = 0;
static uint8_t Service_Parameters[MAX_APDU];
/* the invoke id is needed to filter incoming messages */
static uint8_t Request_Invoke_ID = 0;
/* MAC and SNET address of target */
static BACNET_ADDRESS Target_Address;
/* indication of error, reject, or abort */
static bool Error_Detected = false;
/* data used in COV subscription request */
BACNET_SUBSCRIBE_COV_DATA *COV_Subscribe_Data = NULL;
static void MyErrorHandler(
BACNET_ADDRESS * src,
@@ -138,6 +142,20 @@ static void Init_Service_Handlers(
apdu_set_reject_handler(MyRejectHandler);
}
void cleanup(
void)
{
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
BACNET_SUBSCRIBE_COV_DATA *cov_data_old = NULL;
cov_data = COV_Subscribe_Data;
while (cov_data) {
cov_data_old = cov_data;
cov_data = cov_data->next;
free(cov_data_old);
}
}
int main(
int argc,
char *argv[])
@@ -155,11 +173,13 @@ int main(
time_t delta_seconds = 0;
bool found = false;
char *filename = NULL;
BACNET_SUBSCRIBE_COV_DATA cov_data = {0};
bool print_usage_terse = false;
bool print_usage_verbose = false;
BACNET_SUBSCRIBE_COV_DATA *cov_data = NULL;
int argi = 0;
int arg_remaining = 0;
if (argc < 5) {
if (argc < 6) {
print_usage_terse = true;
}
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
@@ -219,40 +239,61 @@ int main(
}
/* decode the command line parameters */
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
cov_data.monitoredObjectIdentifier.type = strtol(argv[2], NULL, 0);
cov_data.monitoredObjectIdentifier.instance = strtol(argv[3], NULL, 0);
cov_data.subscriberProcessIdentifier =
Target_Device_Process_Identifier = strtol(argv[4], NULL, 0);
if (strcmp(argv[5],"cancel") == 0) {
cov_data.cancellationRequest = true;
} else {
cov_data.cancellationRequest = false;
if (strcmp(argv[5],"confirmed") == 0) {
cov_data.issueConfirmedNotifications = true;
} else if (strcmp(argv[5],"unconfirmed") == 0) {
cov_data.issueConfirmedNotifications = false;
} else {
fprintf(stderr, "unknown option: %s\r\n",
argv[5]);
return 1;
}
cov_data.lifetime = strtol(argv[6], NULL, 0);
}
if (Target_Device_Object_Instance >= BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE);
return 1;
}
if (cov_data.monitoredObjectIdentifier.type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
cov_data.monitoredObjectIdentifier.type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
if (cov_data.monitoredObjectIdentifier.instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
cov_data.monitoredObjectIdentifier.instance,
BACNET_MAX_INSTANCE + 1);
return 1;
atexit(cleanup);
COV_Subscribe_Data = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = COV_Subscribe_Data;
argi = 2;
while (cov_data) {
cov_data->monitoredObjectIdentifier.type =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.type >= MAX_BACNET_OBJECT_TYPE) {
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.type, MAX_BACNET_OBJECT_TYPE);
return 1;
}
argi++;
cov_data->monitoredObjectIdentifier.instance =
strtol(argv[argi], NULL, 0);
if (cov_data->monitoredObjectIdentifier.instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
cov_data->monitoredObjectIdentifier.instance,
BACNET_MAX_INSTANCE + 1);
return 1;
}
argi++;
cov_data->subscriberProcessIdentifier =
strtol(argv[argi], NULL, 0);
argi++;
if (strcmp(argv[argi],"cancel") == 0) {
cov_data->cancellationRequest = true;
argi++;
} else {
cov_data->cancellationRequest = false;
if (strcmp(argv[argi],"confirmed") == 0) {
cov_data->issueConfirmedNotifications = true;
} else if (strcmp(argv[argi],"unconfirmed") == 0) {
cov_data->issueConfirmedNotifications = false;
} else {
fprintf(stderr, "unknown option: %s\r\n",
argv[argi]);
return 1;
}
argi++;
cov_data->lifetime = strtol(argv[argi], NULL, 0);
argi++;
}
arg_remaining = argc - argi;
if (arg_remaining < 5) {
break;
} else {
cov_data->next = calloc(1, sizeof(BACNET_SUBSCRIBE_COV_DATA));
cov_data = cov_data->next;
}
}
/* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
@@ -262,9 +303,10 @@ int main(
/* configure the timeout values */
last_seconds = time(NULL);
timeout_seconds = (apdu_timeout() / 1000) * apdu_retries();
if (!cov_data.cancellationRequest &&
(timeout_seconds < cov_data.lifetime)) {
timeout_seconds = cov_data.lifetime;
if (!COV_Subscribe_Data->cancellationRequest &&
(timeout_seconds < COV_Subscribe_Data->lifetime)) {
/* only use the first subscribe value */
timeout_seconds = COV_Subscribe_Data->lifetime;
}
/* try to bind with the device */
found =
@@ -274,6 +316,8 @@ int main(
Send_WhoIs(Target_Device_Object_Instance,
Target_Device_Object_Instance);
}
/* start at the beginning of the subscribe list */
cov_data = COV_Subscribe_Data;
/* loop forever */
for (;;) {
/* increment timer - exit if timed out */
@@ -297,13 +341,20 @@ int main(
}
if (found) {
if (Request_Invoke_ID == 0) {
Target_Device_Process_Identifier =
cov_data->subscriberProcessIdentifier;
Request_Invoke_ID = Send_COV_Subscribe(
Target_Device_Object_Instance,
&cov_data);
cov_data);
printf("Sent SubscribeCOV request. Waiting %u seconds.\r\n",
(unsigned)(timeout_seconds - elapsed_seconds));
} else if (tsm_invoke_id_free(Request_Invoke_ID)) {
/* do nothing - wait for lifetime value to expire */
if (cov_data->next) {
cov_data = cov_data->next;
Request_Invoke_ID = 0;
} else {
/* do nothing - wait for lifetime value to expire */
}
} else if (tsm_invoke_id_failed(Request_Invoke_ID)) {
fprintf(stderr, "\rError: TSM Timeout!\r\n");
tsm_free_invoke_id(Request_Invoke_ID);
+9 -7
View File
@@ -47,6 +47,7 @@ typedef struct BACnet_COV_Data {
BACNET_PROPERTY_VALUE *listOfValues;
} BACNET_COV_DATA;
struct BACnet_Subscribe_COV_Data;
typedef struct BACnet_Subscribe_COV_Data {
uint32_t subscriberProcessIdentifier;
BACNET_OBJECT_ID monitoredObjectIdentifier;
@@ -58,6 +59,7 @@ typedef struct BACnet_Subscribe_COV_Data {
float covIncrement; /* optional */
BACNET_ERROR_CLASS error_class;
BACNET_ERROR_CODE error_code;
struct BACnet_Subscribe_COV_Data *next;
} BACNET_SUBSCRIBE_COV_DATA;
#ifdef __cplusplus
@@ -131,14 +133,14 @@ extern "C" {
/** @defgroup DSCOV Data Sharing - Change of Value Service (DS-COV)
* @ingroup DataShare
* 13.1 Change of Value Reporting <br>
* Change of value (COV) reporting allows a COV-client to subscribe with a
* COV-server, on a permanent or temporary basis, to receive reports of some
* changes of value of some referenced property based on fixed criteria.
* If an object provides COV reporting, then changes of value of any
* Change of value (COV) reporting allows a COV-client to subscribe with a
* COV-server, on a permanent or temporary basis, to receive reports of some
* changes of value of some referenced property based on fixed criteria.
* If an object provides COV reporting, then changes of value of any
* subscribed-to properties of the object, in some cases based on programmable
* increments, trigger COV notifications to be sent to subscribing clients.
* Typically, COV notifications are sent to supervisory programs in COV-client
* devices or to operators or logging devices. Any object, proprietary or
* increments, trigger COV notifications to be sent to subscribing clients.
* Typically, COV notifications are sent to supervisory programs in COV-client
* devices or to operators or logging devices. Any object, proprietary or
* standard, may support COV reporting at the implementor's option.
*/
#endif