refactored the application tagged encode and decode, and created types for character and octet strings.
This commit is contained in:
+1
-26
@@ -37,32 +37,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include "bacdef.h"
|
||||||
// bit strings
|
|
||||||
#define MAX_BITSTRING_BYTES 15
|
|
||||||
typedef struct BACnet_Bit_String
|
|
||||||
{
|
|
||||||
uint8_t bits_used;
|
|
||||||
uint8_t value[MAX_BITSTRING_BYTES];
|
|
||||||
} BACNET_BIT_STRING;
|
|
||||||
|
|
||||||
// date
|
|
||||||
typedef struct BACnet_Date
|
|
||||||
{
|
|
||||||
uint8_t year;
|
|
||||||
uint8_t month;
|
|
||||||
uint8_t day;
|
|
||||||
uint8_t wday;
|
|
||||||
} BACNET_DATE;
|
|
||||||
|
|
||||||
// time
|
|
||||||
typedef struct BACnet_Time
|
|
||||||
{
|
|
||||||
uint8_t hour;
|
|
||||||
uint8_t min;
|
|
||||||
uint8_t sec;
|
|
||||||
uint8_t hundredths;
|
|
||||||
} BACNET_TIME;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -80,6 +80,51 @@ struct BACnet_Device_Address {
|
|||||||
};
|
};
|
||||||
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
typedef struct BACnet_Device_Address BACNET_ADDRESS;
|
||||||
|
|
||||||
|
/* bit strings
|
||||||
|
They could be as large as 256/8=32 octets */
|
||||||
|
#define MAX_BITSTRING_BYTES 15
|
||||||
|
typedef struct BACnet_Bit_String
|
||||||
|
{
|
||||||
|
uint8_t bits_used;
|
||||||
|
uint8_t value[MAX_BITSTRING_BYTES];
|
||||||
|
} BACNET_BIT_STRING;
|
||||||
|
|
||||||
|
typedef struct BACnet_Character_String
|
||||||
|
{
|
||||||
|
size_t length;
|
||||||
|
char value[MAX_APDU];
|
||||||
|
} BACNET_CHARACTER_STRING;
|
||||||
|
|
||||||
|
typedef struct BACnet_Octet_String
|
||||||
|
{
|
||||||
|
size_t length;
|
||||||
|
char value[MAX_APDU];
|
||||||
|
} BACNET_OCTET_STRING;
|
||||||
|
|
||||||
|
/* date */
|
||||||
|
typedef struct BACnet_Date
|
||||||
|
{
|
||||||
|
uint8_t year;
|
||||||
|
uint8_t month;
|
||||||
|
uint8_t day;
|
||||||
|
uint8_t wday;
|
||||||
|
} BACNET_DATE;
|
||||||
|
|
||||||
|
/* time */
|
||||||
|
typedef struct BACnet_Time
|
||||||
|
{
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t min;
|
||||||
|
uint8_t sec;
|
||||||
|
uint8_t hundredths;
|
||||||
|
} BACNET_TIME;
|
||||||
|
|
||||||
|
typedef struct BACnet_Object_Id
|
||||||
|
{
|
||||||
|
uint16_t type;
|
||||||
|
uint32_t instance;
|
||||||
|
} BACNET_OBJECT_ID;
|
||||||
|
|
||||||
#define MAX_NPDU (1+1+2+1+MAX_MAC_LEN+2+1+MAX_MAC_LEN+1+1+2)
|
#define MAX_NPDU (1+1+2+1+MAX_MAC_LEN+2+1+MAX_MAC_LEN+1+1+2)
|
||||||
#define MAX_PDU (MAX_APDU + MAX_NPDU)
|
#define MAX_PDU (MAX_APDU + MAX_NPDU)
|
||||||
|
|
||||||
|
|||||||
@@ -735,7 +735,7 @@ typedef enum
|
|||||||
CHARACTER_UCS4 = 3,
|
CHARACTER_UCS4 = 3,
|
||||||
CHARACTER_UCS2 = 4,
|
CHARACTER_UCS2 = 4,
|
||||||
CHARACTER_ISO8859 = 5
|
CHARACTER_ISO8859 = 5
|
||||||
} BACNET_CHARACTER_STRING;
|
} BACNET_CHARACTER_STRING_ENCODING;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BACNET_APPLICATION_TAG_NULL = 0,
|
BACNET_APPLICATION_TAG_NULL = 0,
|
||||||
|
|||||||
+5
-4
@@ -421,6 +421,7 @@ int rpm_ack_decode_object_property(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
*array_index = BACNET_ARRAY_ALL;
|
*array_index = BACNET_ARRAY_ALL;
|
||||||
|
}
|
||||||
|
|
||||||
return (int)len;
|
return (int)len;
|
||||||
}
|
}
|
||||||
@@ -467,12 +468,11 @@ int rpm_ack_decode_object_property_value(
|
|||||||
unsigned len = 0;
|
unsigned len = 0;
|
||||||
|
|
||||||
/* check for valid pointers */
|
/* check for valid pointers */
|
||||||
if (apdu && apdu_len && object_property && array_index)
|
if (apdu && apdu_len && application_data && application_data_len)
|
||||||
{
|
{
|
||||||
// don't decode the application tag number or its data here
|
// don't decode the application tag number or its data here
|
||||||
*application_data = &apdu[len];
|
*application_data = &apdu[len];
|
||||||
*application_data_len = apdu_len - len - 1 /*closing tag*/;
|
*application_data_len = apdu_len - len - 1 /*closing tag*/;
|
||||||
/* FIXME: check for closing tag?*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)len;
|
return (int)len;
|
||||||
@@ -715,10 +715,10 @@ void testReadPropertyMultipleAck(Test * pTest)
|
|||||||
apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
|
apdu_len += rpm_ack_encode_apdu_object_property_value(&apdu[apdu_len],
|
||||||
application_data[2],application_data_len[2]);
|
application_data[2],application_data_len[2]);
|
||||||
/* reply property */
|
/* reply property */
|
||||||
apdu_len = rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
|
apdu_len += rpm_ack_encode_apdu_object_property(&apdu[apdu_len],
|
||||||
PROP_DEADBAND, BACNET_ARRAY_ALL);
|
PROP_DEADBAND, BACNET_ARRAY_ALL);
|
||||||
/* reply error */
|
/* reply error */
|
||||||
apdu_len = rpm_ack_encode_apdu_object_property_error(&apdu[apdu_len],
|
apdu_len += rpm_ack_encode_apdu_object_property_error(&apdu[apdu_len],
|
||||||
ERROR_CLASS_PROPERTY, ERROR_CODE_UNKNOWN_PROPERTY);
|
ERROR_CLASS_PROPERTY, ERROR_CODE_UNKNOWN_PROPERTY);
|
||||||
/* object end */
|
/* object end */
|
||||||
apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]);
|
apdu_len += rpm_ack_encode_apdu_object_end(&apdu[apdu_len]);
|
||||||
@@ -927,5 +927,6 @@ int main(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* TEST_READ_PROPERTY_MULTIPLE */
|
#endif /* TEST_READ_PROPERTY_MULTIPLE */
|
||||||
|
|
||||||
#endif /* TEST */
|
#endif /* TEST */
|
||||||
|
|
||||||
|
|||||||
+13
-131
@@ -63,44 +63,7 @@ int wp_encode_apdu(
|
|||||||
data->array_index);
|
data->array_index);
|
||||||
// propertyValue
|
// propertyValue
|
||||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
|
apdu_len += encode_opening_tag(&apdu[apdu_len], 3);
|
||||||
if (data->value.tag == BACNET_APPLICATION_TAG_NULL)
|
apdu_len += bacapp_encode_application_data(&apdu[apdu_len], &data->value);
|
||||||
apdu[apdu_len++] = data->value.tag;
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_BOOLEAN)
|
|
||||||
apdu_len += encode_tagged_boolean(&apdu[apdu_len],
|
|
||||||
data->value.type.Boolean);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT)
|
|
||||||
apdu_len += encode_tagged_unsigned(&apdu[apdu_len],
|
|
||||||
data->value.type.Unsigned_Int);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_SIGNED_INT)
|
|
||||||
apdu_len += encode_tagged_signed(&apdu[apdu_len],
|
|
||||||
data->value.type.Signed_Int);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_REAL)
|
|
||||||
apdu_len += encode_tagged_real(&apdu[apdu_len],
|
|
||||||
data->value.type.Real);
|
|
||||||
/*
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING)
|
|
||||||
apdu_len += encode_tagged_character_string(
|
|
||||||
&apdu[apdu_len],
|
|
||||||
&data->value.type.Character_String[0]);
|
|
||||||
*/
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_ENUMERATED)
|
|
||||||
apdu_len += encode_tagged_enumerated(&apdu[apdu_len],
|
|
||||||
data->value.type.Enumerated);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_DATE)
|
|
||||||
apdu_len += encode_tagged_date(&apdu[apdu_len],
|
|
||||||
data->value.type.Date.year,
|
|
||||||
data->value.type.Date.month,
|
|
||||||
data->value.type.Date.day,
|
|
||||||
data->value.type.Date.wday);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_TIME)
|
|
||||||
apdu_len += encode_tagged_time(&apdu[apdu_len],
|
|
||||||
data->value.type.Time.hour,
|
|
||||||
data->value.type.Time.min,
|
|
||||||
data->value.type.Time.sec,
|
|
||||||
data->value.type.Time.hundredths);
|
|
||||||
else if (data->value.tag == BACNET_APPLICATION_TAG_OBJECT_ID)
|
|
||||||
apdu_len += encode_tagged_object_id(&apdu[apdu_len],
|
|
||||||
data->value.type.Object_ID.type,data->value.type.Object_ID.instance);
|
|
||||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
|
apdu_len += encode_closing_tag(&apdu[apdu_len], 3);
|
||||||
// optional priority - 0 if not set, 1..16 if set
|
// optional priority - 0 if not set, 1..16 if set
|
||||||
if (data->priority)
|
if (data->priority)
|
||||||
@@ -124,10 +87,6 @@ int wp_decode_service_request(
|
|||||||
int type = 0; // for decoding
|
int type = 0; // for decoding
|
||||||
int property = 0; // for decoding
|
int property = 0; // for decoding
|
||||||
unsigned unsigned_value = 0;
|
unsigned unsigned_value = 0;
|
||||||
int hour, min, sec, hundredths;
|
|
||||||
int year, month, day, wday;
|
|
||||||
int object_type = 0;
|
|
||||||
uint32_t instance = 0;
|
|
||||||
|
|
||||||
// check for value pointers
|
// check for value pointers
|
||||||
if (apdu_len && data)
|
if (apdu_len && data)
|
||||||
@@ -162,87 +121,10 @@ int wp_decode_service_request(
|
|||||||
return -1;
|
return -1;
|
||||||
// a tag number of 3 is not extended so only one octet
|
// a tag number of 3 is not extended so only one octet
|
||||||
len++;
|
len++;
|
||||||
tag_len = decode_tag_number_and_value(&apdu[len],
|
len += bacapp_decode_application_data(
|
||||||
&tag_number, &len_value_type);
|
&apdu[len],
|
||||||
if (tag_len)
|
apdu_len - len,
|
||||||
{
|
&data->value);
|
||||||
len += tag_len;
|
|
||||||
if (tag_number == BACNET_APPLICATION_TAG_NULL)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
data->value.type.Boolean = decode_boolean(len_value_type);
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_unsigned(&apdu[len],
|
|
||||||
len_value_type,
|
|
||||||
&data->value.type.Unsigned_Int);
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_signed(&apdu[len],
|
|
||||||
len_value_type,
|
|
||||||
&data->value.type.Signed_Int);
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_REAL)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_real(&apdu[len],&(data->value.type.Real));
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_character_string(&apdu[len],
|
|
||||||
&data->value.type.Character_String[0],
|
|
||||||
sizeof(data->value.type.Character_String));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_enumerated(&apdu[len],
|
|
||||||
len_value_type,
|
|
||||||
&data->value.type.Enumerated);
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_DATE)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_date(&apdu[len], &year, &month, &day, &wday);
|
|
||||||
data->value.type.Date.year = year;
|
|
||||||
data->value.type.Date.month = month;
|
|
||||||
data->value.type.Date.day = day;
|
|
||||||
data->value.type.Date.wday = wday;
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_TIME)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_bacnet_time(&apdu[len], &hour, &min, &sec, &hundredths);
|
|
||||||
data->value.type.Time.hour = hour;
|
|
||||||
data->value.type.Time.min = min;
|
|
||||||
data->value.type.Time.sec = sec;
|
|
||||||
data->value.type.Time.hundredths = hundredths;
|
|
||||||
}
|
|
||||||
else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID)
|
|
||||||
{
|
|
||||||
data->value.tag = tag_number;
|
|
||||||
len += decode_object_id(&apdu[len],
|
|
||||||
&object_type,
|
|
||||||
&instance);
|
|
||||||
data->value.type.Object_ID.type = object_type;
|
|
||||||
data->value.type.Object_ID.instance = instance;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
if (!decode_is_closing_tag_number(&apdu[len], 3))
|
if (!decode_is_closing_tag_number(&apdu[len], 3))
|
||||||
return -1;
|
return -1;
|
||||||
// a tag number of 3 is not extended so only one octet
|
// a tag number of 3 is not extended so only one octet
|
||||||
@@ -374,10 +256,10 @@ void testWritePropertyTag(Test * pTest,
|
|||||||
data->value.type.Time.hundredths);
|
data->value.type.Time.hundredths);
|
||||||
break;
|
break;
|
||||||
case BACNET_APPLICATION_TAG_OBJECT_ID:
|
case BACNET_APPLICATION_TAG_OBJECT_ID:
|
||||||
ct_test(pTest, test_data.value.type.Object_ID.type ==
|
ct_test(pTest, test_data.value.type.Object_Id.type ==
|
||||||
data->value.type.Object_ID.type);
|
data->value.type.Object_Id.type);
|
||||||
ct_test(pTest, test_data.value.type.Object_ID.instance ==
|
ct_test(pTest, test_data.value.type.Object_Id.instance ==
|
||||||
data->value.type.Object_ID.instance);
|
data->value.type.Object_Id.instance);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -450,11 +332,11 @@ void testWriteProperty(Test * pTest)
|
|||||||
testWritePropertyTag(pTest, &data);
|
testWritePropertyTag(pTest, &data);
|
||||||
|
|
||||||
data.value.tag = BACNET_APPLICATION_TAG_OBJECT_ID;
|
data.value.tag = BACNET_APPLICATION_TAG_OBJECT_ID;
|
||||||
data.value.type.Object_ID.type = OBJECT_ANALOG_INPUT;
|
data.value.type.Object_Id.type = OBJECT_ANALOG_INPUT;
|
||||||
data.value.type.Object_ID.instance = 0;
|
data.value.type.Object_Id.instance = 0;
|
||||||
testWritePropertyTag(pTest, &data);
|
testWritePropertyTag(pTest, &data);
|
||||||
data.value.type.Object_ID.type = OBJECT_LIFE_SAFETY_ZONE;
|
data.value.type.Object_Id.type = OBJECT_LIFE_SAFETY_ZONE;
|
||||||
data.value.type.Object_ID.instance = BACNET_MAX_INSTANCE;
|
data.value.type.Object_Id.instance = BACNET_MAX_INSTANCE;
|
||||||
testWritePropertyTag(pTest, &data);
|
testWritePropertyTag(pTest, &data);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
+2
-28
@@ -37,33 +37,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "bacdcode.h"
|
#include "bacdcode.h"
|
||||||
|
#include "bacapp.h"
|
||||||
typedef struct BACnet_Write_Property_Value
|
|
||||||
{
|
|
||||||
uint8_t tag;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
// NULL - not needed as it is encoded in the tag alone
|
|
||||||
bool Boolean;
|
|
||||||
unsigned Unsigned_Int;
|
|
||||||
int Signed_Int;
|
|
||||||
float Real;
|
|
||||||
// Note: if you choose to enable the writing of certain types
|
|
||||||
// you can uncomment the ones you need. Good Luck!
|
|
||||||
//double Double;
|
|
||||||
//uint8_t Octet_String[20];
|
|
||||||
//char Character_String[20];
|
|
||||||
//BACNET_BIT_STRING Bit_String
|
|
||||||
int Enumerated;
|
|
||||||
BACNET_DATE Date;
|
|
||||||
BACNET_TIME Time;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint16_t type;
|
|
||||||
uint32_t instance;
|
|
||||||
} Object_ID;
|
|
||||||
} type;
|
|
||||||
} BACNET_WRITE_PROPERTY_VALUE;
|
|
||||||
|
|
||||||
typedef struct BACnet_Write_Property_Data
|
typedef struct BACnet_Write_Property_Data
|
||||||
{
|
{
|
||||||
@@ -71,7 +45,7 @@ typedef struct BACnet_Write_Property_Data
|
|||||||
uint32_t object_instance;
|
uint32_t object_instance;
|
||||||
BACNET_PROPERTY_ID object_property;
|
BACNET_PROPERTY_ID object_property;
|
||||||
int32_t array_index; // use BACNET_ARRAY_ALL when not setting
|
int32_t array_index; // use BACNET_ARRAY_ALL when not setting
|
||||||
BACNET_WRITE_PROPERTY_VALUE value;
|
BACNET_APPLICATION_DATA_VALUE value;
|
||||||
uint8_t priority; // use 0 if not setting the priority
|
uint8_t priority; // use 0 if not setting the priority
|
||||||
} BACNET_WRITE_PROPERTY_DATA;
|
} BACNET_WRITE_PROPERTY_DATA;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ CFLAGS = -Wall -I. -Itest -DTEST -DTEST_WRITE_PROPERTY -DBACDL_BIP=1 -g
|
|||||||
|
|
||||||
SRCS = bacdcode.c \
|
SRCS = bacdcode.c \
|
||||||
bigend.c \
|
bigend.c \
|
||||||
|
bacapp.c \
|
||||||
wp.c \
|
wp.c \
|
||||||
test/ctest.c
|
test/ctest.c
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user