writing unit tests
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
set listsize 35
|
||||||
|
set print array on
|
||||||
|
set print pretty on
|
||||||
|
set print union on
|
||||||
|
set print address on
|
||||||
|
list
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
-kr -nut -nlp
|
||||||
+226
-234
@@ -33,8 +33,10 @@
|
|||||||
####COPYRIGHTEND####*/
|
####COPYRIGHTEND####*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
|
#include "bacenum.h"
|
||||||
#include "bits.h"
|
#include "bits.h"
|
||||||
#include "bigend.h"
|
#include "bigend.h"
|
||||||
|
|
||||||
@@ -47,10 +49,10 @@
|
|||||||
|
|
||||||
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_tag(uint8_t *apdu, uint8_t tag_number, bool context_specific,
|
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
||||||
uint32_t len_value_type)
|
uint32_t len_value_type)
|
||||||
{
|
{
|
||||||
int len = 1; // return value
|
int len = 1; // return value
|
||||||
union {
|
union {
|
||||||
uint8_t byte[2];
|
uint8_t byte[2];
|
||||||
uint16_t value;
|
uint16_t value;
|
||||||
@@ -81,36 +83,36 @@ int encode_tag(uint8_t *apdu, uint8_t tag_number, bool context_specific,
|
|||||||
else {
|
else {
|
||||||
apdu[0] |= 5;
|
apdu[0] |= 5;
|
||||||
if (len_value_type <= 253) {
|
if (len_value_type <= 253) {
|
||||||
apdu[len] = len_value_type;
|
apdu[len] = len_value_type;
|
||||||
len++;
|
len++;
|
||||||
} else if (len_value_type <= 65535) {
|
} else if (len_value_type <= 65535) {
|
||||||
apdu[len] = 254;
|
apdu[len] = 254;
|
||||||
len++;
|
len++;
|
||||||
short_data.value = len_value_type;
|
short_data.value = len_value_type;
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
apdu[len + 0] = short_data.byte[0];
|
apdu[len + 0] = short_data.byte[0];
|
||||||
apdu[len + 1] = short_data.byte[1];
|
apdu[len + 1] = short_data.byte[1];
|
||||||
} else {
|
} else {
|
||||||
apdu[len + 0] = short_data.byte[1];
|
apdu[len + 0] = short_data.byte[1];
|
||||||
apdu[len + 1] = short_data.byte[0];
|
apdu[len + 1] = short_data.byte[0];
|
||||||
}
|
}
|
||||||
len += 2;
|
len += 2;
|
||||||
} else {
|
} else {
|
||||||
apdu[len] = 255;
|
apdu[len] = 255;
|
||||||
len++;
|
len++;
|
||||||
long_data.value = len_value_type;
|
long_data.value = len_value_type;
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
apdu[len + 0] = long_data.byte[0];
|
apdu[len + 0] = long_data.byte[0];
|
||||||
apdu[len + 1] = long_data.byte[1];
|
apdu[len + 1] = long_data.byte[1];
|
||||||
apdu[len + 2] = long_data.byte[2];
|
apdu[len + 2] = long_data.byte[2];
|
||||||
apdu[len + 3] = long_data.byte[3];
|
apdu[len + 3] = long_data.byte[3];
|
||||||
} else {
|
} else {
|
||||||
apdu[len + 0] = long_data.byte[3];
|
apdu[len + 0] = long_data.byte[3];
|
||||||
apdu[len + 1] = long_data.byte[2];
|
apdu[len + 1] = long_data.byte[2];
|
||||||
apdu[len + 2] = long_data.byte[1];
|
apdu[len + 2] = long_data.byte[1];
|
||||||
apdu[len + 3] = long_data.byte[0];
|
apdu[len + 3] = long_data.byte[0];
|
||||||
}
|
}
|
||||||
len += 4;
|
len += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,16 +121,16 @@ int encode_tag(uint8_t *apdu, uint8_t tag_number, bool context_specific,
|
|||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
|
int encode_opening_tag(uint8_t * apdu, uint8_t tag_number)
|
||||||
{
|
{
|
||||||
int len = 1;
|
int len = 1;
|
||||||
|
|
||||||
apdu[0] = BIT3;
|
apdu[0] = BIT3;
|
||||||
// additional tag byte after this byte for extended tag byte
|
// additional tag byte after this byte for extended tag byte
|
||||||
if (tag_number <= 14)
|
if (tag_number <= 14)
|
||||||
apdu[0] |= (tag_number << 4);
|
apdu[0] |= (tag_number << 4);
|
||||||
else {
|
else {
|
||||||
apdu[0] |= 0xF0;
|
apdu[0] |= 0xF0;
|
||||||
apdu[1] = tag_number;
|
apdu[1] = tag_number;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
@@ -141,16 +143,16 @@ int encode_opening_tag(uint8_t *apdu, uint8_t tag_number)
|
|||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_closing_tag(uint8_t *apdu, uint8_t tag_number)
|
int encode_closing_tag(uint8_t * apdu, uint8_t tag_number)
|
||||||
{
|
{
|
||||||
int len = 1;
|
int len = 1;
|
||||||
|
|
||||||
apdu[0] = BIT3;
|
apdu[0] = BIT3;
|
||||||
// additional tag byte after this byte for extended tag byte
|
// additional tag byte after this byte for extended tag byte
|
||||||
if (tag_number <= 14)
|
if (tag_number <= 14)
|
||||||
apdu[0] |= (tag_number << 4);
|
apdu[0] |= (tag_number << 4);
|
||||||
else {
|
else {
|
||||||
apdu[0] |= 0xF0;
|
apdu[0] |= 0xF0;
|
||||||
apdu[1] = tag_number;
|
apdu[1] = tag_number;
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
@@ -163,30 +165,29 @@ int encode_closing_tag(uint8_t *apdu, uint8_t tag_number)
|
|||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_tag_number(uint8_t *apdu,int *tag_number)
|
int decode_tag_number(uint8_t * apdu, uint8_t * tag_number)
|
||||||
{
|
{
|
||||||
int len = 1;
|
int len = 1;
|
||||||
|
|
||||||
if ((apdu[0] & 0xF0) == 0xF0) {
|
if ((apdu[0] & 0xF0) == 0xF0) {
|
||||||
*tag_number = (int)apdu[1];
|
*tag_number = (int) apdu[1];
|
||||||
len++;
|
len++;
|
||||||
}
|
} else
|
||||||
else
|
*tag_number = (int) apdu[0];
|
||||||
*tag_number = (int)apdu[0];
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
bool decode_is_context_specific(uint8_t *apdu)
|
bool decode_is_context_specific(uint8_t * apdu)
|
||||||
{
|
{
|
||||||
return (apdu[0] & BIT3);
|
return (apdu[0] & BIT3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_tag_value(uint8_t *apdu, uint32_t *value)
|
int decode_tag_value(uint8_t * apdu, uint32_t * value)
|
||||||
{
|
{
|
||||||
int len = 1;
|
int len = 1;
|
||||||
union {
|
union {
|
||||||
@@ -204,56 +205,53 @@ int decode_tag_value(uint8_t *apdu, uint32_t *value)
|
|||||||
if ((apdu[0] & 0xF0) == 0xF0)
|
if ((apdu[0] & 0xF0) == 0xF0)
|
||||||
len++;
|
len++;
|
||||||
if (apdu[len] == 255) {
|
if (apdu[len] == 255) {
|
||||||
len++;
|
len++;
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
long_data.byte[0] = apdu[len + 0];
|
long_data.byte[0] = apdu[len + 0];
|
||||||
long_data.byte[1] = apdu[len + 1];
|
long_data.byte[1] = apdu[len + 1];
|
||||||
long_data.byte[2] = apdu[len + 2];
|
long_data.byte[2] = apdu[len + 2];
|
||||||
long_data.byte[3] = apdu[len + 3];
|
long_data.byte[3] = apdu[len + 3];
|
||||||
} else {
|
} else {
|
||||||
long_data.byte[3] = apdu[len + 0];
|
long_data.byte[3] = apdu[len + 0];
|
||||||
long_data.byte[2] = apdu[len + 1];
|
long_data.byte[2] = apdu[len + 1];
|
||||||
long_data.byte[1] = apdu[len + 2];
|
long_data.byte[1] = apdu[len + 2];
|
||||||
long_data.byte[0] = apdu[len + 3];
|
long_data.byte[0] = apdu[len + 3];
|
||||||
}
|
}
|
||||||
value = long_data.value;
|
*value = long_data.value;
|
||||||
len += 4;
|
len += 4;
|
||||||
|
|
||||||
}
|
} else if (apdu[len] == 254) {
|
||||||
else if (apdu[len] == 254) {
|
len++;
|
||||||
len++;
|
if (big_endian()) {
|
||||||
if (is_big_endian()) {
|
short_data.byte[0] = apdu[len + 0];
|
||||||
short_data.byte[0] = apdu[len + 0];
|
short_data.byte[1] = apdu[len + 1];
|
||||||
short_data.byte[1] = apdu[len + 1];
|
} else {
|
||||||
} else {
|
short_data.byte[1] = apdu[len + 0];
|
||||||
short_data.byte[1] = apdu[len + 0];
|
short_data.byte[0] = apdu[len + 1];
|
||||||
short_data.byte[0] = apdu[len + 1];
|
}
|
||||||
}
|
*value = short_data.value;
|
||||||
value = short_data.value;
|
len += 2;
|
||||||
len += 2;
|
} else {
|
||||||
}
|
|
||||||
else {
|
|
||||||
*value = apdu[len];
|
*value = apdu[len];
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} else
|
||||||
else
|
*value = (int) (apdu[0] & 5);
|
||||||
*value = (int)(apdu[0] & 5);
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.6 Encoding of a Real Number Value
|
// from clause 20.2.6 Encoding of a Real Number Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_real(uint8_t *apdu, float *real_value)
|
int decode_real(uint8_t * apdu, float *real_value)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
float real_value;
|
float real_value;
|
||||||
} my_data;
|
} my_data;
|
||||||
|
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
my_data.byte[0] = apdu[0];
|
my_data.byte[0] = apdu[0];
|
||||||
my_data.byte[1] = apdu[1];
|
my_data.byte[1] = apdu[1];
|
||||||
my_data.byte[2] = apdu[2];
|
my_data.byte[2] = apdu[2];
|
||||||
@@ -265,14 +263,14 @@ int decode_real(uint8_t *apdu, float *real_value)
|
|||||||
my_data.byte[3] = apdu[0];
|
my_data.byte[3] = apdu[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
real_value = my_data.real_value;
|
*real_value = my_data.real_value;
|
||||||
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.6 Encoding of a Real Number Value
|
// from clause 20.2.6 Encoding of a Real Number Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_real(float value, uint8_t *apdu)
|
int encode_bacnet_real(float value, uint8_t * apdu)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
@@ -281,7 +279,7 @@ int encode_bacnet_real(float value, uint8_t *apdu)
|
|||||||
|
|
||||||
my_data.real_value = value;
|
my_data.real_value = value;
|
||||||
|
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
apdu[0] = my_data.byte[0];
|
apdu[0] = my_data.byte[0];
|
||||||
apdu[1] = my_data.byte[1];
|
apdu[1] = my_data.byte[1];
|
||||||
apdu[2] = my_data.byte[2];
|
apdu[2] = my_data.byte[2];
|
||||||
@@ -299,28 +297,27 @@ int encode_bacnet_real(float value, uint8_t *apdu)
|
|||||||
// from clause 20.2.6 Encoding of a Real Number Value
|
// from clause 20.2.6 Encoding of a Real Number Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_real(uint8_t *apdu, float value)
|
int encode_real(uint8_t * apdu, float value)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_float(value, &apdu[1]);
|
len = encode_bacnet_real(value, &apdu[1]);
|
||||||
len += encode_tag(&apdu[0],BACNET_APPLICATION_TAG_REAL, false, len);
|
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_REAL, false, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_object_id(uint8_t *apdu,
|
int decode_object_id(uint8_t * apdu, int *object_type, int *instance)
|
||||||
int *object_type, int *instance)
|
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
} my_data;
|
} my_data;
|
||||||
|
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
my_data.byte[0] = apdu[0];
|
my_data.byte[0] = apdu[0];
|
||||||
my_data.byte[1] = apdu[1];
|
my_data.byte[1] = apdu[1];
|
||||||
my_data.byte[2] = apdu[2];
|
my_data.byte[2] = apdu[2];
|
||||||
@@ -332,16 +329,15 @@ int decode_object_id(uint8_t *apdu,
|
|||||||
my_data.byte[3] = apdu[0];
|
my_data.byte[3] = apdu[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
*object_type = (int)((my_data.value >> 22) & 0x3FF);
|
*object_type = (int) ((my_data.value >> 22) & 0x3FF);
|
||||||
*instance = (int)(my_data.value & 0x3FFFFF);
|
*instance = (int) (my_data.value & 0x3FFFFF);
|
||||||
|
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_object_id(uint8_t * apdu,
|
int encode_bacnet_object_id(uint8_t * apdu, int object_type, int instance)
|
||||||
int object_type, int instance)
|
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
@@ -350,7 +346,7 @@ int encode_bacnet_object_id(uint8_t * apdu,
|
|||||||
|
|
||||||
my_data.value = ((object_type & 0x3FF) << 22) | (instance & 0x3FFFFF);
|
my_data.value = ((object_type & 0x3FF) << 22) | (instance & 0x3FFFFF);
|
||||||
|
|
||||||
if (is_big_endian()) {
|
if (big_endian()) {
|
||||||
apdu[0] = my_data.byte[0];
|
apdu[0] = my_data.byte[0];
|
||||||
apdu[1] = my_data.byte[1];
|
apdu[1] = my_data.byte[1];
|
||||||
apdu[2] = my_data.byte[2];
|
apdu[2] = my_data.byte[2];
|
||||||
@@ -368,14 +364,14 @@ int encode_bacnet_object_id(uint8_t * apdu,
|
|||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_context_object_id(uint8_t * apdu,int tag_number,
|
int encode_context_object_id(uint8_t * apdu, int tag_number,
|
||||||
int object_type, int instance)
|
int object_type, int instance)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_object_id(&apdu[1], object_type, instance);
|
len = encode_bacnet_object_id(&apdu[1], object_type, instance);
|
||||||
len += encode_tag(&apdu[0],tag_number, true, len);
|
len += encode_tag(&apdu[0], tag_number, true, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -383,35 +379,31 @@ int encode_context_object_id(uint8_t * apdu,int tag_number,
|
|||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_object_id(uint8_t *apdu,
|
int encode_object_id(uint8_t * apdu, int object_type, int instance)
|
||||||
enum BACnetObjectType object_type, int instance)
|
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_object_id(&apdu[1], object_type, instance);
|
len = encode_bacnet_object_id(&apdu[1], object_type, instance);
|
||||||
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OBJECT_ID,
|
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_OBJECT_ID,
|
||||||
false, len);
|
false, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
// from clause 20.2.9 Encoding of a Character String Value
|
// from clause 20.2.9 Encoding of a Character String Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_string(uint8_t *apdu,
|
int encode_bacnet_string(uint8_t * apdu, const char *char_string, int len)
|
||||||
const char *char_string, int string_len)
|
|
||||||
{
|
{
|
||||||
int len, i;
|
int i;
|
||||||
|
|
||||||
len = string_len;
|
|
||||||
// limit - 6 octets is the most our tag and type could be
|
// limit - 6 octets is the most our tag and type could be
|
||||||
if (len > (MAX_APDU - 6))
|
if (len > (MAX_APDU - 6))
|
||||||
len = MAX_APDU - 6;
|
len = MAX_APDU - 6;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
apdu[1 + i] = char_string[i];
|
apdu[1 + i] = char_string[i];
|
||||||
}
|
}
|
||||||
// character set ANSI X3.4
|
apdu[0] = CHARACTER_ANSI;
|
||||||
apdu[0] = 0;
|
|
||||||
len++;
|
len++;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -419,13 +411,12 @@ int encode_bacnet_string(uint8_t *apdu,
|
|||||||
|
|
||||||
// from clause 20.2.9 Encoding of a Character String Value
|
// from clause 20.2.9 Encoding of a Character String Value
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_character_string(uint8_t *apdu,
|
int encode_bacnet_character_string(uint8_t * apdu, const char *char_string)
|
||||||
const char *char_string)
|
|
||||||
{
|
{
|
||||||
int len, i;
|
int len;
|
||||||
|
|
||||||
len = strlen(char_string);
|
len = strlen(char_string);
|
||||||
len = encode_bacnet_string(&apdu[0],char_string, len);
|
len = encode_bacnet_string(&apdu[0], char_string, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -433,17 +424,18 @@ int encode_bacnet_character_string(uint8_t *apdu,
|
|||||||
// from clause 20.2.9 Encoding of a Character String Value
|
// from clause 20.2.9 Encoding of a Character String Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_character_string(uint8_t *apdu, const char *char_string)
|
int encode_character_string(uint8_t * apdu, const char *char_string)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
int string_len = 0;
|
int string_len = 0;
|
||||||
|
|
||||||
// find the size of the apdu first
|
// find the size of the apdu first - not necessarily effecient
|
||||||
string_len = strlen(char_string);
|
// but reuses existing functions
|
||||||
len = encode_tag(apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING,
|
string_len = encode_bacnet_character_string(&apdu[1], char_string);
|
||||||
false, string_len + 1/*character set*/);
|
len = encode_tag(&apdu[0], BACNET_APPLICATION_TAG_CHARACTER_STRING,
|
||||||
assert((len + string_len + 1) < MAX_APDU);
|
false, string_len);
|
||||||
len += encode_bacnet_string(&apdu[len], value, string_len);
|
assert((len + string_len) < MAX_APDU);
|
||||||
|
len += encode_bacnet_character_string(&apdu[1], char_string);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
@@ -453,20 +445,22 @@ int encode_character_string(uint8_t *apdu, const char *char_string)
|
|||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_character_string(uint8_t * apdu, char *char_string)
|
int decode_character_string(uint8_t * apdu, char *char_string)
|
||||||
{
|
{
|
||||||
int len = 0,i;
|
int len = 0, i = 0;
|
||||||
uint32_t len_value;
|
uint32_t len_value = 0;
|
||||||
|
|
||||||
len = decode_tag_value(&apdu[0], &len_value);
|
len = decode_tag_value(&apdu[0], &len_value);
|
||||||
// decode ANSI X3.4
|
if (len_value) {
|
||||||
if (apdu[len] == 0)
|
// decode ANSI X3.4
|
||||||
{
|
if (apdu[len] == 0) {
|
||||||
len++;
|
len++;
|
||||||
for (i = 0; i < len_value; i++) {
|
len_value--;
|
||||||
char_string[i] = apdu[len + i];
|
for (i = 0; i < len_value; i++) {
|
||||||
|
char_string[i] = apdu[len + i];
|
||||||
|
}
|
||||||
|
// terminate the c string
|
||||||
|
char_string[i] = 0;
|
||||||
|
len += len_value;
|
||||||
}
|
}
|
||||||
// terminate the c string
|
|
||||||
char_string[i] = 0;
|
|
||||||
len += len_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -475,31 +469,27 @@ int decode_character_string(uint8_t * apdu, char *char_string)
|
|||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_unsigned(uint8_t *apdu, unsigned int value)
|
int encode_bacnet_unsigned(uint8_t * apdu, unsigned int value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|
||||||
if (value < 0x100) {
|
if (value < 0x100) {
|
||||||
apdu[0] = value;
|
apdu[0] = value;
|
||||||
len = 1;
|
len = 1;
|
||||||
}
|
} else if (value < 0x10000) {
|
||||||
else if (value < 0x10000) {
|
|
||||||
apdu[0] = value / 0x100;
|
apdu[0] = value / 0x100;
|
||||||
apdu[1] = value - (apdu[0] * 0x100);
|
apdu[1] = value - (apdu[0] * 0x100);
|
||||||
len = 2;
|
len = 2;
|
||||||
}
|
} else if (value < 0x1000000) {
|
||||||
else if (value < 0x1000000) {
|
|
||||||
apdu[0] = value / 0x10000;
|
apdu[0] = value / 0x10000;
|
||||||
apdu[1] = (value - apdu[0] * 0x10000) / 0x100;
|
apdu[1] = (value - apdu[0] * 0x10000) / 0x100;
|
||||||
apdu[2] = value - (apdu[0] * 0x10000) - (apdu[1] * 0x100);
|
apdu[2] = value - (apdu[0] * 0x10000) - (apdu[1] * 0x100);
|
||||||
len = 3;
|
len = 3;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
apdu[0] = value / 0x1000000;
|
apdu[0] = value / 0x1000000;
|
||||||
apdu[1] = (value - (apdu[0] * 0x1000000)) / 0x10000;
|
apdu[1] = (value - (apdu[0] * 0x1000000)) / 0x10000;
|
||||||
apdu[2] =
|
apdu[2] =
|
||||||
(value - (apdu[0] * 0x1000000) -
|
(value - (apdu[0] * 0x1000000) - (apdu[1] * 0x10000)) / 0x100;
|
||||||
(apdu[1] * 0x10000)) / 0x100;
|
|
||||||
apdu[3] =
|
apdu[3] =
|
||||||
value - (apdu[0] * 0x1000000) - (apdu[1] * 0x10000) -
|
value - (apdu[0] * 0x1000000) - (apdu[1] * 0x10000) -
|
||||||
(apdu[2] * 0x100);
|
(apdu[2] * 0x100);
|
||||||
@@ -512,7 +502,7 @@ int encode_bacnet_unsigned(uint8_t *apdu, unsigned int value)
|
|||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_context_unsigned(uint8_t *apdu, int tag_number, int value)
|
int encode_context_unsigned(uint8_t * apdu, int tag_number, int value)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
@@ -530,7 +520,7 @@ int encode_unsigned(uint8_t * apdu, unsigned int value)
|
|||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
len = encode_bacnet_unsigned(&apdu[1], value);
|
len = encode_bacnet_unsigned(&apdu[1], value);
|
||||||
len += encode_tag(&apdu[0],BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||||
false, len);
|
false, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
@@ -539,33 +529,32 @@ int encode_unsigned(uint8_t * apdu, unsigned int value)
|
|||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_unsigned(uint8_t *apdu, int *value)
|
int decode_unsigned(uint8_t * apdu, int *value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
uint32_t len_value;
|
uint32_t len_value;
|
||||||
|
|
||||||
len = decode_tag_value(&apdu[0], &len_value);
|
len = decode_tag_value(&apdu[0], &len_value);
|
||||||
|
|
||||||
switch (len_value)
|
switch (len_value) {
|
||||||
{
|
case 1:
|
||||||
case 1:
|
*value = apdu[len];
|
||||||
*value = apdu[len];
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
*value = (apdu[len] * 0x100) + apdu[len + 1];
|
||||||
*value = (apdu[len] * 0x100) + apdu[len + 1];
|
break;
|
||||||
break;
|
case 3:
|
||||||
case 3:
|
*value = (apdu[len] * 0x10000) +
|
||||||
*value = (apdu[len] * 0x10000) +
|
(apdu[len + 1] * 0x100) + apdu[len + 2];
|
||||||
(apdu[len + 1] * 0x100) + apdu[len + 2];
|
break;
|
||||||
break;
|
case 4:
|
||||||
case 4:
|
*value = (apdu[len] * 0x1000000) +
|
||||||
*value = (apdu[len] * 0x1000000) +
|
(apdu[len + 1] * 0x10000) + (apdu[len + 2] * 0x100) +
|
||||||
(apdu[len + 1] * 0x10000) + (apdu[len + 2] * 0x100) +
|
apdu[len + 3];
|
||||||
apdu[len + 3];
|
break;
|
||||||
break;
|
default:
|
||||||
default:
|
*value = 0;
|
||||||
*value = 0;
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
len += len_value;
|
len += len_value;
|
||||||
|
|
||||||
@@ -575,7 +564,7 @@ int decode_unsigned(uint8_t *apdu, int *value)
|
|||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_enumerated(uint8_t * apdu_ptr, int *value)
|
int decode_enumerated(uint8_t * apdu, int *value)
|
||||||
{
|
{
|
||||||
return decode_unsigned(apdu, value);
|
return decode_unsigned(apdu, value);
|
||||||
}
|
}
|
||||||
@@ -583,7 +572,7 @@ int decode_enumerated(uint8_t * apdu_ptr, int *value)
|
|||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_enumerated(uint8_t *apdu, int value)
|
int encode_bacnet_enumerated(uint8_t * apdu, int value)
|
||||||
{
|
{
|
||||||
return encode_bacnet_unsigned(apdu, value);
|
return encode_bacnet_unsigned(apdu, value);
|
||||||
}
|
}
|
||||||
@@ -591,9 +580,9 @@ int encode_bacnet_enumerated(uint8_t *apdu, int value)
|
|||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_enumerated(uint8_t *apdu, int value)
|
int encode_enumerated(uint8_t * apdu, int value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_enumerated(&apdu[1], value);
|
len = encode_bacnet_enumerated(&apdu[1], value);
|
||||||
@@ -606,10 +595,9 @@ int encode_enumerated(uint8_t *apdu, int value)
|
|||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_context_enumerated(uint8_t * apdu,int tag_number,
|
int encode_context_enumerated(uint8_t * apdu, int tag_number, int value)
|
||||||
int value)
|
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_enumerated(&apdu[1], value);
|
len = encode_bacnet_enumerated(&apdu[1], value);
|
||||||
@@ -621,7 +609,7 @@ int encode_context_enumerated(uint8_t * apdu,int tag_number,
|
|||||||
// from clause 20.2.5 Encoding of a Signed Integer Value
|
// from clause 20.2.5 Encoding of a Signed Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_signed(uint8_t * apdu_ptr, int *value)
|
int decode_signed(uint8_t * apdu, int *value)
|
||||||
{
|
{
|
||||||
return decode_unsigned(apdu, value);
|
return decode_unsigned(apdu, value);
|
||||||
}
|
}
|
||||||
@@ -629,7 +617,7 @@ int decode_signed(uint8_t * apdu_ptr, int *value)
|
|||||||
// from clause 20.2.5 Encoding of a Signed Integer Value
|
// from clause 20.2.5 Encoding of a Signed Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_signed(uint8_t *apdu, int value)
|
int encode_bacnet_signed(uint8_t * apdu, int value)
|
||||||
{
|
{
|
||||||
return encode_bacnet_unsigned(apdu, value);
|
return encode_bacnet_unsigned(apdu, value);
|
||||||
}
|
}
|
||||||
@@ -637,9 +625,9 @@ int encode_bacnet_signed(uint8_t *apdu, int value)
|
|||||||
// from clause 20.2.5 Encoding of a Signed Integer Value
|
// from clause 20.2.5 Encoding of a Signed Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_signed(uint8_t *apdu, int value)
|
int encode_signed(uint8_t * apdu, int value)
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_signed(&apdu[1], value);
|
len = encode_bacnet_signed(&apdu[1], value);
|
||||||
@@ -652,10 +640,9 @@ int encode_signed(uint8_t *apdu, int value)
|
|||||||
// from clause 20.2.5 Encoding of a Signed Integer Value
|
// from clause 20.2.5 Encoding of a Signed Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_context_signed(uint8_t * apdu,int tag_number,
|
int encode_context_signed(uint8_t * apdu, int tag_number, int value)
|
||||||
int value)
|
|
||||||
{
|
{
|
||||||
int len = 0; // return value
|
int len = 0; // return value
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_signed(&apdu[1], value);
|
len = encode_bacnet_signed(&apdu[1], value);
|
||||||
@@ -667,7 +654,8 @@ int encode_context_signed(uint8_t * apdu,int tag_number,
|
|||||||
// from clause 20.2.13 Encoding of a Time Value
|
// from clause 20.2.13 Encoding of a Time Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_time(uint8_t *apdu,int hour, int min, int sec, int hundredths)
|
int encode_bacnet_time(uint8_t * apdu, int hour, int min, int sec,
|
||||||
|
int hundredths)
|
||||||
{
|
{
|
||||||
apdu[0] = hour;
|
apdu[0] = hour;
|
||||||
apdu[1] = min;
|
apdu[1] = min;
|
||||||
@@ -680,13 +668,13 @@ int encode_bacnet_time(uint8_t *apdu,int hour, int min, int sec, int hundredths)
|
|||||||
// from clause 20.2.13 Encoding of a Time Value
|
// from clause 20.2.13 Encoding of a Time Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_time(uint8_t *apdu,int hour, int min, int sec, int hundredths)
|
int encode_time(uint8_t * apdu, int hour, int min, int sec, int hundredths)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_time(&apdu[1], hour, min, sec, hundredths);
|
len = encode_bacnet_time(&apdu[1], hour, min, sec, hundredths);
|
||||||
len += encode_tag(&apdu[0],BACNET_APPLICATION_TAG_TIME, false, len);
|
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_TIME, false, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
@@ -695,7 +683,7 @@ int encode_time(uint8_t *apdu,int hour, int min, int sec, int hundredths)
|
|||||||
// from clause 20.2.13 Encoding of a Time Value
|
// from clause 20.2.13 Encoding of a Time Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_bacnet_time(uint8_t *apdu, int *hour, int *min, int *sec,
|
int decode_bacnet_time(uint8_t * apdu, int *hour, int *min, int *sec,
|
||||||
int *hundredths)
|
int *hundredths)
|
||||||
{
|
{
|
||||||
*hour = apdu[0];
|
*hour = apdu[0];
|
||||||
@@ -715,7 +703,8 @@ int decode_bacnet_time(uint8_t *apdu, int *hour, int *min, int *sec,
|
|||||||
// from clause 20.2.12 Encoding of a Date Value
|
// from clause 20.2.12 Encoding of a Date Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_date(uint8_t *apdu, int year, int month, int day, int wday)
|
int encode_bacnet_date(uint8_t * apdu, int year, int month, int day,
|
||||||
|
int wday)
|
||||||
{
|
{
|
||||||
apdu[0] = year;
|
apdu[0] = year;
|
||||||
apdu[1] = month;
|
apdu[1] = month;
|
||||||
@@ -728,13 +717,13 @@ int encode_bacnet_date(uint8_t *apdu, int year, int month, int day, int wday)
|
|||||||
// from clause 20.2.12 Encoding of a Date Value
|
// from clause 20.2.12 Encoding of a Date Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_date(uint8_t *apdu, int year, int month, int day, int wday)
|
int encode_date(uint8_t * apdu, int year, int month, int day, int wday)
|
||||||
{
|
{
|
||||||
int len = 0;
|
int len = 0;
|
||||||
|
|
||||||
// assumes that the tag only consumes 1 octet
|
// assumes that the tag only consumes 1 octet
|
||||||
len = encode_bacnet_date(&apdu[1], year, month, day, wday);
|
len = encode_bacnet_date(&apdu[1], year, month, day, wday);
|
||||||
len += encode_tag(&apdu[0],BACNET_APPLICATION_TAG_DATE, false, len);
|
len += encode_tag(&apdu[0], BACNET_APPLICATION_TAG_DATE, false, len);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
@@ -743,7 +732,7 @@ int encode_date(uint8_t *apdu, int year, int month, int day, int wday)
|
|||||||
// from clause 20.2.12 Encoding of a Date Value
|
// from clause 20.2.12 Encoding of a Date Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_date(uint8_t *apdu, int *year, int *month, int *day, int *wday)
|
int decode_date(uint8_t * apdu, int *year, int *month, int *day, int *wday)
|
||||||
{
|
{
|
||||||
*year = apdu[0];
|
*year = apdu[0];
|
||||||
*month = apdu[1];
|
*month = apdu[1];
|
||||||
@@ -757,27 +746,28 @@ int decode_date(uint8_t *apdu, int *year, int *month, int *day, int *wday)
|
|||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "bacenum.h"
|
||||||
|
|
||||||
#include "ctest.h"
|
#include "ctest.h"
|
||||||
|
|
||||||
void testDecodingEncodingReal(Test * pTest)
|
void testBACDCodeReal(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t real_array[4] = { 0 };
|
uint8_t real_array[4] = { 0 };
|
||||||
uint8_t encoded_array[4] = { 0 };
|
uint8_t encoded_array[4] = { 0 };
|
||||||
float value = 42.123;
|
float value = 42.123;
|
||||||
float decoded_value = 0;
|
float decoded_value = 0;
|
||||||
|
|
||||||
encode_bacnet_float(value, &real_array[0]);
|
encode_bacnet_real(value, &real_array[0]);
|
||||||
decode_float(&real_array[0],&decoded_value);
|
decode_real(&real_array[0], &decoded_value);
|
||||||
ct_test(pTest, decoded_value == value);
|
ct_test(pTest, decoded_value == value);
|
||||||
encode_bacnet_float(value, &encoded_array[0]);
|
encode_bacnet_real(value, &encoded_array[0]);
|
||||||
ct_test(pTest, memcmp(&real_array, &encoded_array,
|
ct_test(pTest, memcmp(&real_array, &encoded_array,
|
||||||
sizeof(real_array)) == 0);
|
sizeof(real_array)) == 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDecodingEncodingEnumerated(Test * pTest)
|
void testBACDCodeEnumerated(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t array[5] = { 0 };
|
uint8_t array[5] = { 0 };
|
||||||
uint8_t encoded_array[5] = { 0 };
|
uint8_t encoded_array[5] = { 0 };
|
||||||
@@ -787,7 +777,7 @@ void testDecodingEncodingEnumerated(Test * pTest)
|
|||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
encode_enumerated(&array[0], value);
|
encode_enumerated(&array[0], value);
|
||||||
decode_enumerated(&array[0],&decoded_value);
|
decode_enumerated(&array[0], &decoded_value);
|
||||||
ct_test(pTest, decoded_value == value);
|
ct_test(pTest, decoded_value == value);
|
||||||
encode_enumerated(&encoded_array[0], decoded_value);
|
encode_enumerated(&encoded_array[0], decoded_value);
|
||||||
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
||||||
@@ -798,7 +788,7 @@ void testDecodingEncodingEnumerated(Test * pTest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDecodingEncodingUnsigned(Test * pTest)
|
void testBACDCodeUnsigned(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t array[5] = { 0 };
|
uint8_t array[5] = { 0 };
|
||||||
uint8_t encoded_array[5] = { 0 };
|
uint8_t encoded_array[5] = { 0 };
|
||||||
@@ -808,7 +798,7 @@ void testDecodingEncodingUnsigned(Test * pTest)
|
|||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
encode_unsigned(&array[0], value);
|
encode_unsigned(&array[0], value);
|
||||||
decode_unsigned(&array[0],&decoded_value);
|
decode_unsigned(&array[0], &decoded_value);
|
||||||
ct_test(pTest, decoded_value == value);
|
ct_test(pTest, decoded_value == value);
|
||||||
encode_unsigned(&encoded_array[0], decoded_value);
|
encode_unsigned(&encoded_array[0], decoded_value);
|
||||||
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
||||||
@@ -819,7 +809,7 @@ void testDecodingEncodingUnsigned(Test * pTest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDecodingEncodingSigned(Test * pTest)
|
void testBACDCodeSigned(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t array[5] = { 0 };
|
uint8_t array[5] = { 0 };
|
||||||
uint8_t encoded_array[5] = { 0 };
|
uint8_t encoded_array[5] = { 0 };
|
||||||
@@ -829,7 +819,7 @@ void testDecodingEncodingSigned(Test * pTest)
|
|||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
encode_signed(&array[0], value);
|
encode_signed(&array[0], value);
|
||||||
decoded_value = decode_signed(&array[0]);
|
decode_signed(&array[0], &decoded_value);
|
||||||
ct_test(pTest, decoded_value == value);
|
ct_test(pTest, decoded_value == value);
|
||||||
encode_signed(&encoded_array[0], decoded_value);
|
encode_signed(&encoded_array[0], decoded_value);
|
||||||
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
||||||
@@ -837,50 +827,52 @@ void testDecodingEncodingSigned(Test * pTest)
|
|||||||
value = value << 1;
|
value = value << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
value = -1;
|
||||||
|
encode_signed(&array[0], value);
|
||||||
|
decode_signed(&array[0], &decoded_value);
|
||||||
|
ct_test(pTest, decoded_value == value);
|
||||||
|
encode_signed(&encoded_array[0], decoded_value);
|
||||||
|
ct_test(pTest, memcmp(&array[0], &encoded_array[0],
|
||||||
|
sizeof(array)) == 0);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDecodingEncodingString(Test * pTest)
|
void testBACDCodeString(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t array[256] = { 0 };
|
uint8_t array[MAX_APDU] = { 0 };
|
||||||
uint8_t encoded_array[256] = { 0 };
|
uint8_t encoded_array[MAX_APDU] = { 0 };
|
||||||
char test_string[256] = { "" };
|
char test_string[MAX_APDU] = { "" };
|
||||||
char decoded_string[256] = { "" };
|
char decoded_string[MAX_APDU] = { "" };
|
||||||
char *decoded_string_ptr = NULL;
|
|
||||||
int i; // for loop counter
|
int i; // for loop counter
|
||||||
int last_byte;
|
int apdu_len;
|
||||||
int test_last_byte;
|
int test_apdu_len;
|
||||||
size_t len;
|
size_t len;
|
||||||
char *test_string0 = "";
|
char *test_string0 = "";
|
||||||
|
|
||||||
last_byte = encode_string(&array[0], &test_string0[0]);
|
apdu_len = encode_character_string(&array[0], &test_string0[0]);
|
||||||
decoded_string_ptr = decode_string(&array[0], &decoded_string[0]);
|
decode_character_string(&array[0], &decoded_string[0]);
|
||||||
ct_test(pTest, last_byte == 0);
|
ct_test(pTest, apdu_len == 3);
|
||||||
ct_test(pTest, strcmp(&test_string0[0], &decoded_string[0]) == 0);
|
ct_test(pTest, strcmp(&test_string0[0], &decoded_string[0]) == 0);
|
||||||
for (i = 0; i < (256 - 1); i++) {
|
for (i = 0; i < (MAX_APDU - 5); i++) {
|
||||||
test_string[i] = 'S';
|
test_string[i] = 'S';
|
||||||
test_string[i + 1] = '\0';
|
test_string[i + 1] = '\0';
|
||||||
last_byte = encode_string(&encoded_array[0], &test_string[0]);
|
apdu_len =
|
||||||
decoded_string_ptr =
|
encode_character_string(&encoded_array[0], &test_string[0]);
|
||||||
decode_string(&encoded_array[0], &decoded_string[0]);
|
test_apdu_len =
|
||||||
|
decode_character_string(&encoded_array[0], &decoded_string[0]);
|
||||||
len = strlen(test_string);
|
len = strlen(test_string);
|
||||||
if (len <= 3)
|
if (apdu_len != test_apdu_len) {
|
||||||
test_last_byte = len + 1;
|
printf("test string=%d\n", i);
|
||||||
else
|
|
||||||
test_last_byte = len + 2;
|
|
||||||
if (len <= 253) {
|
|
||||||
ct_test(pTest, last_byte == test_last_byte);
|
|
||||||
ct_test(pTest, strcmp(&test_string[0],
|
|
||||||
&decoded_string[0]) == 0);
|
|
||||||
} else {
|
|
||||||
ct_test(pTest, last_byte == 0);
|
|
||||||
}
|
}
|
||||||
|
ct_test(pTest, apdu_len == test_apdu_len);
|
||||||
|
ct_test(pTest, strcmp(&test_string[0], &decoded_string[0]) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void testDecodingEncodingObject(Test * pTest)
|
void testBACDCodeObject(Test * pTest)
|
||||||
{
|
{
|
||||||
uint8_t object_array[4] = {
|
uint8_t object_array[4] = {
|
||||||
0
|
0
|
||||||
@@ -888,14 +880,14 @@ void testDecodingEncodingObject(Test * pTest)
|
|||||||
uint8_t encoded_array[4] = {
|
uint8_t encoded_array[4] = {
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
enum BACnetObjectType type = OBJECT_BINARY_INPUT;
|
BACNET_OBJECT_TYPE type = OBJECT_BINARY_INPUT;
|
||||||
enum BACnetObjectType decoded_type = OBJECT_ANALOG_OUTPUT;
|
BACNET_OBJECT_TYPE decoded_type = OBJECT_ANALOG_OUTPUT;
|
||||||
int instance = 123;
|
int instance = 123;
|
||||||
int decoded_instance = 0;
|
int decoded_instance = 0;
|
||||||
|
|
||||||
encode_bacnet_object_id(&encoded_array[0], type, instance);
|
encode_bacnet_object_id(&encoded_array[0], type, instance);
|
||||||
decode_object_and_instance(&encoded_array[0],
|
decode_object_id(&encoded_array[0],
|
||||||
&decoded_type, &decoded_instance);
|
(int *) &decoded_type, &decoded_instance);
|
||||||
ct_test(pTest, decoded_type == type);
|
ct_test(pTest, decoded_type == type);
|
||||||
ct_test(pTest, decoded_instance == instance);
|
ct_test(pTest, decoded_instance == instance);
|
||||||
encode_bacnet_object_id(&object_array[0], type, instance);
|
encode_bacnet_object_id(&object_array[0], type, instance);
|
||||||
@@ -904,8 +896,8 @@ void testDecodingEncodingObject(Test * pTest)
|
|||||||
for (type = 0; type < 1024; type++) {
|
for (type = 0; type < 1024; type++) {
|
||||||
for (instance = 0; instance <= 0x3FFFFF; instance += 1024) {
|
for (instance = 0; instance <= 0x3FFFFF; instance += 1024) {
|
||||||
encode_bacnet_object_id(&encoded_array[0], type, instance);
|
encode_bacnet_object_id(&encoded_array[0], type, instance);
|
||||||
decode_object_and_instance(&encoded_array[0],
|
decode_object_id(&encoded_array[0],
|
||||||
&decoded_type, &decoded_instance);
|
(int *) &decoded_type, &decoded_instance);
|
||||||
ct_test(pTest, decoded_type == type);
|
ct_test(pTest, decoded_type == type);
|
||||||
ct_test(pTest, decoded_instance == instance);
|
ct_test(pTest, decoded_instance == instance);
|
||||||
encode_bacnet_object_id(&object_array[0], type, instance);
|
encode_bacnet_object_id(&object_array[0], type, instance);
|
||||||
@@ -923,19 +915,19 @@ int main(void)
|
|||||||
Test *pTest;
|
Test *pTest;
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
pTest = ct_create("decoding-encoding", NULL);
|
pTest = ct_create("BACDCode", NULL);
|
||||||
/* individual tests */
|
/* individual tests */
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingReal);
|
rc = ct_addTestFunction(pTest, testBACDCodeReal);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingUnsigned);
|
rc = ct_addTestFunction(pTest, testBACDCodeUnsigned);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingSigned);
|
rc = ct_addTestFunction(pTest, testBACDCodeSigned);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingEnumerated);
|
rc = ct_addTestFunction(pTest, testBACDCodeEnumerated);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingString);
|
rc = ct_addTestFunction(pTest, testBACDCodeString);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
rc = ct_addTestFunction(pTest, testDecodingEncodingObject);
|
rc = ct_addTestFunction(pTest, testBACDCodeObject);
|
||||||
assert(rc);
|
assert(rc);
|
||||||
ct_setStream(pTest, stdout);
|
ct_setStream(pTest, stdout);
|
||||||
ct_run(pTest);
|
ct_run(pTest);
|
||||||
@@ -944,5 +936,5 @@ int main(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_KEYLIST */
|
#endif /* TEST_DECODE */
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|||||||
+36
-54
@@ -37,109 +37,89 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
enum BACnetApplicationTag {
|
|
||||||
BACNET_APPLICATION_TAG_NULL = 0,
|
|
||||||
BACNET_APPLICATION_TAG_BOOLEAN = 1,
|
|
||||||
BACNET_APPLICATION_TAG_UNSIGNED_INT = 2,
|
|
||||||
BACNET_APPLICATION_TAG_SIGNED_INT = 3,
|
|
||||||
BACNET_APPLICATION_TAG_REAL = 4,
|
|
||||||
BACNET_APPLICATION_TAG_DOUBLE = 5,
|
|
||||||
BACNET_APPLICATION_TAG_OCTET_STRING = 6,
|
|
||||||
BACNET_APPLICATION_TAG_CHARACTER_STRING = 7,
|
|
||||||
BACNET_APPLICATION_TAG_BIT_STRING = 8,
|
|
||||||
BACNET_APPLICATION_TAG_ENUMERATED = 9,
|
|
||||||
BACNET_APPLICATION_TAG_DATE = 10,
|
|
||||||
BACNET_APPLICATION_TAG_TIME = 11,
|
|
||||||
BACNET_APPLICATION_TAG_OBJECT_ID = 12,
|
|
||||||
BACNET_APPLICATION_TAG_RESERVED1 = 13,
|
|
||||||
BACNET_APPLICATION_TAG_RESERVED2 = 14,
|
|
||||||
BACNET_APPLICATION_TAG_RESERVED3 = 15,
|
|
||||||
};
|
|
||||||
|
|
||||||
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
// from clause 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_tag(uint8_t *apdu, uint8_t tag_number, bool context_specific,
|
int encode_tag(uint8_t * apdu, uint8_t tag_number, bool context_specific,
|
||||||
uint32_t len_value_type);
|
uint32_t len_value_type);
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_opening_tag(uint8_t *apdu, uint8_t tag_number);
|
int encode_opening_tag(uint8_t * apdu, uint8_t tag_number);
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_closing_tag(uint8_t *apdu, uint8_t tag_number);
|
int encode_closing_tag(uint8_t * apdu, uint8_t tag_number);
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_tag_number(uint8_t *apdu, uint8_t *tag_number);
|
int decode_tag_number(uint8_t * apdu, uint8_t * tag_number);
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
bool decode_is_context_specific(uint8_t *apdu);
|
bool decode_is_context_specific(uint8_t * apdu);
|
||||||
|
|
||||||
// from clause 20.2.1.3.2 Constructed Data
|
// from clause 20.2.1.3.2 Constructed Data
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_tag_value(uint8_t *apdu, uint32_t *value);
|
int decode_tag_value(uint8_t * apdu, uint32_t * value);
|
||||||
|
|
||||||
// from clause 20.2.6 Encoding of a Real Number Value
|
// from clause 20.2.6 Encoding of a Real Number Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_real(uint8_t *apdu, float *real_value);
|
int decode_real(uint8_t * apdu, float *real_value);
|
||||||
int encode_bacnet_real(float value, uint8_t *apdu);
|
int encode_bacnet_real(float value, uint8_t * apdu);
|
||||||
int encode_real(uint8_t *apdu_ptr, float value);
|
int encode_real(uint8_t * apdu, float value);
|
||||||
|
|
||||||
// from clause 20.2.14 Encoding of an Object Identifier Value
|
// from clause 20.2.14 Encoding of an Object Identifier Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_object_id(uint8_t *apdu,
|
int decode_object_id(uint8_t * apdu, int *object_type, int *instance);
|
||||||
int *object_type, int *instance);
|
int encode_bacnet_object_id(uint8_t * apdu, int object_type, int instance);
|
||||||
int encode_bacnet_object_id(uint8_t * apdu,
|
int encode_context_object_id(uint8_t * apdu, int tag_number,
|
||||||
int object_type, int instance);
|
int object_type, int instance);
|
||||||
int encode_context_object_id(uint8_t * apdu,int tag_number,
|
int encode_object_id(uint8_t * apdu, int object_type, int instance);
|
||||||
int object_type, int instance);
|
|
||||||
int encode_object_id(uint8_t *apdu,
|
|
||||||
enum BACnetObjectType object_type, int instance);
|
|
||||||
|
|
||||||
// from clause 20.2.9 Encoding of a Character String Value
|
// from clause 20.2.9 Encoding of a Character String Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_character_string(uint8_t *apdu,
|
int encode_bacnet_string(uint8_t * apdu,
|
||||||
|
const char *char_string, int string_len);
|
||||||
|
int encode_bacnet_character_string(uint8_t * apdu,
|
||||||
const char *char_string);
|
const char *char_string);
|
||||||
int encode_character_string(uint8_t *apdu, const char *char_string);
|
int encode_character_string(uint8_t * apdu, const char *char_string);
|
||||||
int decode_character_string(uint8_t * apdu, char *char_string);
|
int decode_character_string(uint8_t * apdu, char *char_string);
|
||||||
|
|
||||||
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
// from clause 20.2.4 Encoding of an Unsigned Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_unsigned(uint8_t *apdu, unsigned int value);
|
int encode_bacnet_unsigned(uint8_t * apdu, unsigned int value);
|
||||||
int encode_context_unsigned(uint8_t *apdu, int tag_number, int value);
|
int encode_context_unsigned(uint8_t * apdu, int tag_number, int value);
|
||||||
int encode_unsigned(uint8_t * apdu, unsigned int value);
|
int encode_unsigned(uint8_t * apdu, unsigned int value);
|
||||||
int decode_unsigned(uint8_t *apdu, int *value);
|
int decode_unsigned(uint8_t * apdu, int *value);
|
||||||
|
|
||||||
// from clause 20.2.5 Encoding of a Signed Integer Value
|
// from clause 20.2.5 Encoding of a Signed Integer Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_signed(uint8_t *apdu, int value);
|
int encode_bacnet_signed(uint8_t * apdu, int value);
|
||||||
int encode_signed(uint8_t *apdu, int value);
|
int encode_signed(uint8_t * apdu, int value);
|
||||||
int encode_context_signed(uint8_t * apdu,int tag_number, int value);
|
int encode_context_signed(uint8_t * apdu, int tag_number, int value);
|
||||||
int decode_signed(uint8_t * apdu_ptr, int *value);
|
int decode_signed(uint8_t * apdu, int *value);
|
||||||
|
|
||||||
// from clause 20.2.11 Encoding of an Enumerated Value
|
// from clause 20.2.11 Encoding of an Enumerated Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int decode_enumerated(uint8_t * apdu, int *value);
|
int decode_enumerated(uint8_t * apdu, int *value);
|
||||||
int encode_bacnet_enumerated(uint8_t * apdu, unsigned int value);
|
int encode_bacnet_enumerated(uint8_t * apdu, int value);
|
||||||
int encode_enumerated(uint8_t *apdu, int value);
|
int encode_enumerated(uint8_t * apdu, int value);
|
||||||
int encode_context_enumerated(uint8_t * apdu,int tag_number,
|
int encode_context_enumerated(uint8_t * apdu, int tag_number, int value);
|
||||||
unsigned int value);
|
|
||||||
|
|
||||||
// from clause 20.2.13 Encoding of a Time Value
|
// from clause 20.2.13 Encoding of a Time Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_time(uint8_t *apdu,int hour, int min, int sec,
|
int encode_bacnet_time(uint8_t * apdu, int hour, int min, int sec,
|
||||||
int hundredths);
|
int hundredths);
|
||||||
int encode_time(uint8_t *apdu,int hour, int min, int sec, int hundredths);
|
int encode_time(uint8_t * apdu, int hour, int min, int sec,
|
||||||
int decode_bacnet_time(uint8_t *apdu, int *hour, int *min, int *sec,
|
int hundredths);
|
||||||
|
int decode_bacnet_time(uint8_t * apdu, int *hour, int *min, int *sec,
|
||||||
int *hundredths);
|
int *hundredths);
|
||||||
|
|
||||||
// BACnet Date
|
// BACnet Date
|
||||||
@@ -151,8 +131,10 @@ int decode_bacnet_time(uint8_t *apdu, int *hour, int *min, int *sec,
|
|||||||
// from clause 20.2.12 Encoding of a Date Value
|
// from clause 20.2.12 Encoding of a Date Value
|
||||||
// and 20.2.1 General Rules for Encoding BACnet Tags
|
// and 20.2.1 General Rules for Encoding BACnet Tags
|
||||||
// returns the number of apdu bytes consumed
|
// returns the number of apdu bytes consumed
|
||||||
int encode_bacnet_date(uint8_t *apdu, int year, int month, int day, int wday);
|
int encode_bacnet_date(uint8_t * apdu, int year, int month, int day,
|
||||||
int encode_date(uint8_t *apdu, int year, int month, int day, int wday);
|
int wday);
|
||||||
int decode_date(uint8_t *apdu, int *year, int *month, int *day, int *wday);
|
int encode_date(uint8_t * apdu, int year, int month, int day, int wday);
|
||||||
|
int decode_date(uint8_t * apdu, int *year, int *month, int *day,
|
||||||
|
int *wday);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#Makefile to build unit tests
|
||||||
|
CC = gcc
|
||||||
|
BASEDIR = .
|
||||||
|
CFLAGS = -Wall -I. -Itest -g -DTEST -DTEST_DECODE
|
||||||
|
|
||||||
|
TARGET = bacdcode
|
||||||
|
|
||||||
|
SRCS = bacdcode.c \
|
||||||
|
bigend.c \
|
||||||
|
test/ctest.c
|
||||||
|
|
||||||
|
OBJS = ${SRCS:.c=.o}
|
||||||
|
|
||||||
|
all: ${TARGET}
|
||||||
|
|
||||||
|
${TARGET}: ${OBJS}
|
||||||
|
${CC} -o $@ ${OBJS}
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
${CC} -c ${CFLAGS} $*.c -o $@
|
||||||
|
|
||||||
|
depend:
|
||||||
|
rm -f .depend
|
||||||
|
${CC} -MM ${CFLAGS} *.c >> .depend
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf core ${OBJS} ${TARGET} *.bak
|
||||||
|
|
||||||
|
include: .depend
|
||||||
+41
-32
@@ -186,9 +186,6 @@ typedef enum
|
|||||||
PROP_MAXIMUM_VALUE_TIMESTAMP = 149,
|
PROP_MAXIMUM_VALUE_TIMESTAMP = 149,
|
||||||
PROP_MINIMUM_VALUE_TIMESTAMP = 150,
|
PROP_MINIMUM_VALUE_TIMESTAMP = 150,
|
||||||
PROP_VARIANCE_VALUE = 151,
|
PROP_VARIANCE_VALUE = 151,
|
||||||
PROP_MAXIMUM_VALUE_TIMESTAMP = 149,
|
|
||||||
PROP_MINIMUM_VALUE_TIMESTAMP = 150,
|
|
||||||
PROP_VARIANCE_VALUE = 151,
|
|
||||||
PROP_ACTIVE_COV_SUBSCRIPTIONS = 152,
|
PROP_ACTIVE_COV_SUBSCRIPTIONS = 152,
|
||||||
PROP_BACKUP_FAILURE_TIMEOUT = 153,
|
PROP_BACKUP_FAILURE_TIMEOUT = 153,
|
||||||
PROP_CONFIGURATION_FILES = 154,
|
PROP_CONFIGURATION_FILES = 154,
|
||||||
@@ -476,7 +473,7 @@ typedef enum
|
|||||||
LIFE_SAFETY_MODE_DISCONNECTED = 10,
|
LIFE_SAFETY_MODE_DISCONNECTED = 10,
|
||||||
LIFE_SAFETY_MODE_ENABLED = 11,
|
LIFE_SAFETY_MODE_ENABLED = 11,
|
||||||
LIFE_SAFETY_MODE_DISABLED = 12,
|
LIFE_SAFETY_MODE_DISABLED = 12,
|
||||||
LIFE_SAFETY_MODE_AUTOMATIC-RELEASE-DISABLED = 13,
|
LIFE_SAFETY_MODE_AUTOMATIC_RELEASE_DISABLED = 13,
|
||||||
LIFE_SAFETY_MODE_DEFAULT = 14,
|
LIFE_SAFETY_MODE_DEFAULT = 14,
|
||||||
// Enumerated values 0-255 are reserved for definition by ASHRAE.
|
// Enumerated values 0-255 are reserved for definition by ASHRAE.
|
||||||
// Enumerated values 256-65535 may be used by others subject to
|
// Enumerated values 256-65535 may be used by others subject to
|
||||||
@@ -608,18 +605,30 @@ typedef enum
|
|||||||
CHARACTER_ISO8859 = 5,
|
CHARACTER_ISO8859 = 5,
|
||||||
} BACNET_CHARACTER_STRING;
|
} BACNET_CHARACTER_STRING;
|
||||||
|
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
BACNET_APPLICATION_TAG_NULL = 0,
|
||||||
SERVICE_SUBSCRIBE_COV = 5,
|
BACNET_APPLICATION_TAG_BOOLEAN = 1,
|
||||||
SERVICE_READ_PROPERTY = 12,
|
BACNET_APPLICATION_TAG_UNSIGNED_INT = 2,
|
||||||
SERVICE_WRITE_PROPERTY = 15,
|
BACNET_APPLICATION_TAG_SIGNED_INT = 3,
|
||||||
} BACNET_SERVICE_IDENTIFIER;
|
BACNET_APPLICATION_TAG_REAL = 4,
|
||||||
|
BACNET_APPLICATION_TAG_DOUBLE = 5,
|
||||||
|
BACNET_APPLICATION_TAG_OCTET_STRING = 6,
|
||||||
|
BACNET_APPLICATION_TAG_CHARACTER_STRING = 7,
|
||||||
|
BACNET_APPLICATION_TAG_BIT_STRING = 8,
|
||||||
|
BACNET_APPLICATION_TAG_ENUMERATED = 9,
|
||||||
|
BACNET_APPLICATION_TAG_DATE = 10,
|
||||||
|
BACNET_APPLICATION_TAG_TIME = 11,
|
||||||
|
BACNET_APPLICATION_TAG_OBJECT_ID = 12,
|
||||||
|
BACNET_APPLICATION_TAG_RESERVED1 = 13,
|
||||||
|
BACNET_APPLICATION_TAG_RESERVED2 = 14,
|
||||||
|
BACNET_APPLICATION_TAG_RESERVED3 = 15,
|
||||||
|
} BACNET_APPLICATION_TAG;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
// Alarm and Event Services
|
// Alarm and Event Services
|
||||||
SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM = 0,
|
SERVICE_CONFIRMED_ACKNOWLEDGE_ALARM = 0,
|
||||||
SERVICE_CONFIRMED_COV_NOTIFICATION (1),
|
SERVICE_CONFIRMED_COV_NOTIFICATION = 1,
|
||||||
SERVICE_CONFIRMED_EVENT_NOTIFICATION = 2,
|
SERVICE_CONFIRMED_EVENT_NOTIFICATION = 2,
|
||||||
SERVICE_CONFIRMED_GET_ALARM_SUMMARY = 3,
|
SERVICE_CONFIRMED_GET_ALARM_SUMMARY = 3,
|
||||||
SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY = 4,
|
SERVICE_CONFIRMED_GET_ENROLLMENT_SUMMARY = 4,
|
||||||
@@ -700,11 +709,11 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
RELATION_SPECIFIER_EQUAL = 0,
|
RELATION_SPECIFIER_EQUAL = 0,
|
||||||
RELATION_SPECIFIER_NOT-EQUAL = 1,
|
RELATION_SPECIFIER_NOT_EQUAL = 1,
|
||||||
RELATION_SPECIFIER_LESS-THAN = 2,
|
RELATION_SPECIFIER_LESS_THAN = 2,
|
||||||
RELATION_SPECIFIER_GREATER-THAN = 3,
|
RELATION_SPECIFIER_GREATER_THAN = 3,
|
||||||
RELATION_SPECIFIER_LESS-THAN-OR-EQUAL = 4,
|
RELATION_SPECIFIER_LESS_THAN_OR_EQUAL = 4,
|
||||||
RELATION_SPECIFIER_GREATER-THAN-OR-EQUAL = 5
|
RELATION_SPECIFIER_GREATER_THAN_OR_EQUAL = 5
|
||||||
} BACNET_RELATION_SPECIFIER;
|
} BACNET_RELATION_SPECIFIER;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -729,26 +738,26 @@ typedef enum {
|
|||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ABORT_REASON_OTHER = 0,
|
ABORT_REASON_OTHER = 0,
|
||||||
ABORT_REASON_BUFFER-OVERFLOW = 1,
|
ABORT_REASON_BUFFER_OVERFLOW = 1,
|
||||||
ABORT_REASON_INVALID-APDU-IN-THIS-STATE = 2,
|
ABORT_REASON_INVALID_APDU_IN_THIS_STATE = 2,
|
||||||
ABORT_REASON_PREEMPTED-BY-HIGHER-PRIORITY-TASK = 3,
|
ABORT_REASON_PREEMPTED_BY_HIGHER_PRIORITY_TASK = 3,
|
||||||
ABORT_REASON_SEGMENTATION-NOT-SUPPORTED = 4,
|
ABORT_REASON_SEGMENTATION_NOT_SUPPORTED = 4,
|
||||||
// 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.
|
||||||
} BACNET_ABORT_REASON;
|
} BACNET_ABORT_REASON;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OTHER = 0,
|
REJECT_REASON_OTHER = 0,
|
||||||
BUFFER-OVERFLOW = 1,
|
REJECT_REASON_BUFFER_OVERFLOW = 1,
|
||||||
INCONSISTENT-PARAMETERS = 2,
|
REJECT_REASON_INCONSISTENT_PARAMETERS = 2,
|
||||||
INVALID-PARAMETER-DATA-TYPE = 3,
|
REJECT_REASON_INVALID_PARAMETER_DATA_TYPE = 3,
|
||||||
INVALID-TAG = 4,
|
REJECT_REASON_INVALID_TAG = 4,
|
||||||
MISSING-REQUIRED-PARAMETER = 5,
|
REJECT_REASON_MISSING_REQUIRED_PARAMETER = 5,
|
||||||
PARAMETER-OUT-OF-RANGE = 6,
|
REJECT_REASON_PARAMETER_OUT_OF_RANGE = 6,
|
||||||
TOO-MANY-ARGUMENTS = 7,
|
REJECT_REASON_TOO_MANY_ARGUMENTS = 7,
|
||||||
UNDEFINED-ENUMERATION = 8,
|
REJECT_REASON_UNDEFINED_ENUMERATION = 8,
|
||||||
UNRECOGNIZED-SERVICE = 9,
|
REJECT_REASON_UNRECOGNIZED_SERVICE = 9,
|
||||||
// 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.
|
||||||
@@ -796,7 +805,7 @@ typedef enum {
|
|||||||
ERROR_CODE_OBJECT_DELETION_NOT_PERMITTED = 23,
|
ERROR_CODE_OBJECT_DELETION_NOT_PERMITTED = 23,
|
||||||
ERROR_CODE_OBJECT_IDENTIFIER_ALREADY_EXISTS = 24,
|
ERROR_CODE_OBJECT_IDENTIFIER_ALREADY_EXISTS = 24,
|
||||||
ERROR_CODE_OPERATIONAL_PROBLEM = 25,
|
ERROR_CODE_OPERATIONAL_PROBLEM = 25,
|
||||||
ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED, = 45,
|
ERROR_CODE_OPTIONAL_FUNCTIONALITY_NOT_SUPPORTED = 45,
|
||||||
ERROR_CODE_PASSWORD_FAILURE = 26,
|
ERROR_CODE_PASSWORD_FAILURE = 26,
|
||||||
ERROR_CODE_PROPERTY_IS_NOT_A_LIST = 22,
|
ERROR_CODE_PROPERTY_IS_NOT_A_LIST = 22,
|
||||||
ERROR_CODE_READ_ACCESS_DENIED = 27,
|
ERROR_CODE_READ_ACCESS_DENIED = 27,
|
||||||
@@ -805,7 +814,7 @@ typedef enum {
|
|||||||
ERROR_CODE_TIMEOUT = 30,
|
ERROR_CODE_TIMEOUT = 30,
|
||||||
ERROR_CODE_UNKNOWN_OBJECT = 31,
|
ERROR_CODE_UNKNOWN_OBJECT = 31,
|
||||||
ERROR_CODE_UNKNOWN_PROPERTY = 32,
|
ERROR_CODE_UNKNOWN_PROPERTY = 32,
|
||||||
// this enumeration was removed = 33,
|
ERROR_CODE_RESERVED1 = 33,
|
||||||
ERROR_CODE_UNKNOWN_VT_CLASS = 34,
|
ERROR_CODE_UNKNOWN_VT_CLASS = 34,
|
||||||
ERROR_CODE_UNKNOWN_VT_SESSION = 35,
|
ERROR_CODE_UNKNOWN_VT_SESSION = 35,
|
||||||
ERROR_CODE_UNSUPPORTED_OBJECT_TYPE = 36,
|
ERROR_CODE_UNSUPPORTED_OBJECT_TYPE = 36,
|
||||||
|
|||||||
@@ -19,4 +19,8 @@ make -f mstp.mak
|
|||||||
./mstp >> test.log
|
./mstp >> test.log
|
||||||
make -f mstp.mak clean
|
make -f mstp.mak clean
|
||||||
|
|
||||||
|
make -f bacdcode.mak clean
|
||||||
|
make -f bacdcode.mak
|
||||||
|
./mstp >> test.log
|
||||||
|
make -f bacdcode.mak clean
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user