-context specific decoders for all of the primitive times to go with the context specific encoders
-unconfirmed/confirmed EventNotificationRequest structure/encoder/decoder
-BACnetTimestamp structure/encoder/decoder
-BACnetPropertyStates structure/encoder/decoder
-BACnetDeviceObjectPropertyReference structure/encoder/decoder

Changes:
-decode_context_object_id::object_type changed to uint16_t
-explicit casts have been added to some functions to remove compiler warnings
-encode_bacnet_date::year behaviour has been changed slightly
This commit is contained in:
minack
2008-10-14 04:02:34 +00:00
parent 1dad528da8
commit 60ac0d0f8a
16 changed files with 3593 additions and 33 deletions
+711 -25
View File
@@ -71,6 +71,24 @@
B'1110' reserved by ASHRAE
B'1111' reserved by ASHRAE
*/
/* Encoding of BACNET Length/Value/Type tag
From clause 20.2.1.3.1
B'000' interpreted as Value = FALSE if application class == BOOLEAN
B'001' interpreted as Value = TRUE if application class == BOOLEAN
B'000' interpreted as Length = 0 if application class != BOOLEAN
B'001' interpreted as Length = 1
B'010' interpreted as Length = 2
B'011' interpreted as Length = 3
B'100' interpreted as Length = 4
B'101' interpreted as Length > 4
B'110' interpreted as Type = Opening Tag
B'111' interpreted as Type = Closing Tag
*/
/* from clause 20.1.2.4 max-segments-accepted */
/* and clause 20.1.2.5 max-APDU-length-accepted */
/* returns the encoded octet */
@@ -285,7 +303,7 @@ int encode_closing_tag(
static bool decode_is_extended_tag_number(
uint8_t * apdu)
{
return ((apdu[0] & 0xF0) == 0xF0);
return (bool)((apdu[0] & 0xF0) == 0xF0);
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -293,7 +311,7 @@ static bool decode_is_extended_tag_number(
static bool decode_is_extended_value(
uint8_t * apdu)
{
return ((apdu[0] & 0x07) == 5);
return (bool)((apdu[0] & 0x07) == 5);
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -301,7 +319,7 @@ static bool decode_is_extended_value(
bool decode_is_context_specific(
uint8_t * apdu)
{
return ((apdu[0] & BIT3) == BIT3);
return (bool)((apdu[0] & BIT3) == BIT3);
}
int decode_tag_number(
@@ -319,7 +337,7 @@ int decode_tag_number(
len++;
} else {
if (tag_number) {
*tag_number = (apdu[0] >> 4);
*tag_number = (uint8_t)(apdu[0] >> 4);
}
}
@@ -329,7 +347,7 @@ int decode_tag_number(
bool decode_is_opening_tag(
uint8_t * apdu)
{
return ((apdu[0] & 0x07) == 6);
return (bool)((apdu[0] & 0x07) == 6);
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -337,7 +355,7 @@ bool decode_is_opening_tag(
bool decode_is_closing_tag(
uint8_t * apdu)
{
return ((apdu[0] & 0x07) == 7);
return (bool)((apdu[0] & 0x07) == 7);
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -398,10 +416,26 @@ bool decode_is_context_tag(
uint8_t my_tag_number = 0;
bool context_specific = false;
context_specific = decode_is_context_specific(apdu);
decode_tag_number(apdu, &my_tag_number);
return (context_specific && (my_tag_number == tag_number));
return (bool)(context_specific && (my_tag_number == tag_number));
}
bool decode_is_context_tag_with_length(
uint8_t * apdu,
uint8_t tag_number,
int * tag_length)
{
uint8_t my_tag_number = 0;
bool context_specific = false;
context_specific = decode_is_context_specific(apdu);
*tag_length = decode_tag_number(apdu, &my_tag_number);
return (bool)(context_specific && (my_tag_number == tag_number));
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -413,10 +447,10 @@ bool decode_is_opening_tag_number(
uint8_t my_tag_number = 0;
bool opening_tag = false;
opening_tag = ((apdu[0] & 0x07) == 6);
opening_tag = (bool)((apdu[0] & 0x07) == 6);
decode_tag_number(apdu, &my_tag_number);
return (opening_tag && (my_tag_number == tag_number));
return (bool)(opening_tag && (my_tag_number == tag_number));
}
/* from clause 20.2.1.3.2 Constructed Data */
@@ -428,10 +462,10 @@ bool decode_is_closing_tag_number(
uint8_t my_tag_number = 0;
bool closing_tag = false;
closing_tag = ((apdu[0] & 0x07) == 7);
closing_tag = (bool)((apdu[0] & 0x07) == 7);
decode_tag_number(apdu, &my_tag_number);
return (closing_tag && (my_tag_number == tag_number));
return (bool)(closing_tag && (my_tag_number == tag_number));
}
/* from clause 20.2.3 Encoding of a Boolean Value */
@@ -456,13 +490,13 @@ int encode_application_boolean(
/* context tagged is encoded differently */
int encode_context_boolean(
uint8_t * apdu,
int tag_number,
uint8_t tag_number,
bool boolean_value)
{
int len = 0; /* return value */
len = encode_tag(&apdu[0], (uint8_t) tag_number, true, 1);
apdu[len] = boolean_value ? 1 : 0;
apdu[len] = (bool)(boolean_value ? 1 : 0);
len++;
return len;
@@ -480,6 +514,29 @@ bool decode_context_boolean(
return boolean_value;
}
int decode_context_boolean2(
uint8_t * apdu,
uint8_t tag_number,
bool *boolean_value)
{
int len = 0;
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
if (apdu[len]) {
*boolean_value = true;
}
else
{
*boolean_value = false;
}
len++;
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.3 Encoding of a Boolean Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -567,7 +624,7 @@ int decode_bitstring(
bitstring_set_octet(bit_string, (uint8_t) i,
byte_reverse_bits(apdu[len++]));
}
unused_bits = apdu[0] & 0x07;
unused_bits = (uint8_t)(apdu[0] & 0x07);
bitstring_set_bits_used(bit_string, (uint8_t) bytes_used,
unused_bits);
}
@@ -576,6 +633,27 @@ int decode_bitstring(
return len;
}
int decode_context_bitstring(
uint8_t * apdu,
uint8_t tag_number,
BACNET_BIT_STRING * bit_string)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_bitstring(&apdu[len], len_value, bit_string);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.10 Encoding of a Bit String Value */
/* returns the number of apdu bytes consumed */
int encode_bitstring(
@@ -593,9 +671,9 @@ int encode_bitstring(
} else {
used_bytes = bitstring_bytes_used(bit_string);
remaining_used_bits =
bitstring_bits_used(bit_string) - ((used_bytes - 1) * 8);
(uint8_t)(bitstring_bits_used(bit_string) - ((used_bytes - 1) * 8));
/* number of unused bits in the subsequent final octet */
apdu[len++] = 8 - remaining_used_bits;
apdu[len++] = (uint8_t)(8 - remaining_used_bits);
for (i = 0; i < used_bytes; i++) {
apdu[len++] = byte_reverse_bits(bitstring_octet(bit_string, i));
}
@@ -650,12 +728,30 @@ int decode_object_id(
int len = 0;
len = decode_unsigned32(apdu, &value);
*object_type = ((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT);
*object_type = (uint16_t)(((value >> BACNET_INSTANCE_BITS) & BACNET_MAX_OBJECT));
*instance = (value & BACNET_MAX_INSTANCE);
return len;
}
int decode_context_object_id(
uint8_t * apdu,
uint8_t tag_number,
uint16_t * object_type,
uint32_t * instance)
{
int len = 0;
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
len += decode_object_id(&apdu[len], object_type, instance);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.14 Encoding of an Object Identifier Value */
/* returns the number of apdu bytes consumed */
int encode_bacnet_object_id(
@@ -807,6 +903,34 @@ int decode_octet_string(
return len;
}
int decode_context_octet_string(
uint8_t * apdu,
uint8_t tag_number,
BACNET_OCTET_STRING * octet_string)
{
int len = 0; /* return value */
bool status = false;
uint32_t len_value = 0;
if (decode_is_context_tag(&apdu[len], tag_number))
{
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
status = octetstring_init(octet_string, &apdu[len], len_value);
if (status) {
len += len_value;
}
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.9 Encoding of a Character String Value */
/* returns the number of apdu bytes consumed */
int encode_bacnet_character_string(
@@ -889,6 +1013,35 @@ int decode_character_string(
return len;
}
int decode_context_character_string(
uint8_t * apdu,
uint8_t tag_number,
BACNET_CHARACTER_STRING * char_string)
{
int len = 0; /* return value */
bool status = false;
uint32_t len_value = 0;
if (decode_is_context_tag(&apdu[len], tag_number))
{
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
status =
characterstring_init(char_string, apdu[len], (char *) &apdu[len+1],
len_value - 1);
if (status) {
len += len_value;
}
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -923,6 +1076,27 @@ int decode_unsigned(
return len_value;
}
int decode_context_unsigned(
uint8_t * apdu,
uint8_t tag_number,
uint32_t * value)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_unsigned(&apdu[len], len_value, value);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.4 Encoding of an Unsigned Integer Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -1002,6 +1176,27 @@ int decode_enumerated(
return len;
}
int decode_context_enumerated(
uint8_t * apdu,
uint8_t tag_value,
int *value)
{
int len = 0;
uint8_t tag_number;
uint32_t len_value;
if (decode_is_context_tag(&apdu[len], tag_value)) {
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_enumerated(&apdu[len], len_value, value);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.11 Encoding of an Enumerated Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -1081,6 +1276,26 @@ int decode_signed(
return len_value;
}
int decode_context_signed(
uint8_t * apdu,
uint8_t tag_number,
int32_t * value)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_signed(&apdu[len], len_value, value);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.5 Encoding of a Signed Integer Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -1281,6 +1496,45 @@ int decode_bacnet_time(
return 4;
}
int decode_application_time(
uint8_t * apdu,
BACNET_TIME * btime)
{
int len = 0;
uint8_t tag_number;
decode_tag_number(&apdu[len], &tag_number);
if ( tag_number == BACNET_APPLICATION_TAG_TIME )
{
len++;
len += decode_bacnet_time(&apdu[len], btime);
}
else
{
len = -1;
}
return len;
}
int decode_context_bacnet_time(
uint8_t * apdu,
uint8_t tag_number,
BACNET_TIME * btime)
{
int len = 0;
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
len += decode_bacnet_time(&apdu[len], btime);
}
else
{
len = -1;
}
return len;
}
/* BACnet Date */
/* year = years since 1900 */
/* month 1=Jan */
@@ -1295,14 +1549,23 @@ int encode_bacnet_date(
BACNET_DATE * bdate)
{
/* allow 2 digit years */
if (bdate->year < 1900) {
if (bdate->year <= 38) {
bdate->year += 2000;
} else {
bdate->year += 1900;
}
if (bdate->year >= 1900) {
apdu[0] = (uint8_t)(bdate->year - 1900);
}
apdu[0] = bdate->year - 1900;
else if ( bdate->year < 0x100 )
{
apdu[0] = (uint8_t)bdate->year;
}
else
{
/*
** Don't try and guess what the user meant here. Just fail
*/
return -1;
}
apdu[1] = bdate->month;
apdu[2] = bdate->day;
apdu[3] = bdate->wday;
@@ -1310,6 +1573,7 @@ int encode_bacnet_date(
return 4;
}
/* from clause 20.2.12 Encoding of a Date Value */
/* and 20.2.1 General Rules for Encoding BACnet Tags */
/* returns the number of apdu bytes consumed */
@@ -1353,7 +1617,7 @@ int decode_date(
uint8_t * apdu,
BACNET_DATE * bdate)
{
bdate->year = apdu[0] + 1900;
bdate->year = (uint16_t)(apdu[0] + 1900);
bdate->month = apdu[1];
bdate->day = apdu[2];
bdate->wday = apdu[3];
@@ -1361,6 +1625,45 @@ int decode_date(
return 4;
}
int decode_application_date(
uint8_t * apdu,
BACNET_DATE * bdate)
{
int len = 0;
uint8_t tag_number;
decode_tag_number(&apdu[len], &tag_number);
if ( tag_number == BACNET_APPLICATION_TAG_DATE )
{
len++;
len += decode_date(&apdu[len], bdate);
}
else
{
len = -1;
}
return len;
}
int decode_context_date(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DATE * bdate)
{
int len = 0;
if (decode_is_context_tag_with_length(&apdu[len], tag_number, &len)) {
len += decode_date(&apdu[len], bdate);
}
else
{
len = -1;
}
return len;
}
/* returns the number of apdu bytes consumed */
int encode_simple_ack(
uint8_t * apdu,
@@ -1990,6 +2293,358 @@ void testBACDCodeBitString(
}
}
void testUnsignedContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
/* 32 bit number */
uint32_t in = 0xdeadbeef;
uint32_t out;
outLen2 = decode_context_unsigned(apdu, 9, &out);
in = 0xdeadbeef;
inLen = encode_context_unsigned(apdu, 10, in);
outLen = decode_context_unsigned(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
ct_test(pTest, outLen2 == -1);
/* 16 bit number */
in = 0xdead;
inLen = encode_context_unsigned(apdu, 10, in);
outLen = decode_context_unsigned(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 8 bit number */
in = 0xde;
inLen = encode_context_unsigned(apdu, 10, in);
outLen = decode_context_unsigned(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 4 bit number */
in = 0xd;
inLen = encode_context_unsigned(apdu, 10, in);
outLen = decode_context_unsigned(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 2 bit number */
in = 0x2;
inLen = encode_context_unsigned(apdu, 10, in);
outLen = decode_context_unsigned(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
}
void testSignedContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
/* 32 bit number */
int32_t in = 0xdeadbeef;
int32_t out;
outLen2 = decode_context_signed(apdu, 9, &out);
in = 0xdeadbeef;
inLen = encode_context_signed(apdu, 10, in);
outLen = decode_context_signed(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
ct_test(pTest, outLen2 == -1);
/* 16 bit number */
in = 0xdead;
inLen = encode_context_signed(apdu, 10, in);
outLen = decode_context_signed(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 8 bit number */
in = 0xde;
inLen = encode_context_signed(apdu, 10, in);
outLen = decode_context_signed(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 4 bit number */
in = 0xd;
inLen = encode_context_signed(apdu, 10, in);
outLen = decode_context_signed(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 2 bit number */
in = 0x2;
inLen = encode_context_signed(apdu, 10, in);
outLen = decode_context_signed(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
}
void testEnumeratedContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
/* 32 bit number */
int32_t in = 0xdeadbeef;
int32_t out;
outLen2 = decode_context_enumerated(apdu, 9, &out);
in = 0xdeadbeef;
inLen = encode_context_enumerated(apdu, 10, in);
outLen = decode_context_enumerated(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
ct_test(pTest, outLen2 == -1);
/* 16 bit number */
in = 0xdead;
inLen = encode_context_enumerated(apdu, 10, in);
outLen = decode_context_enumerated(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 8 bit number */
in = 0xde;
inLen = encode_context_enumerated(apdu, 10, in);
outLen = decode_context_enumerated(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 4 bit number */
in = 0xd;
inLen = encode_context_enumerated(apdu, 10, in);
outLen = decode_context_enumerated(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
/* 2 bit number */
in = 0x2;
inLen = encode_context_enumerated(apdu, 10, in);
outLen = decode_context_enumerated(apdu, 10, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
}
void testFloatContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
/* 32 bit number */
float in;
float out;
in = 0.1234f;
inLen = encode_context_real(apdu, 10, in);
outLen = decode_context_real(apdu, 10, &out);
outLen2 = decode_context_real(apdu, 9, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
ct_test(pTest, outLen2 == -1);
in = 0.0f;
inLen = encode_context_real(apdu, 10, in);
outLen = decode_context_real(apdu, 10, &out);
outLen2 = decode_context_real(apdu, 9, &out);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in == out);
}
void testObjectIDContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
/* 32 bit number */
uint16_t in_type;
uint32_t in_id;
uint16_t out_type;
uint32_t out_id;
in_type = 0xde;
in_id = 0xbeef;
inLen = encode_context_object_id(apdu, 10, in_type, in_id);
outLen = decode_context_object_id(apdu, 10, &out_type, &out_id);
outLen2 = decode_context_object_id(apdu, 9, &out_type, &out_id);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in_type == out_type);
ct_test(pTest, in_id == out_id);
ct_test(pTest, outLen2 == -1);
}
void testCharacterStringContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
BACNET_CHARACTER_STRING in;
BACNET_CHARACTER_STRING out;
characterstring_init_ansi(&in, "This is a test");
inLen = encode_context_character_string(apdu, 10, &in);
outLen= decode_context_character_string(apdu, 10, &out);
outLen2= decode_context_character_string(apdu, 9, &out);
ct_test(pTest, outLen2 == -1);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in.length == out.length);
ct_test(pTest, in.encoding == out.encoding);
ct_test(pTest, strcmp(in.value, out.value) == 0);
}
void testBitStringContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
BACNET_BIT_STRING in;
BACNET_BIT_STRING out;
bitstring_init(&in);
bitstring_set_bit(&in, 1, true);
bitstring_set_bit(&in, 3, true);
bitstring_set_bit(&in, 6, true);
bitstring_set_bit(&in, 10, false);
bitstring_set_bit(&in, 11, true);
bitstring_set_bit(&in, 12, false);
inLen = encode_context_bitstring(apdu, 10, &in);
outLen= decode_context_bitstring(apdu, 10, &out);
outLen2= decode_context_bitstring(apdu, 9, &out);
ct_test(pTest, outLen2 == -1);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in.bits_used == out.bits_used);
ct_test(pTest, memcmp(in.value, out.value, MAX_BITSTRING_BYTES) == 0);
}
void testOctetStringContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
BACNET_OCTET_STRING in;
BACNET_OCTET_STRING out;
uint8_t initData[] = {0xde,0xad,0xbe,0xef};
octetstring_init(&in, initData, sizeof(initData));
inLen = encode_context_octet_string(apdu, 10, &in);
outLen= decode_context_octet_string(apdu, 10, &out);
outLen2= decode_context_octet_string(apdu, 9, &out);
ct_test(pTest, outLen2 == -1);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in.length == out.length);
ct_test(pTest, memcmp(in.value, out.value, MAX_APDU - 6) == 0);
}
void testTimeContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
BACNET_TIME in;
BACNET_TIME out;
in.hour = 10;
in.hundredths = 20;
in.min = 30;
in.sec = 40;
inLen = encode_context_time(apdu, 10, &in);
outLen= decode_context_bacnet_time(apdu, 10, &out);
outLen2= decode_context_bacnet_time(apdu, 9, &out);
ct_test(pTest, outLen2 == -1);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in.hour == out.hour);
ct_test(pTest, in.hundredths == out.hundredths);
ct_test(pTest, in.min == out.min);
ct_test(pTest, in.sec == out.sec);
}
void testDateContextDecodes(Test * pTest)
{
uint8_t apdu[MAX_APDU];
int inLen;
int outLen;
int outLen2;
BACNET_DATE in;
BACNET_DATE out;
in.day = 3;
in.month = 10;
in.wday = 5;
in.year = 1945;
inLen = encode_context_date(apdu, 10, &in);
outLen= decode_context_date(apdu, 10, &out);
outLen2= decode_context_date(apdu, 9, &out);
ct_test(pTest, outLen2 == -1);
ct_test(pTest, inLen == outLen);
ct_test(pTest, in.day == out.day);
ct_test(pTest, in.month == out.month);
ct_test(pTest, in.wday == out.wday);
ct_test(pTest, in.year == out.year);
}
#ifdef TEST_DECODE
int main(
void)
@@ -2023,6 +2678,37 @@ int main(
assert(rc);
rc = ct_addTestFunction(pTest, testBACDCodeBitString);
assert(rc);
rc = ct_addTestFunction(pTest, testUnsignedContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testSignedContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testEnumeratedContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testCharacterStringContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testFloatContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testObjectIDContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testBitStringContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testTimeContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testDateContextDecodes);
assert(rc);
rc = ct_addTestFunction(pTest, testOctetStringContextDecodes);
assert(rc);
/* configure output */
ct_setStream(pTest, stdout);
ct_run(pTest);
+209
View File
@@ -0,0 +1,209 @@
#include <assert.h>
#include "bacdcode.h"
#include "npdu.h"
#include "device.h"
#include "datalink.h"
#include "timestamp.h"
#include "bacdevobjpropref.h"
int bacapp_encode_context_device_obj_property_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
{
int len;
int apdu_len = 0;
len = encode_opening_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
len = bacapp_encode_device_obj_property_ref(&apdu[apdu_len], value);
apdu_len += len;
len = encode_closing_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
return apdu_len;
}
int bacapp_encode_device_obj_property_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
{
int len;
int apdu_len = 0;
len = encode_context_object_id(&apdu[apdu_len], 0,
value->objectIdentifier.type,
value->objectIdentifier.instance);
apdu_len += len;
len = encode_context_enumerated(&apdu[apdu_len], 1,
value->propertyIdentifier);
apdu_len += len;
if ( value->arrayIndex > 0 )
{
len = encode_context_unsigned(&apdu[apdu_len], 2,
value->arrayIndex);
apdu_len += len;
}
len = encode_context_object_id(&apdu[apdu_len], 3,
value->deviceIndentifier.type,
value->deviceIndentifier.instance);
apdu_len += len;
return apdu_len;
}
int bacapp_decode_device_obj_property_ref(
uint8_t * apdu,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
{
int len;
int apdu_len = 0;
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 0,
&value->objectIdentifier.type,
&value->objectIdentifier.instance)) )
{
return -1;
}
apdu_len += len;
if ( -1 == ( len = decode_context_enumerated(&apdu[apdu_len], 1,
&value->propertyIdentifier)))
{
return -1;
}
apdu_len += len;
if ( decode_is_context_tag(&apdu[apdu_len], 2 ))
{
if ( -1 == ( len = decode_context_unsigned(&apdu[apdu_len], 2,
&value->arrayIndex)))
{
return -1;
}
apdu_len += len;
}
else
{
value->arrayIndex = 0;
}
if ( decode_is_context_tag(&apdu[apdu_len], 3 ))
{
if ( -1 == ( len = decode_context_object_id(&apdu[apdu_len], 3,
&value->deviceIndentifier.type,
&value->deviceIndentifier.instance)) )
{
return -1;
}
apdu_len += len;
}
else
{
value->deviceIndentifier.instance = 0;
value->deviceIndentifier.type = 0;
}
return apdu_len;
}
int bacapp_decode_context_device_obj_property_ref(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE * value)
{
int len = 0;
int section_length;
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
len++;
section_length = bacapp_decode_device_obj_property_ref(
&apdu[len], value);
if ( section_length == -1 )
{
len = -1;
}
else
{
len += section_length;
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
len++;
}
else
{
len = -1;
}
}
}
else
{
len = -1;
}
return len;
}
#ifdef TEST
void testDevIdPropRef(
Test * pTest)
{
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE inData;
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE outData;
uint8_t buffer[MAX_APDU];
int inLen;
int outLen;
inData.objectIdentifier.instance = 0x1234;
inData.objectIdentifier.type = 15;
inData.propertyIdentifier = 25;
inData.arrayIndex = 0x5678;
inData.deviceIndentifier.instance = 0x4343;
inData.deviceIndentifier.type = 28;
inLen = bacapp_encode_device_obj_property_ref(buffer, &inData);
outLen = bacapp_decode_device_obj_property_ref(buffer, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.objectIdentifier.instance == outData.objectIdentifier.instance);
ct_test(pTest, inData.objectIdentifier.type == outData.objectIdentifier.type);
ct_test(pTest, inData.propertyIdentifier == outData.propertyIdentifier);
ct_test(pTest, inData.arrayIndex == outData.arrayIndex);
ct_test(pTest, inData.deviceIndentifier.instance == outData.deviceIndentifier.instance);
ct_test(pTest, inData.deviceIndentifier.type == outData.deviceIndentifier.type);
}
#ifdef TEST_DEV_ID_PROP_REF
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Prop Ref", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testDevIdPropRef);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif // TEST_DEV_ID_PROP_REF
#endif // TEST
+369
View File
@@ -0,0 +1,369 @@
#include <assert.h>
#include "bacdcode.h"
#include "npdu.h"
#include "device.h"
#include "datalink.h"
#include "timestamp.h"
#include "bacpropstates.h"
int bacapp_decode_property_state(
uint8_t * apdu,
BACNET_PROPERTY_STATE * value)
{
int len = 0;
uint32_t len_value_type;
int section_length;
section_length =
decode_tag_number_and_value(&apdu[len], (uint8_t*)&value->tag,
&len_value_type);
if ( -1 == section_length )
{
return -1;
}
len += section_length;
switch(value->tag)
{
case BOOLEAN_VALUE:
value->state.booleanValue = decode_boolean(len_value_type);
break;
case BINARY_VALUE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.binaryValue)))
{
return -1;
}
break;
case EVENT_TYPE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.eventType)))
{
return -1;
}
break;
case POLARITY:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.polarity)))
{
return -1;
}
break;
case PROGRAM_CHANGE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programChange)))
{
return -1;
}
break;
case PROGRAM_STATE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programState)))
{
return -1;
}
break;
case REASON_FOR_HALT:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.programError)))
{
return -1;
}
break;
case RELIABILITY:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.reliability)))
{
return -1;
}
break;
case STATE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.state)))
{
return -1;
}
break;
case SYSTEM_STATUS:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.systemStatus)))
{
return -1;
}
break;
case UNITS:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.units)))
{
return -1;
}
break;
case UNSIGNED_VALUE:
if ( -1 == ( section_length = decode_unsigned(&apdu[len], len_value_type, &value->state.unsignedValue)))
{
return -1;
}
break;
case LIFE_SAFETY_MODE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyMode)))
{
return -1;
}
break;
case LIFE_SAFETY_STATE:
if ( -1 == ( section_length = decode_enumerated(&apdu[len], len_value_type, &value->state.lifeSafetyState)))
{
return -1;
}
break;
default:
return -1;
}
len += section_length;
return len;
}
int bacapp_decode_context_property_state(
uint8_t * apdu,
uint8_t tag_number,
BACNET_PROPERTY_STATE * value)
{
int len = 0;
int section_length;
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
len++;
section_length = bacapp_decode_property_state(
&apdu[len], value);
if ( section_length == -1 )
{
len = -1;
}
else
{
len += section_length;
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
len++;
}
else
{
len = -1;
}
}
}
else
{
len = -1;
}
return len;
}
int bacapp_encode_property_state(
uint8_t * apdu,
BACNET_PROPERTY_STATE * value)
{
int len = 0; /* length of each encoding */
if (value && apdu) {
switch(value->tag)
{
case BOOLEAN_VALUE:
len = encode_context_boolean(&apdu[0], 0, value->state.booleanValue);
break;
case BINARY_VALUE:
len = encode_context_enumerated(&apdu[0], 1, value->state.binaryValue);
break;
case EVENT_TYPE:
len = encode_context_enumerated(&apdu[0], 2, value->state.eventType);
break;
case POLARITY:
len = encode_context_enumerated(&apdu[0], 3, value->state.polarity);
break;
case PROGRAM_CHANGE:
len = encode_context_enumerated(&apdu[0], 4, value->state.programChange);
break;
case PROGRAM_STATE:
len = encode_context_enumerated(&apdu[0], 5, value->state.programState);
break;
case REASON_FOR_HALT:
len = encode_context_enumerated(&apdu[0], 6, value->state.programError);
break;
case RELIABILITY:
len = encode_context_enumerated(&apdu[0], 7, value->state.reliability);
break;
case STATE:
len = encode_context_enumerated(&apdu[0], 8, value->state.state);
break;
case SYSTEM_STATUS:
len = encode_context_enumerated(&apdu[0], 9, value->state.systemStatus);
break;
case UNITS:
len = encode_context_enumerated(&apdu[0], 10, value->state.units);
break;
case UNSIGNED_VALUE:
len = encode_context_unsigned(&apdu[0], 11, value->state.unsignedValue);
break;
case LIFE_SAFETY_MODE:
len = encode_context_enumerated(&apdu[0], 12, value->state.lifeSafetyMode);
break;
case LIFE_SAFETY_STATE:
len = encode_context_enumerated(&apdu[0], 13, value->state.lifeSafetyState);
break;
default:
assert(0);
break;
}
}
return len;
}
#ifdef TEST
void testPropStates(
Test * pTest)
{
BACNET_PROPERTY_STATE inData;
BACNET_PROPERTY_STATE outData;
uint8_t appMsg[MAX_APDU];
int inLen;
int outLen;
inData.tag = BOOLEAN_VALUE;
inData.state.booleanValue = true;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.booleanValue == outData.state.booleanValue );
/****************
*****************
****************/
inData.tag = BINARY_VALUE;
inData.state.binaryValue = BINARY_ACTIVE;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.binaryValue == outData.state.binaryValue );
/****************
*****************
****************/
inData.tag = EVENT_TYPE;
inData.state.eventType = EVENT_BUFFER_READY;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.eventType == outData.state.eventType );
/****************
*****************
****************/
inData.tag = POLARITY;
inData.state.polarity = POLARITY_REVERSE;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.polarity == outData.state.polarity );
/****************
*****************
****************/
inData.tag = PROGRAM_CHANGE;
inData.state.programChange = PROGRAM_REQUEST_RESTART;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.programChange == outData.state.programChange );
/****************
*****************
****************/
inData.tag = UNSIGNED_VALUE;
inData.state.unsignedValue = 0xdeadbeef;
inLen = bacapp_encode_property_state(appMsg, &inData);
memset(&outData, 0, sizeof(outData));
outLen = bacapp_decode_property_state(appMsg, &outData);
ct_test(pTest, outLen == inLen);
ct_test(pTest, inData.tag == outData.tag );
ct_test(pTest, inData.state.unsignedValue == outData.state.unsignedValue );
}
#ifdef TEST_PROP_STATES
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Event", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testPropStates);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif // TEST_PROP_STATES
#endif // TEST
+19
View File
@@ -76,6 +76,25 @@ int decode_real(
return 4;
}
int decode_context_real(
uint8_t * apdu,
uint8_t tag_number,
float *real_value)
{
uint32_t len_value;
int len = 0;
if (decode_is_context_tag(&apdu[len], tag_number)) {
len += decode_tag_number_and_value(&apdu[len], &tag_number,
&len_value);
len += decode_real(&apdu[len], real_value);
}
else
{
len = -1;
}
return len;
}
/* from clause 20.2.6 Encoding of a Real Number Value */
/* returns the number of apdu bytes consumed */
int encode_bacnet_real(
+2 -2
View File
@@ -96,10 +96,10 @@ uint8_t bitstring_bits_used(
}
/* returns the number of bytes that a bit string is using */
int bitstring_bytes_used(
uint8_t bitstring_bytes_used(
BACNET_BIT_STRING * bit_string)
{
int len = 0; /* return value */
uint8_t len = 0; /* return value */
uint8_t used_bytes = 0;
uint8_t last_bit = 0;
+134 -3
View File
@@ -38,6 +38,7 @@
#include <stdlib.h>
#include <ctype.h>
#include "datetime.h"
#include "bacdcode.h"
/* BACnet Date */
/* year = years since 1900 */
@@ -52,6 +53,7 @@
time or date may be interpreted as "any" or "don't care"
*/
static bool is_leap_year(
uint16_t year)
{
@@ -73,7 +75,7 @@ static uint8_t month_days(
if ((month == 2) && is_leap_year(year))
return 29;
else if (month >= 1 && month <= 12)
return month_days[month];
return (uint8_t)month_days[month];
else
return 0;
}
@@ -128,7 +130,7 @@ static void days_since_epoch_into_ymd(
month++;
}
day += ((uint8_t) days);
day = (uint8_t) (day + days);
if (pYear)
*pYear = year;
@@ -148,7 +150,7 @@ static uint8_t day_of_week(
uint8_t month,
uint8_t day)
{
return ((uint8_t) (days_since_epoch(year, month, day) % 7) + 1);
return (uint8_t) ((days_since_epoch(year, month, day) % 7) + 1);
}
/* if the date1 is the same as date2, return is 0
@@ -428,6 +430,93 @@ void datetime_wildcard_set(
}
}
int bacapp_encode_context_datetime(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DATE_TIME * value)
{
int len = 0;
int apdu_len = 0;
if ( apdu && value )
{
len = encode_opening_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
len = encode_application_date(&apdu[apdu_len], &value->date);
apdu_len += len;
len = encode_application_time(&apdu[apdu_len], &value->time);
apdu_len += len;
len = encode_closing_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
}
return apdu_len;
}
int bacapp_decode_datetime(
uint8_t * apdu,
BACNET_DATE_TIME * value)
{
int len = 0;
int section_len;
if ( -1 == ( section_len = decode_application_date(&apdu[len], &value->date) ) )
{
return -1;
}
len += section_len;
if ( -1 == ( section_len = decode_application_time(&apdu[len], &value->time) ) )
{
return -1;
}
len += section_len;
return len;
}
int bacapp_decode_context_datetime(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DATE_TIME * value)
{
int apdu_len = 0;
int len;
if (decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
apdu_len++;
}
else
{
return -1;
}
if ( -1 == (len = bacapp_decode_datetime(&apdu[apdu_len], value)))
{
return -1;
}
else
{
apdu_len += len;
}
if (decode_is_closing_tag_number(&apdu[apdu_len], tag_number))
{
apdu_len++;
}
else
{
return -1;
}
return apdu_len;
}
#ifdef TEST
#include <assert.h>
@@ -744,6 +833,43 @@ void testBACnetDayOfWeek(
ct_test(pTest, dow == 3);
}
void testDatetimeCodec(
Test * pTest)
{
uint8_t apdu[MAX_APDU];
BACNET_DATE_TIME datetimeIn;
BACNET_DATE_TIME datetimeOut;
int inLen;
int outLen;
datetimeIn.date.day = 1;
datetimeIn.date.month = 2;
datetimeIn.date.wday = 3;
datetimeIn.date.year = 1904;
datetimeIn.time.hour = 5;
datetimeIn.time.min = 6;
datetimeIn.time.sec = 7;
datetimeIn.time.hundredths = 8;
inLen = bacapp_encode_context_datetime(apdu, 10, &datetimeIn);
outLen = bacapp_decode_context_datetime(apdu, 10, &datetimeOut);
ct_test(pTest, inLen == outLen );
ct_test(pTest, datetimeIn.date.day == datetimeOut.date.day);
ct_test(pTest, datetimeIn.date.month == datetimeOut.date.month);
ct_test(pTest, datetimeIn.date.wday == datetimeOut.date.wday);
ct_test(pTest, datetimeIn.date.year == datetimeOut.date.year);
ct_test(pTest, datetimeIn.time.hour == datetimeOut.time.hour);
ct_test(pTest, datetimeIn.time.min == datetimeOut.time.min);
ct_test(pTest, datetimeIn.time.sec == datetimeOut.time.sec);
ct_test(pTest, datetimeIn.time.hundredths == datetimeOut.time.hundredths);
}
#ifdef TEST_DATE_TIME
int main(
void)
@@ -769,6 +895,8 @@ int main(
assert(rc);
rc = ct_addTestFunction(pTest, testBACnetDateTimeWildcard);
assert(rc);
rc = ct_addTestFunction(pTest, testDatetimeCodec);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
@@ -777,5 +905,8 @@ int main(
return 0;
}
#endif /* TEST_DATE_TIME */
#endif /* TEST */
File diff suppressed because it is too large Load Diff
+249
View File
@@ -0,0 +1,249 @@
#include "assert.h"
#include "timestamp.h"
int bacapp_encode_context_timestamp(
uint8_t * apdu,
uint8_t tag_number,
BACNET_TIMESTAMP * value)
{
int len = 0; /* length of each encoding */
int apdu_len = 0;
if (value && apdu) {
len = encode_opening_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
switch(value->tag)
{
case TIME_STAMP_TIME:
len = encode_context_time(&apdu[apdu_len], 0, &value->value.time);
break;
case TIME_STAMP_SEQUENCE:
len = encode_context_unsigned(&apdu[apdu_len], 1, value->value.sequenceNum);
break;
case TIME_STAMP_DATETIME:
len = bacapp_encode_context_datetime(&apdu[apdu_len], 2, &value->value.dateTime);
break;
default:
len = 0;
assert(0);
break;
}
apdu_len += len;
len = encode_closing_tag(&apdu[apdu_len], tag_number);
apdu_len += len;
}
return apdu_len;
}
int bacapp_decode_context_timestamp(
uint8_t * apdu,
uint8_t tag_number,
BACNET_TIMESTAMP * value)
{
int len = 0;
int section_len;
uint32_t len_value_type;
uint32_t sequenceNum;
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
len++;
section_len =
decode_tag_number_and_value(&apdu[len], &value->tag,
&len_value_type);
if ( -1 == section_len )
{
return -1;
}
switch( value->tag )
{
case TIME_STAMP_TIME:
if ( (section_len = decode_context_bacnet_time(&apdu[len], TIME_STAMP_TIME, &value->value.time)) == -1 )
{
return -1;
}
else
{
len += section_len;
}
break;
case TIME_STAMP_SEQUENCE:
if ( (section_len = decode_context_unsigned(&apdu[len], TIME_STAMP_SEQUENCE, &sequenceNum)) == -1 )
{
return -1;
}
else
{
if ( sequenceNum <= 0xffff )
{
len += section_len;
value->value.sequenceNum = (uint16_t)sequenceNum;
}
else
{
return -1;
}
}
break;
case TIME_STAMP_DATETIME:
if ( (section_len = bacapp_decode_context_datetime(&apdu[len], TIME_STAMP_DATETIME, &value->value.dateTime)) == -1 )
{
return -1;
}
else
{
len += section_len;
}
break;
default:
return -1;
}
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
len++;
}
else
{
return -1;
}
}
return len;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
void testTimestampSequence(
Test * pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
uint8_t buffer[MAX_APDU];
int inLen;
int outLen;
testTimestampIn.tag = TIME_STAMP_SEQUENCE;
testTimestampIn.value.sequenceNum = 0x1234;
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest, testTimestampIn.value.sequenceNum == testTimestampOut.value.sequenceNum);
}
void testTimestampTime(
Test * pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
uint8_t buffer[MAX_APDU];
int inLen;
int outLen;
testTimestampIn.tag = TIME_STAMP_TIME;
testTimestampIn.value.time.hour = 1;
testTimestampIn.value.time.min = 2;
testTimestampIn.value.time.sec = 3;
testTimestampIn.value.time.hundredths = 4;
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest, testTimestampIn.value.time.hour == testTimestampOut.value.time.hour);
ct_test(pTest, testTimestampIn.value.time.min == testTimestampOut.value.time.min);
ct_test(pTest, testTimestampIn.value.time.sec == testTimestampOut.value.time.sec);
ct_test(pTest, testTimestampIn.value.time.hundredths == testTimestampOut.value.time.hundredths);
}
void testTimestampTimeDate(
Test * pTest)
{
BACNET_TIMESTAMP testTimestampIn;
BACNET_TIMESTAMP testTimestampOut;
uint8_t buffer[MAX_APDU];
int inLen;
int outLen;
testTimestampIn.tag = TIME_STAMP_DATETIME;
testTimestampIn.value.dateTime.time.hour = 1;
testTimestampIn.value.dateTime.time.min = 2;
testTimestampIn.value.dateTime.time.sec = 3;
testTimestampIn.value.dateTime.time.hundredths = 4;
testTimestampIn.value.dateTime.date.year = 1901;
testTimestampIn.value.dateTime.date.month = 1;
testTimestampIn.value.dateTime.date.wday = 2;
testTimestampIn.value.dateTime.date.day = 3;
memset(&testTimestampOut, 0, sizeof(testTimestampOut));
inLen = bacapp_encode_context_timestamp(buffer, 2, &testTimestampIn);
outLen = bacapp_decode_context_timestamp(buffer, 2, &testTimestampOut);
ct_test(pTest, inLen == outLen);
ct_test(pTest, testTimestampIn.tag == testTimestampOut.tag);
ct_test(pTest, testTimestampIn.value.dateTime.time.hour == testTimestampOut.value.dateTime.time.hour);
ct_test(pTest, testTimestampIn.value.dateTime.time.min == testTimestampOut.value.dateTime.time.min);
ct_test(pTest, testTimestampIn.value.dateTime.time.sec == testTimestampOut.value.dateTime.time.sec);
ct_test(pTest, testTimestampIn.value.dateTime.time.hundredths == testTimestampOut.value.dateTime.time.hundredths);
ct_test(pTest, testTimestampIn.value.dateTime.date.year == testTimestampOut.value.dateTime.date.year);
ct_test(pTest, testTimestampIn.value.dateTime.date.month == testTimestampOut.value.dateTime.date.month);
ct_test(pTest, testTimestampIn.value.dateTime.date.wday == testTimestampOut.value.dateTime.date.wday);
ct_test(pTest, testTimestampIn.value.dateTime.date.day == testTimestampOut.value.dateTime.date.day);
}
#ifdef TEST_TIME_STAMP
int main(
void)
{
Test *pTest;
bool rc;
pTest = ct_create("BACnet Time Stamp", NULL);
/* individual tests */
rc = ct_addTestFunction(pTest, testTimestampSequence);
assert(rc);
rc = ct_addTestFunction(pTest, testTimestampTime);
assert(rc);
rc = ct_addTestFunction(pTest, testTimestampTimeDate);
assert(rc);
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
ct_destroy(pTest);
return 0;
}
#endif // TEST_TIME_STAMP
#endif // TEST