Correcting COV subscribe - almost working...
This commit is contained in:
@@ -61,6 +61,7 @@ typedef struct BACnet_COV_Subscription {
|
|||||||
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
||||||
bool issueConfirmedNotifications; /* optional */
|
bool issueConfirmedNotifications; /* optional */
|
||||||
uint32_t lifetime; /* optional */
|
uint32_t lifetime; /* optional */
|
||||||
|
bool send_requested;
|
||||||
} BACNET_COV_SUBSCRIPTION;
|
} BACNET_COV_SUBSCRIPTION;
|
||||||
|
|
||||||
#define MAX_COV_SUBCRIPTIONS 32
|
#define MAX_COV_SUBCRIPTIONS 32
|
||||||
@@ -80,18 +81,24 @@ void handler_cov_init(
|
|||||||
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
|
COV_Subscriptions[index].monitoredObjectIdentifier.instance = 0;
|
||||||
COV_Subscriptions[index].issueConfirmedNotifications = false;
|
COV_Subscriptions[index].issueConfirmedNotifications = false;
|
||||||
COV_Subscriptions[index].lifetime = 0;
|
COV_Subscriptions[index].lifetime = 0;
|
||||||
|
COV_Subscriptions[index].send_requested = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cov_list_subscribe(
|
static bool cov_list_subscribe(
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
BACNET_SUBSCRIBE_COV_DATA * cov_data)
|
BACNET_SUBSCRIBE_COV_DATA * cov_data,
|
||||||
|
BACNET_ERROR_CLASS * error_class,
|
||||||
|
BACNET_ERROR_CODE * error_code)
|
||||||
{
|
{
|
||||||
bool existing_entry = false;
|
bool existing_entry = false;
|
||||||
int index;
|
int index;
|
||||||
int first_invalid_index = -1;
|
int first_invalid_index = -1;
|
||||||
bool found = true;
|
bool found = true;
|
||||||
|
|
||||||
|
/* unable to subscribe - resources? */
|
||||||
|
/* unable to cancel subscription - other? */
|
||||||
|
|
||||||
/* existing? - match Object ID and Process ID */
|
/* existing? - match Object ID and Process ID */
|
||||||
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
for (index = 0; index < MAX_COV_SUBCRIPTIONS; index++) {
|
||||||
if ((COV_Subscriptions[index].valid) &&
|
if ((COV_Subscriptions[index].valid) &&
|
||||||
@@ -109,6 +116,7 @@ static bool cov_list_subscribe(
|
|||||||
COV_Subscriptions[index].issueConfirmedNotifications =
|
COV_Subscriptions[index].issueConfirmedNotifications =
|
||||||
cov_data->issueConfirmedNotifications;
|
cov_data->issueConfirmedNotifications;
|
||||||
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
||||||
|
COV_Subscriptions[index].send_requested = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@@ -132,7 +140,17 @@ static bool cov_list_subscribe(
|
|||||||
COV_Subscriptions[index].issueConfirmedNotifications =
|
COV_Subscriptions[index].issueConfirmedNotifications =
|
||||||
cov_data->issueConfirmedNotifications;
|
cov_data->issueConfirmedNotifications;
|
||||||
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
COV_Subscriptions[index].lifetime = cov_data->lifetime;
|
||||||
|
COV_Subscriptions[index].send_requested = true;
|
||||||
} else {
|
} else {
|
||||||
|
if (first_invalid_index < 0) {
|
||||||
|
/* Out of resources */
|
||||||
|
*error_class = ERROR_CLASS_RESOURCES;
|
||||||
|
*error_code = ERROR_CODE_OTHER;
|
||||||
|
} else {
|
||||||
|
/* Unable to cancel request of unsubscribed object */
|
||||||
|
*error_class = ERROR_CLASS_OBJECT;
|
||||||
|
*error_code = ERROR_CODE_OTHER;
|
||||||
|
}
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +170,9 @@ static bool cov_send_request(
|
|||||||
BACNET_COV_DATA cov_data;
|
BACNET_COV_DATA cov_data;
|
||||||
BACNET_PROPERTY_VALUE value_list[2];
|
BACNET_PROPERTY_VALUE value_list[2];
|
||||||
|
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stderr, "COVnotification: requested\n");
|
||||||
|
#endif
|
||||||
datalink_get_my_address(&my_address);
|
datalink_get_my_address(&my_address);
|
||||||
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
npdu_encode_npdu_data(&npdu_data, false, MESSAGE_PRIORITY_NORMAL);
|
||||||
pdu_len =
|
pdu_len =
|
||||||
@@ -172,6 +193,7 @@ static bool cov_send_request(
|
|||||||
cov_data.timeRemaining =
|
cov_data.timeRemaining =
|
||||||
cov_subscription->lifetime;
|
cov_subscription->lifetime;
|
||||||
/* encode the value list */
|
/* encode the value list */
|
||||||
|
cov_data.listOfValues = &value_list[0];
|
||||||
value_list[0].next = &value_list[1];
|
value_list[0].next = &value_list[1];
|
||||||
value_list[1].next = NULL;
|
value_list[1].next = NULL;
|
||||||
switch (cov_subscription->monitoredObjectIdentifier.type) {
|
switch (cov_subscription->monitoredObjectIdentifier.type) {
|
||||||
@@ -239,6 +261,11 @@ void handler_cov_task(
|
|||||||
lifetime_seconds = COV_Subscriptions[index].lifetime;
|
lifetime_seconds = COV_Subscriptions[index].lifetime;
|
||||||
if (lifetime_seconds >= elapsed_seconds) {
|
if (lifetime_seconds >= elapsed_seconds) {
|
||||||
COV_Subscriptions[index].lifetime -= elapsed_seconds;
|
COV_Subscriptions[index].lifetime -= elapsed_seconds;
|
||||||
|
#if PRINT_ENABLED
|
||||||
|
fprintf(stderr,"COVtask: subscription[%d].lifetime=%d\n",
|
||||||
|
index,
|
||||||
|
COV_Subscriptions[index].lifetime);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
COV_Subscriptions[index].lifetime = 0;
|
COV_Subscriptions[index].lifetime = 0;
|
||||||
}
|
}
|
||||||
@@ -253,16 +280,18 @@ void handler_cov_task(
|
|||||||
switch (object_id.type) {
|
switch (object_id.type) {
|
||||||
case OBJECT_BINARY_INPUT:
|
case OBJECT_BINARY_INPUT:
|
||||||
if (Binary_Input_Change_Of_Value(object_id.instance)) {
|
if (Binary_Input_Change_Of_Value(object_id.instance)) {
|
||||||
status = cov_send_request(&COV_Subscriptions[index]);
|
COV_Subscriptions[index].send_requested = true;
|
||||||
if (status) {
|
Binary_Input_Change_Of_Value_Clear(
|
||||||
Binary_Input_Change_Of_Value_Clear(
|
object_id.instance);
|
||||||
object_id.instance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (COV_Subscriptions[index].send_requested) {
|
||||||
|
status = cov_send_request(&COV_Subscriptions[index]);
|
||||||
|
COV_Subscriptions[index].send_requested = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -278,10 +307,12 @@ static bool cov_subscribe(
|
|||||||
switch (cov_data->monitoredObjectIdentifier.type) {
|
switch (cov_data->monitoredObjectIdentifier.type) {
|
||||||
case OBJECT_BINARY_INPUT:
|
case OBJECT_BINARY_INPUT:
|
||||||
status = true;
|
status = true;
|
||||||
status = cov_list_subscribe(src, cov_data);
|
status = cov_list_subscribe(src, cov_data,
|
||||||
|
error_class, error_code);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* FIXME: what is the ERROR? */
|
*error_class = ERROR_CLASS_OBJECT;
|
||||||
|
*error_code = ERROR_CODE_UNKNOWN_OBJECT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ int main(
|
|||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
elapsed_seconds = current_seconds - last_seconds;
|
elapsed_seconds = current_seconds - last_seconds;
|
||||||
if (elapsed_seconds) {
|
if (elapsed_seconds) {
|
||||||
|
last_seconds = current_seconds;
|
||||||
dcc_timer_seconds(elapsed_seconds);
|
dcc_timer_seconds(elapsed_seconds);
|
||||||
Load_Control_State_Machine_Handler();
|
Load_Control_State_Machine_Handler();
|
||||||
elapsed_milliseconds = elapsed_seconds * 1000;
|
elapsed_milliseconds = elapsed_seconds * 1000;
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ int main(
|
|||||||
char *value_string = NULL;
|
char *value_string = NULL;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
BACNET_COV_DATA cov_data;
|
BACNET_COV_DATA cov_data;
|
||||||
|
BACNET_PROPERTY_VALUE value_list;
|
||||||
uint8_t tag;
|
uint8_t tag;
|
||||||
|
|
||||||
if (argc < 7) {
|
if (argc < 7) {
|
||||||
@@ -134,19 +135,21 @@ int main(
|
|||||||
cov_data.monitoredObjectIdentifier.type = strtol(argv[3], NULL, 0);
|
cov_data.monitoredObjectIdentifier.type = strtol(argv[3], NULL, 0);
|
||||||
cov_data.monitoredObjectIdentifier.instance = strtol(argv[4], NULL, 0);
|
cov_data.monitoredObjectIdentifier.instance = strtol(argv[4], NULL, 0);
|
||||||
cov_data.timeRemaining = strtol(argv[5], NULL, 0);
|
cov_data.timeRemaining = strtol(argv[5], NULL, 0);
|
||||||
cov_data.listOfValues.propertyIdentifier = strtol(argv[6], NULL, 0);
|
cov_data.listOfValues = &value_list;
|
||||||
|
value_list.next = NULL;
|
||||||
|
value_list.propertyIdentifier = strtol(argv[6], NULL, 0);
|
||||||
tag = strtol(argv[7], NULL, 0);
|
tag = strtol(argv[7], NULL, 0);
|
||||||
value_string = argv[8];
|
value_string = argv[8];
|
||||||
/* optional priority */
|
/* optional priority */
|
||||||
if (argc > 9)
|
if (argc > 9)
|
||||||
cov_data.listOfValues.priority = strtol(argv[9], NULL, 0);
|
value_list.priority = strtol(argv[9], NULL, 0);
|
||||||
else
|
else
|
||||||
cov_data.listOfValues.priority = BACNET_NO_PRIORITY;
|
value_list.priority = BACNET_NO_PRIORITY;
|
||||||
/* optional index */
|
/* optional index */
|
||||||
if (argc > 10)
|
if (argc > 10)
|
||||||
cov_data.listOfValues.propertyArrayIndex = strtol(argv[10], NULL, 0);
|
value_list.propertyArrayIndex = strtol(argv[10], NULL, 0);
|
||||||
else
|
else
|
||||||
cov_data.listOfValues.propertyArrayIndex = BACNET_ARRAY_ALL;
|
value_list.propertyArrayIndex = BACNET_ARRAY_ALL;
|
||||||
|
|
||||||
if (cov_data.initiatingDeviceIdentifier >= BACNET_MAX_INSTANCE) {
|
if (cov_data.initiatingDeviceIdentifier >= BACNET_MAX_INSTANCE) {
|
||||||
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
||||||
@@ -165,9 +168,9 @@ int main(
|
|||||||
BACNET_MAX_INSTANCE + 1);
|
BACNET_MAX_INSTANCE + 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (cov_data.listOfValues.propertyIdentifier > MAX_BACNET_PROPERTY_ID) {
|
if (cov_data.listOfValues->propertyIdentifier > MAX_BACNET_PROPERTY_ID) {
|
||||||
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
||||||
cov_data.listOfValues.propertyIdentifier,
|
cov_data.listOfValues->propertyIdentifier,
|
||||||
MAX_BACNET_PROPERTY_ID + 1);
|
MAX_BACNET_PROPERTY_ID + 1);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -178,7 +181,7 @@ int main(
|
|||||||
}
|
}
|
||||||
status =
|
status =
|
||||||
bacapp_parse_application_data(tag, value_string,
|
bacapp_parse_application_data(tag, value_string,
|
||||||
&cov_data.listOfValues.value);
|
&cov_data.listOfValues->value);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
/* FIXME: show the expected entry format for the tag */
|
/* FIXME: show the expected entry format for the tag */
|
||||||
fprintf(stderr, "unable to parse the tag value\r\n");
|
fprintf(stderr, "unable to parse the tag value\r\n");
|
||||||
@@ -189,8 +192,6 @@ int main(
|
|||||||
Init_Service_Handlers();
|
Init_Service_Handlers();
|
||||||
if (!datalink_init(getenv("BACNET_IFACE")))
|
if (!datalink_init(getenv("BACNET_IFACE")))
|
||||||
return 1;
|
return 1;
|
||||||
/* only one value in our value list */
|
|
||||||
cov_data.listOfValues.next = NULL;
|
|
||||||
ucov_notify_send(&Handler_Transmit_Buffer[0], &cov_data);
|
ucov_notify_send(&Handler_Transmit_Buffer[0], &cov_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ typedef struct BACnet_COV_Data {
|
|||||||
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
BACNET_OBJECT_ID monitoredObjectIdentifier;
|
||||||
uint32_t timeRemaining; /* seconds */
|
uint32_t timeRemaining; /* seconds */
|
||||||
/* simple linked list of values */
|
/* simple linked list of values */
|
||||||
BACNET_PROPERTY_VALUE listOfValues;
|
BACNET_PROPERTY_VALUE *listOfValues;
|
||||||
} BACNET_COV_DATA;
|
} BACNET_COV_DATA;
|
||||||
|
|
||||||
typedef struct BACnet_Property_Reference {
|
typedef struct BACnet_Property_Reference {
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ static int notify_encode_adpu(
|
|||||||
/* FIXME: for small implementations, we might try a partial
|
/* FIXME: for small implementations, we might try a partial
|
||||||
approach like the rpm.c where the values are encoded with
|
approach like the rpm.c where the values are encoded with
|
||||||
a separate function */
|
a separate function */
|
||||||
value = &data->listOfValues;
|
value = data->listOfValues;
|
||||||
while (value != NULL) {
|
while (value != NULL) {
|
||||||
/* tag 0 - propertyIdentifier */
|
/* tag 0 - propertyIdentifier */
|
||||||
len =
|
len =
|
||||||
@@ -228,7 +228,7 @@ int cov_notify_decode_service_request(
|
|||||||
/* a tag number of 4 is not extended so only one octet */
|
/* a tag number of 4 is not extended so only one octet */
|
||||||
len++;
|
len++;
|
||||||
/* the first value includes a pointer to the next value, etc */
|
/* the first value includes a pointer to the next value, etc */
|
||||||
value = &data->listOfValues;
|
value = data->listOfValues;
|
||||||
while (value != NULL) {
|
while (value != NULL) {
|
||||||
/* tag 0 - propertyIdentifier */
|
/* tag 0 - propertyIdentifier */
|
||||||
if (decode_is_context_tag(&apdu[len], 0)) {
|
if (decode_is_context_tag(&apdu[len], 0)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user