Enhanced the COV Notify service by adding confirmed to the unconfirmed encoding and decoding.
This commit is contained in:
@@ -557,7 +557,7 @@ typedef enum {
|
|||||||
EVENT_CHANGE_OF_LIFE_SAFETY = 8,
|
EVENT_CHANGE_OF_LIFE_SAFETY = 8,
|
||||||
EVENT_EXTENDED = 9,
|
EVENT_EXTENDED = 9,
|
||||||
EVENT_BUFFER_READY = 10,
|
EVENT_BUFFER_READY = 10,
|
||||||
EVENT_UNSIGNED_RANGE = 11,
|
EVENT_UNSIGNED_RANGE = 11
|
||||||
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 64-65535 may be used by others subject to */
|
/* Enumerated values 64-65535 may be used by others subject to */
|
||||||
/* the procedures and constraints described in Clause 23. */
|
/* the procedures and constraints described in Clause 23. */
|
||||||
@@ -648,7 +648,7 @@ typedef enum {
|
|||||||
SILENCED_STATE_UNSILENCED = 0,
|
SILENCED_STATE_UNSILENCED = 0,
|
||||||
SILENCED_STATE_AUDIBLE_SILENCED = 1,
|
SILENCED_STATE_AUDIBLE_SILENCED = 1,
|
||||||
SILENCED_STATE_VISIBLE_SILENCED = 2,
|
SILENCED_STATE_VISIBLE_SILENCED = 2,
|
||||||
SILENCED_STATE_ALL_SILENCED = 3,
|
SILENCED_STATE_ALL_SILENCED = 3
|
||||||
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
|
||||||
/* Enumerated values 64-65535 may be used by others subject to */
|
/* Enumerated values 64-65535 may be used by others subject to */
|
||||||
/* procedures and constraints described in Clause 23. */
|
/* procedures and constraints described in Clause 23. */
|
||||||
|
|||||||
+149
-40
@@ -37,21 +37,25 @@
|
|||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "bacapp.h"
|
#include "bacapp.h"
|
||||||
#include "cov.h"
|
#include "cov.h"
|
||||||
|
#include "device.h"
|
||||||
#include "datalink.h"
|
#include "datalink.h"
|
||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
|
|
||||||
/* encode service */
|
/* encode service */
|
||||||
|
|
||||||
int cov_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data)
|
/* Change-Of-Value Services
|
||||||
|
COV Subscribe
|
||||||
|
COV Subscribe Property
|
||||||
|
COV Notification
|
||||||
|
Unconfirmed COV Notification
|
||||||
|
*/
|
||||||
|
static int notify_encode_adpu(uint8_t * apdu, BACNET_COV_DATA * data)
|
||||||
{
|
{
|
||||||
int len = 0; /* length of each encoding */
|
int len = 0; /* length of each encoding */
|
||||||
int apdu_len = 0; /* total length of the apdu, return value */
|
int apdu_len = 0; /* total length of the apdu, return value */
|
||||||
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
|
BACNET_PROPERTY_VALUE *value = NULL; /* value in list */
|
||||||
|
|
||||||
if (apdu && data) {
|
if (apdu) {
|
||||||
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
|
|
||||||
apdu[1] = SERVICE_UNCONFIRMED_COV_NOTIFICATION; /* service choice */
|
|
||||||
apdu_len = 2;
|
|
||||||
/* tag 0 - subscriberProcessIdentifier */
|
/* tag 0 - subscriberProcessIdentifier */
|
||||||
len = encode_context_unsigned(&apdu[apdu_len],
|
len = encode_context_unsigned(&apdu[apdu_len],
|
||||||
0, data->subscriberProcessIdentifier);
|
0, data->subscriberProcessIdentifier);
|
||||||
@@ -75,7 +79,7 @@ int cov_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data)
|
|||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
/* the first value includes a pointer to the next value, etc */
|
/* the first value includes a pointer to the next value, etc */
|
||||||
/* 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 added 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) {
|
||||||
@@ -115,8 +119,45 @@ int cov_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data)
|
|||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ccov_notify_encode_apdu(uint8_t * apdu,
|
||||||
|
uint8_t invoke_id, BACNET_COV_DATA * data)
|
||||||
|
{
|
||||||
|
int len = 0; /* length of each encoding */
|
||||||
|
int apdu_len = 0; /* total length of the apdu, return value */
|
||||||
|
uint16_t max_apdu = Device_Max_APDU_Length_Accepted();
|
||||||
|
|
||||||
|
if (apdu) {
|
||||||
|
apdu[0] = PDU_TYPE_CONFIRMED_SERVICE_REQUEST;
|
||||||
|
apdu[1] = encode_max_segs_max_apdu(0, max_apdu);
|
||||||
|
apdu[2] = invoke_id;
|
||||||
|
apdu[3] = SERVICE_CONFIRMED_COV_NOTIFICATION;
|
||||||
|
apdu_len = 4;
|
||||||
|
len = notify_encode_adpu(&apdu[apdu_len], data);
|
||||||
|
apdu_len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apdu_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ucov_notify_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data)
|
||||||
|
{
|
||||||
|
int len = 0; /* length of each encoding */
|
||||||
|
int apdu_len = 0; /* total length of the apdu, return value */
|
||||||
|
|
||||||
|
if (apdu && data) {
|
||||||
|
apdu[0] = PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST;
|
||||||
|
apdu[1] = SERVICE_UNCONFIRMED_COV_NOTIFICATION; /* service choice */
|
||||||
|
apdu_len = 2;
|
||||||
|
len = notify_encode_adpu(&apdu[apdu_len], data);
|
||||||
|
apdu_len += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apdu_len;
|
||||||
|
}
|
||||||
|
|
||||||
/* decode the service request only */
|
/* decode the service request only */
|
||||||
int cov_decode_service_request(uint8_t * apdu,
|
/* COV and Unconfirmed COV are the same */
|
||||||
|
int cov_notify_decode_service_request(uint8_t * apdu,
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data)
|
unsigned apdu_len, BACNET_COV_DATA * data)
|
||||||
{
|
{
|
||||||
int len = 0; /* return value */
|
int len = 0; /* return value */
|
||||||
@@ -233,27 +274,58 @@ int cov_decode_service_request(uint8_t * apdu,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cov_decode_apdu(uint8_t * apdu,
|
int ccov_notify_decode_apdu(uint8_t * apdu,
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data)
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_COV_DATA * data)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
unsigned offset = 0;
|
||||||
|
|
||||||
if (!apdu)
|
if (!apdu)
|
||||||
return -1;
|
return -1;
|
||||||
/* optional checking - most likely was already done prior to this call */
|
/* optional checking - most likely was already done prior to this call */
|
||||||
if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST)
|
if (apdu[0] != PDU_TYPE_CONFIRMED_SERVICE_REQUEST)
|
||||||
return -1;
|
return -2;
|
||||||
if (apdu[1] != SERVICE_UNCONFIRMED_COV_NOTIFICATION)
|
/* apdu[1] = encode_max_segs_max_apdu(0, Device_Max_APDU_Length_Accepted()); */
|
||||||
return -1;
|
*invoke_id = apdu[2]; /* invoke id - filled in by net layer */
|
||||||
|
if (apdu[3] != SERVICE_CONFIRMED_COV_NOTIFICATION)
|
||||||
|
return -3;
|
||||||
|
offset = 4;
|
||||||
|
|
||||||
/* optional limits - must be used as a pair */
|
/* optional limits - must be used as a pair */
|
||||||
if (apdu_len > 2) {
|
if (apdu_len > offset) {
|
||||||
len = cov_decode_service_request(&apdu[2], apdu_len - 2, data);
|
len = cov_notify_decode_service_request(
|
||||||
|
&apdu[offset], apdu_len - offset, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cov_send(uint8_t * buffer, BACNET_COV_DATA * data)
|
int ucov_notify_decode_apdu(uint8_t * apdu,
|
||||||
|
unsigned apdu_len, BACNET_COV_DATA * data)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
unsigned offset = 0;
|
||||||
|
|
||||||
|
if (!apdu)
|
||||||
|
return -1;
|
||||||
|
/* optional checking - most likely was already done prior to this call */
|
||||||
|
if (apdu[0] != PDU_TYPE_UNCONFIRMED_SERVICE_REQUEST)
|
||||||
|
return -2;
|
||||||
|
if (apdu[1] != SERVICE_UNCONFIRMED_COV_NOTIFICATION)
|
||||||
|
return -3;
|
||||||
|
/* optional limits - must be used as a pair */
|
||||||
|
offset = 2;
|
||||||
|
if (apdu_len > offset) {
|
||||||
|
len = cov_notify_decode_service_request(
|
||||||
|
&apdu[offset], apdu_len - offset, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ucov_notify_send(uint8_t * buffer, BACNET_COV_DATA * data)
|
||||||
{
|
{
|
||||||
int pdu_len = 0;
|
int pdu_len = 0;
|
||||||
BACNET_ADDRESS dest;
|
BACNET_ADDRESS dest;
|
||||||
@@ -263,11 +335,12 @@ int cov_send(uint8_t * buffer, BACNET_COV_DATA * data)
|
|||||||
datalink_get_broadcast_address(&dest);
|
datalink_get_broadcast_address(&dest);
|
||||||
|
|
||||||
/* encode the NPDU portion of the packet */
|
/* encode the NPDU portion of the packet */
|
||||||
pdu_len = npdu_encode_apdu(&buffer[0], &dest, NULL, false /* true for confirmed messages */,
|
pdu_len = npdu_encode_apdu(&buffer[0], &dest, NULL,
|
||||||
|
false /* true for confirmed messages */,
|
||||||
MESSAGE_PRIORITY_NORMAL);
|
MESSAGE_PRIORITY_NORMAL);
|
||||||
|
|
||||||
/* encode the APDU portion of the packet */
|
/* encode the APDU portion of the packet */
|
||||||
pdu_len += cov_encode_apdu(&buffer[pdu_len], data);
|
pdu_len += ucov_notify_encode_apdu(&buffer[pdu_len], data);
|
||||||
|
|
||||||
bytes_sent = datalink_send_pdu(&dest, /* destination address */
|
bytes_sent = datalink_send_pdu(&dest, /* destination address */
|
||||||
&buffer[0], pdu_len); /* number of bytes of data */
|
&buffer[0], pdu_len); /* number of bytes of data */
|
||||||
@@ -301,38 +374,73 @@ void datalink_get_broadcast_address(BACNET_ADDRESS * dest)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCOVData(Test * pTest, BACNET_COV_DATA * data)
|
/* dummy function stubs */
|
||||||
|
uint16_t Device_Max_APDU_Length_Accepted(void)
|
||||||
|
{
|
||||||
|
return MAX_APDU;
|
||||||
|
}
|
||||||
|
|
||||||
|
void testCOVNotifyData(Test * pTest,
|
||||||
|
BACNET_COV_DATA * data,
|
||||||
|
BACNET_COV_DATA * test_data)
|
||||||
|
{
|
||||||
|
ct_test(pTest,
|
||||||
|
test_data->subscriberProcessIdentifier ==
|
||||||
|
data->subscriberProcessIdentifier);
|
||||||
|
ct_test(pTest,
|
||||||
|
test_data->initiatingDeviceIdentifier ==
|
||||||
|
data->initiatingDeviceIdentifier);
|
||||||
|
ct_test(pTest,
|
||||||
|
test_data->monitoredObjectIdentifier.type ==
|
||||||
|
data->monitoredObjectIdentifier.type);
|
||||||
|
ct_test(pTest,
|
||||||
|
test_data->monitoredObjectIdentifier.instance ==
|
||||||
|
data->monitoredObjectIdentifier.instance);
|
||||||
|
ct_test(pTest,
|
||||||
|
test_data->timeRemaining == data->timeRemaining);
|
||||||
|
/* FIXME: test the listOfValues in some clever manner */
|
||||||
|
}
|
||||||
|
|
||||||
|
void testUCOVNotifyData(Test * pTest, BACNET_COV_DATA * data)
|
||||||
{
|
{
|
||||||
uint8_t apdu[480] = { 0 };
|
uint8_t apdu[480] = { 0 };
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
BACNET_COV_DATA test_data;
|
BACNET_COV_DATA test_data;
|
||||||
|
|
||||||
len = cov_encode_apdu(&apdu[0], data);
|
len = ucov_notify_encode_apdu(&apdu[0], data);
|
||||||
|
ct_test(pTest, len > 0);
|
||||||
|
apdu_len = len;
|
||||||
|
|
||||||
|
test_data.listOfValues.next = NULL;
|
||||||
|
len = ucov_notify_decode_apdu(&apdu[0], apdu_len, &test_data);
|
||||||
|
ct_test(pTest, len != -1);
|
||||||
|
testCOVNotifyData(pTest, data, &test_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testCCOVNotifyData(Test * pTest, uint8_t invoke_id, BACNET_COV_DATA * data)
|
||||||
|
{
|
||||||
|
uint8_t apdu[480] = { 0 };
|
||||||
|
int len = 0;
|
||||||
|
int apdu_len = 0;
|
||||||
|
BACNET_COV_DATA test_data;
|
||||||
|
uint8_t test_invoke_id = 0;
|
||||||
|
|
||||||
|
len = ccov_notify_encode_apdu(&apdu[0], invoke_id, data);
|
||||||
ct_test(pTest, len != 0);
|
ct_test(pTest, len != 0);
|
||||||
apdu_len = len;
|
apdu_len = len;
|
||||||
|
|
||||||
test_data.listOfValues.next = NULL;
|
test_data.listOfValues.next = NULL;
|
||||||
len = cov_decode_apdu(&apdu[0], apdu_len, &test_data);
|
len = ccov_notify_decode_apdu(&apdu[0], apdu_len,
|
||||||
ct_test(pTest, len != -1);
|
&test_invoke_id, &test_data);
|
||||||
ct_test(pTest,
|
ct_test(pTest, len > 0);
|
||||||
test_data.subscriberProcessIdentifier ==
|
ct_test(pTest, test_invoke_id == invoke_id);
|
||||||
data->subscriberProcessIdentifier);
|
testCOVNotifyData(pTest, data, &test_data);
|
||||||
ct_test(pTest,
|
|
||||||
test_data.initiatingDeviceIdentifier ==
|
|
||||||
data->initiatingDeviceIdentifier);
|
|
||||||
ct_test(pTest,
|
|
||||||
test_data.monitoredObjectIdentifier.type ==
|
|
||||||
data->monitoredObjectIdentifier.type);
|
|
||||||
ct_test(pTest,
|
|
||||||
test_data.monitoredObjectIdentifier.instance ==
|
|
||||||
data->monitoredObjectIdentifier.instance);
|
|
||||||
ct_test(pTest, test_data.timeRemaining == data->timeRemaining);
|
|
||||||
/* FIXME: test the listOfValues in some clever manner */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testCOV(Test * pTest)
|
void testCOVNotify(Test * pTest)
|
||||||
{
|
{
|
||||||
|
uint8_t invoke_id = 12;
|
||||||
BACNET_COV_DATA data;
|
BACNET_COV_DATA data;
|
||||||
/* BACNET_PROPERTY_VALUE value2; */
|
/* BACNET_PROPERTY_VALUE value2; */
|
||||||
|
|
||||||
@@ -349,7 +457,8 @@ void testCOV(Test * pTest)
|
|||||||
data.listOfValues.priority = 0;
|
data.listOfValues.priority = 0;
|
||||||
data.listOfValues.next = NULL;
|
data.listOfValues.next = NULL;
|
||||||
|
|
||||||
testCOVData(pTest, &data);
|
testUCOVNotifyData(pTest, &data);
|
||||||
|
testCCOVNotifyData(pTest, invoke_id, &data);
|
||||||
|
|
||||||
/* FIXME: add more values to the list of values */
|
/* FIXME: add more values to the list of values */
|
||||||
}
|
}
|
||||||
@@ -362,7 +471,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
pTest = ct_create("BACnet COV", NULL);
|
pTest = ct_create("BACnet COV", NULL);
|
||||||
/* individual tests */
|
/* individual tests */
|
||||||
rc = ct_addTestFunction(pTest, testCOV);
|
rc = ct_addTestFunction(pTest, testCOVNotify);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
|
|
||||||
ct_setStream(pTest, stdout);
|
ct_setStream(pTest, stdout);
|
||||||
|
|||||||
+17
-6
@@ -61,21 +61,32 @@ typedef struct BACnet_COV_Data {
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
/* encode service - use -1 for limit if you want unlimited */
|
int ucov_notify_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data);
|
||||||
int cov_encode_apdu(uint8_t * apdu, BACNET_COV_DATA * data);
|
|
||||||
|
|
||||||
int cov_decode_service_request(uint8_t * apdu,
|
int ucov_notify_decode_apdu(uint8_t * apdu,
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data);
|
unsigned apdu_len, BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int cov_decode_apdu(uint8_t * apdu,
|
int ucov_notify_send(uint8_t * buffer, BACNET_COV_DATA * data);
|
||||||
|
|
||||||
|
int ccov_notify_encode_apdu(uint8_t * apdu,
|
||||||
|
uint8_t invoke_id, BACNET_COV_DATA * data);
|
||||||
|
|
||||||
|
int ccov_notify_decode_apdu(uint8_t * apdu,
|
||||||
|
unsigned apdu_len,
|
||||||
|
uint8_t * invoke_id,
|
||||||
|
BACNET_COV_DATA * data);
|
||||||
|
|
||||||
|
/* common for both confirmed and unconfirmed */
|
||||||
|
int cov_notify_decode_service_request(uint8_t * apdu,
|
||||||
unsigned apdu_len, BACNET_COV_DATA * data);
|
unsigned apdu_len, BACNET_COV_DATA * data);
|
||||||
|
|
||||||
int cov_send(uint8_t * buffer, BACNET_COV_DATA * data);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
void testCOV(Test * pTest);
|
void testCOVNotify(Test * pTest);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ BASEDIR = .
|
|||||||
#CFLAGS = -Wall -I.
|
#CFLAGS = -Wall -I.
|
||||||
# -g for debugging with gdb
|
# -g for debugging with gdb
|
||||||
#CFLAGS = -Wall -I. -g
|
#CFLAGS = -Wall -I. -g
|
||||||
CFLAGS = -Wall -I. -Itest -DTEST -DTEST_COV -g
|
CFLAGS = -Wall -I. -Itest -Idemo/object -DTEST -DTEST_COV -g
|
||||||
|
|
||||||
SRCS = bacdcode.c \
|
SRCS = bacdcode.c \
|
||||||
bacstr.c \
|
bacstr.c \
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ int main(int argc, char *argv[])
|
|||||||
/* only one value in our value list */
|
/* only one value in our value list */
|
||||||
cov_data.listOfValues.next = NULL;
|
cov_data.listOfValues.next = NULL;
|
||||||
|
|
||||||
cov_send(&Handler_Transmit_Buffer[0],&cov_data);
|
ucov_notify_send(&Handler_Transmit_Buffer[0],&cov_data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user