Enhanced the WriteProperty service demo to allow multiple tagged data elements and to allow context data.

This commit is contained in:
skarg
2007-02-20 20:56:08 +00:00
parent 2fed6fcf3b
commit b3d15b1f37
10 changed files with 760 additions and 472 deletions
+283 -103
View File
@@ -110,6 +110,77 @@ int bacapp_encode_application_data(uint8_t * apdu,
return apdu_len; return apdu_len;
} }
/* decode the data and store it into value.
Return the number of octets consumed. */
int bacapp_decode_data(uint8_t * apdu,
uint8_t tag_data_type,
uint32_t len_value_type,
BACNET_APPLICATION_DATA_VALUE * value)
{
int len = 0;
int object_type = 0;
uint32_t instance = 0;
if (apdu && value) {
switch (tag_data_type) {
case BACNET_APPLICATION_TAG_NULL:
/* nothing else to do */
break;
case BACNET_APPLICATION_TAG_BOOLEAN:
value->type.Boolean = decode_boolean(len_value_type);
break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
len = decode_unsigned(&apdu[0],
len_value_type, &value->type.Unsigned_Int);
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
len = decode_signed(&apdu[0],
len_value_type, &value->type.Signed_Int);
break;
case BACNET_APPLICATION_TAG_REAL:
len = decode_real(&apdu[0], &(value->type.Real));
break;
#if 0
case BACNET_APPLICATION_TAG_DOUBLE:
len = decode_double(&apdu[0], &(value->type.Double));
break;
#endif
case BACNET_APPLICATION_TAG_ENUMERATED:
len = decode_enumerated(&apdu[0],
len_value_type, &value->type.Enumerated);
break;
case BACNET_APPLICATION_TAG_DATE:
len = decode_date(&apdu[0], &value->type.Date);
break;
case BACNET_APPLICATION_TAG_TIME:
len = decode_bacnet_time(&apdu[0], &value->type.Time);
break;
case BACNET_APPLICATION_TAG_OBJECT_ID:
len = decode_object_id(&apdu[0],
&object_type, &instance);
value->type.Object_Id.type = object_type;
value->type.Object_Id.instance = instance;
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
len = decode_octet_string(&apdu[0],
len_value_type, &value->type.Octet_String);
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len = decode_character_string(&apdu[0],
len_value_type, &value->type.Character_String);
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
len = decode_bitstring(&apdu[0],
len_value_type, &value->type.Bit_String);
break;
default:
break;
}
}
return len;
}
int bacapp_decode_application_data(uint8_t * apdu, int bacapp_decode_application_data(uint8_t * apdu,
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value) int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value)
{ {
@@ -117,132 +188,239 @@ int bacapp_decode_application_data(uint8_t * apdu,
int tag_len = 0; int tag_len = 0;
uint8_t tag_number = 0; uint8_t tag_number = 0;
uint32_t len_value_type = 0; uint32_t len_value_type = 0;
/* FIXME: use max_apdu_len! */
(void) max_apdu_len;
if (apdu && value && !decode_is_context_specific(apdu)) {
value->context_specific = false;
tag_len = decode_tag_number_and_value(&apdu[0],
&tag_number, &len_value_type);
if (tag_len) {
len += tag_len;
value->tag = tag_number;
len += bacapp_decode_data(&apdu[len],
tag_number,
len_value_type,
value);
}
value->next = NULL;
}
return len;
}
int bacapp_encode_context_data_value(uint8_t * apdu, uint8_t context_tag_number,
BACNET_APPLICATION_DATA_VALUE * value)
{
int apdu_len = 0; /* total length of the apdu, return value */
if (value && apdu) {
switch (value->tag) {
case BACNET_APPLICATION_TAG_NULL:
apdu_len = encode_context_null(&apdu[0], context_tag_number);
break;
case BACNET_APPLICATION_TAG_BOOLEAN:
apdu_len = encode_context_boolean(&apdu[0], context_tag_number,
value->type.Boolean);
break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
apdu_len = encode_context_unsigned(&apdu[0], context_tag_number,
value->type.Unsigned_Int);
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
apdu_len = encode_context_signed(&apdu[0], context_tag_number,
value->type.Signed_Int);
break;
case BACNET_APPLICATION_TAG_REAL:
apdu_len = encode_context_real(&apdu[0], context_tag_number,
value->type.Real);
break;
case BACNET_APPLICATION_TAG_ENUMERATED:
apdu_len = encode_context_enumerated(&apdu[0], context_tag_number,
value->type.Enumerated);
break;
case BACNET_APPLICATION_TAG_DATE:
apdu_len = encode_context_date(&apdu[0], context_tag_number,
&value->type.Date);
break;
case BACNET_APPLICATION_TAG_TIME:
apdu_len = encode_context_time(&apdu[0], context_tag_number,
&value->type.Time);
break;
case BACNET_APPLICATION_TAG_OBJECT_ID:
apdu_len = encode_context_object_id(&apdu[0], context_tag_number,
value->type.Object_Id.type,
value->type.Object_Id.instance);
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
apdu_len = encode_context_octet_string(&apdu[0], context_tag_number,
&value->type.Octet_String);
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
apdu_len = encode_context_character_string(&apdu[0], context_tag_number,
&value->type.Character_String);
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
apdu_len = encode_context_bitstring(&apdu[0], context_tag_number,
&value->type.Bit_String);
break;
#if 0
case BACNET_APPLICATION_TAG_DOUBLE:
/* FIXME: double is not implemented yet.*/
apdu_len = encode_context_double(&apdu[0], context_tag_number,
value->type.Double);
break;
#endif
default:
break;
}
}
return apdu_len;
}
/* returns the fixed tag type for certain context tagged properties */
BACNET_APPLICATION_TAG bacapp_context_tag_type(
BACNET_PROPERTY_ID property,
uint8_t tag_number)
{
BACNET_APPLICATION_TAG tag = MAX_BACNET_APPLICATION_TAG;
switch (property) {
case PROP_REQUESTED_SHED_LEVEL:
switch (tag_number) {
case 0:
case 1:
tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
break;
case 2:
tag = BACNET_APPLICATION_TAG_REAL;
break;
default:
break;
}
break;
case PROP_ACTION:
switch (tag_number) {
case 0:
case 1:
tag = BACNET_APPLICATION_TAG_OBJECT_ID;
break;
case 2:
tag = BACNET_APPLICATION_TAG_ENUMERATED;
break;
case 3:
case 5:
case 6:
tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
break;
case 7:
case 8:
tag = BACNET_APPLICATION_TAG_BOOLEAN;
break;
case 4: /* propertyValue: abstract syntax */
default:
break;
}
break;
case PROP_EXCEPTION_SCHEDULE:
switch (tag_number) {
case 1:
tag = BACNET_APPLICATION_TAG_OBJECT_ID;
break;
case 3:
tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
break;
case 0: /* calendarEntry: abstract syntax + context */
case 2: /* list of BACnetTimeValue: abstract syntax */
default:
break;
}
break;
default:
break;
}
return tag;
}
int bacapp_encode_context_data(uint8_t * apdu,
BACNET_APPLICATION_DATA_VALUE * value,
BACNET_PROPERTY_ID property)
{
int apdu_len = 0;
BACNET_APPLICATION_TAG tag_data_type;
if (value && apdu) {
tag_data_type = bacapp_context_tag_type(property, value->context_tag);
if (tag_data_type < MAX_BACNET_APPLICATION_TAG) {
apdu_len = bacapp_encode_context_data_value(&apdu[0],
value->context_tag, value);
} else {
/* FIXME: what now? */
apdu_len = 0;
}
value->next = NULL;
}
return apdu_len;
}
int bacapp_decode_context_data(uint8_t * apdu,
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value,
BACNET_PROPERTY_ID property)
{
int apdu_len = 0, len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
int object_type = 0; int object_type = 0;
uint32_t instance = 0; uint32_t instance = 0;
/* FIXME: use max_apdu_len! */ /* FIXME: use max_apdu_len! */
(void) max_apdu_len; (void) max_apdu_len;
if (apdu && !decode_is_context_specific(apdu)) { if (apdu && value && decode_is_context_specific(apdu)) {
value->context_specific = true;
tag_len = decode_tag_number_and_value(&apdu[0], tag_len = decode_tag_number_and_value(&apdu[0],
&tag_number, &len_value_type); &tag_number, &len_value_type);
if (tag_len) { if (tag_len) {
len += tag_len; apdu_len = tag_len;
value->tag = tag_number; value->context_tag = tag_number;
if (tag_number == BACNET_APPLICATION_TAG_NULL) { value->tag = bacapp_context_tag_type(property, tag_number);
/* nothing else to do */ if (value->tag < MAX_BACNET_APPLICATION_TAG) {
} else if (tag_number == BACNET_APPLICATION_TAG_BOOLEAN) len = bacapp_decode_data(&apdu[apdu_len],
value->type.Boolean = decode_boolean(len_value_type); value->tag,
else if (tag_number == BACNET_APPLICATION_TAG_UNSIGNED_INT) len_value_type,
len += decode_unsigned(&apdu[len], value);
len_value_type, &value->type.Unsigned_Int); apdu_len += len;
else if (tag_number == BACNET_APPLICATION_TAG_SIGNED_INT) } else {
len += decode_signed(&apdu[len], /* FIXME: what now? */
len_value_type, &value->type.Signed_Int); apdu_len = 0;
else if (tag_number == BACNET_APPLICATION_TAG_REAL)
len += decode_real(&apdu[len], &(value->type.Real));
#if 0
else if (tag_number == BACNET_APPLICATION_TAG_DOUBLE)
len += decode_double(&apdu[len], &(value->type.Double));
#endif
else if (tag_number == BACNET_APPLICATION_TAG_OCTET_STRING)
len += decode_octet_string(&apdu[len],
len_value_type, &value->type.Octet_String);
else if (tag_number == BACNET_APPLICATION_TAG_CHARACTER_STRING)
len += decode_character_string(&apdu[len],
len_value_type, &value->type.Character_String);
else if (tag_number == BACNET_APPLICATION_TAG_BIT_STRING)
len += decode_bitstring(&apdu[len],
len_value_type, &value->type.Bit_String);
else if (tag_number == BACNET_APPLICATION_TAG_ENUMERATED)
len += decode_enumerated(&apdu[len],
len_value_type, &value->type.Enumerated);
else if (tag_number == BACNET_APPLICATION_TAG_DATE)
len += decode_date(&apdu[len], &value->type.Date);
else if (tag_number == BACNET_APPLICATION_TAG_TIME)
len += decode_bacnet_time(&apdu[len], &value->type.Time);
else if (tag_number == BACNET_APPLICATION_TAG_OBJECT_ID) {
len += decode_object_id(&apdu[len],
&object_type, &instance);
value->type.Object_Id.type = object_type;
value->type.Object_Id.instance = instance;
} }
} }
value->next = NULL;
} }
return len; return apdu_len;
} }
int bacapp_encode_context_data(uint8_t * apdu, int bacapp_encode_data(uint8_t * apdu,
BACNET_APPLICATION_DATA_VALUE * value, BACNET_PROPERTY_ID property) BACNET_APPLICATION_DATA_VALUE * value)
{ {
int apdu_len = 0; /* total length of the apdu, return value */ int apdu_len = 0; /* total length of the apdu, return value */
if (value && apdu) { if (value && apdu) {
switch (property) { if (value->context_specific) {
case PROP_REQUESTED_SHED_LEVEL: apdu_len = bacapp_encode_context_data_value(&apdu[0],
switch (value->tag) { value->context_tag, value);
case 0: } else {
case 1: apdu_len = bacapp_encode_application_data(&apdu[0], value);
apdu_len = encode_tagged_unsigned(&apdu[0],
value->type.Unsigned_Int);
break;
case 2:
apdu_len = encode_tagged_real(&apdu[0], value->type.Real);
break;
default:
apdu_len = 0;
break;
}
break;
default:
break;
} }
} }
return apdu_len; return apdu_len;
} }
int bacapp_decode_context_data(uint8_t * apdu,
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value,
BACNET_PROPERTY_ID property)
{
int len = 0;
int tag_len = 0;
uint8_t tag_number = 0;
uint32_t len_value_type = 0;
/* FIXME: use max_apdu_len! */
(void) max_apdu_len;
if (apdu && decode_is_context_specific(apdu)) {
tag_len = decode_tag_number_and_value(&apdu[0],
&tag_number, &len_value_type);
if (tag_len) {
len += tag_len;
value->tag = tag_number;
switch (property) {
case PROP_REQUESTED_SHED_LEVEL:
switch (tag_number) {
case 0:
case 1:
len += decode_unsigned(&apdu[len],
len_value_type, &(value->type.Unsigned_Int));
break;
case 2:
len += decode_real(&apdu[len], &(value->type.Real));
break;
default:
len = 0;
break;
}
break;
default:
break;
}
}
}
return len;
}
bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value, bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
BACNET_APPLICATION_DATA_VALUE * src_value) BACNET_APPLICATION_DATA_VALUE * src_value)
@@ -299,6 +477,7 @@ bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
status = false; status = false;
break; break;
} }
dest_value->next = src_value->next;
} }
return status; return status;
@@ -574,6 +753,7 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
} else } else
status = false; status = false;
} }
value->next = NULL;
} }
return status; return status;
+16 -2
View File
@@ -41,8 +41,11 @@
#include "bacstr.h" #include "bacstr.h"
#include "datetime.h" #include "datetime.h"
struct BACnet_Application_Data_Value;
typedef struct BACnet_Application_Data_Value { typedef struct BACnet_Application_Data_Value {
uint8_t tag; /* application or context-specific number */ bool context_specific; /* true if context specific data */
uint8_t context_tag; /* only used for context specific data */
uint8_t tag; /* application tag data type */
union { union {
/* NULL - not needed as it is encoded in the tag alone */ /* NULL - not needed as it is encoded in the tag alone */
bool Boolean; bool Boolean;
@@ -58,11 +61,15 @@ typedef struct BACnet_Application_Data_Value {
BACNET_TIME Time; BACNET_TIME Time;
BACNET_OBJECT_ID Object_Id; BACNET_OBJECT_ID Object_Id;
} type; } type;
/* simple linked list if needed */
struct BACnet_Application_Data_Value *next;
} BACNET_APPLICATION_DATA_VALUE; } BACNET_APPLICATION_DATA_VALUE;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
int bacapp_encode_data(uint8_t * apdu,
BACNET_APPLICATION_DATA_VALUE * value);
int bacapp_decode_application_data(uint8_t * apdu, int bacapp_decode_application_data(uint8_t * apdu,
int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value); int max_apdu_len, BACNET_APPLICATION_DATA_VALUE * value);
@@ -78,6 +85,14 @@ extern "C" {
BACNET_APPLICATION_DATA_VALUE * value, BACNET_APPLICATION_DATA_VALUE * value,
BACNET_PROPERTY_ID property); BACNET_PROPERTY_ID property);
int bacapp_encode_context_data_value(uint8_t * apdu,
uint8_t context_tag_number,
BACNET_APPLICATION_DATA_VALUE * value);
BACNET_APPLICATION_TAG bacapp_context_tag_type(
BACNET_PROPERTY_ID property,
uint8_t tag_number);
bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value, bool bacapp_copy(BACNET_APPLICATION_DATA_VALUE * dest_value,
BACNET_APPLICATION_DATA_VALUE * src_value); BACNET_APPLICATION_DATA_VALUE * src_value);
@@ -99,7 +114,6 @@ extern "C" {
#ifdef BACAPP_PRINT_ENABLED #ifdef BACAPP_PRINT_ENABLED
bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number, bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
const char *argv, BACNET_APPLICATION_DATA_VALUE * value); const char *argv, BACNET_APPLICATION_DATA_VALUE * value);
bool bacapp_print_value(FILE * stream, bool bacapp_print_value(FILE * stream,
BACNET_APPLICATION_DATA_VALUE * value, BACNET_APPLICATION_DATA_VALUE * value,
BACNET_PROPERTY_ID property); BACNET_PROPERTY_ID property);
+38 -7
View File
@@ -734,14 +734,11 @@ int encode_tagged_boolean(uint8_t * apdu, bool boolean_value)
int encode_context_boolean(uint8_t * apdu, int tag_number, int encode_context_boolean(uint8_t * apdu, int tag_number,
bool boolean_value) bool boolean_value)
{ {
int len = 1; /* return value */ int len = 0; /* return value */
apdu[1] = boolean_value ? 1 : 0; len = encode_tag(&apdu[0], (uint8_t) tag_number, true, 1);
/* we only reserved 1 byte for encoding the tag - check the limits */ apdu[len] = boolean_value ? 1 : 0;
if (tag_number <= 14) len++;
len += encode_tag(&apdu[0], (uint8_t) tag_number, true, 1);
else
len = 0;
return len; return len;
} }
@@ -777,6 +774,11 @@ int encode_tagged_null(uint8_t * apdu)
return encode_tag(&apdu[0], BACNET_APPLICATION_TAG_NULL, false, 0); return encode_tag(&apdu[0], BACNET_APPLICATION_TAG_NULL, false, 0);
} }
int encode_context_null(uint8_t * apdu, int tag_number)
{
return encode_tag(&apdu[0], tag_number, true, 0);
}
static uint8_t byte_reverse_bits(uint8_t in_byte) static uint8_t byte_reverse_bits(uint8_t in_byte)
{ {
uint8_t out_byte = 0; uint8_t out_byte = 0;
@@ -872,6 +874,20 @@ int encode_tagged_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string)
return len; return len;
} }
int encode_context_bitstring(uint8_t * apdu, int tag_number,
BACNET_BIT_STRING * bit_string)
{
int len = 0;
int bit_string_encoded_length = 1; /* 1 for the bits remaining octet */
/* bit string may use more than 1 octet for the tag, so find out how many */
bit_string_encoded_length += bitstring_bytes_used(bit_string);
len = encode_tag(&apdu[0], tag_number, true, bit_string_encoded_length);
len += encode_bitstring(&apdu[len], bit_string);
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)
@@ -1429,7 +1445,22 @@ int encode_tagged_time(uint8_t * apdu, BACNET_TIME * btime)
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;
}
int encode_context_time(uint8_t * apdu, int tag_number,
BACNET_TIME * btime)
{
int len = 0; /* return value */
/* assumes that the tag only consumes 1 octet */
len = encode_bacnet_time(&apdu[1], btime);
/* we only reserved 1 byte for encoding the tag - check the limits */
if ((tag_number <= 14) && (len <= 4))
len += encode_tag(&apdu[0], (uint8_t) tag_number, true, len);
else
len = 0;
return len;
} }
/* from clause 20.2.13 Encoding of a Time Value */ /* from clause 20.2.13 Encoding of a Time Value */
+5
View File
@@ -72,6 +72,7 @@ extern "C" {
/* from clause 20.2.2 Encoding of a Null Value */ /* from clause 20.2.2 Encoding of a Null Value */
int encode_tagged_null(uint8_t * apdu); int encode_tagged_null(uint8_t * apdu);
int encode_context_null(uint8_t * apdu, int tag_number);
/* from clause 20.2.3 Encoding of a Boolean Value */ /* from clause 20.2.3 Encoding of a Boolean Value */
int encode_tagged_boolean(uint8_t * apdu, bool boolean_value); int encode_tagged_boolean(uint8_t * apdu, bool boolean_value);
@@ -88,6 +89,8 @@ extern "C" {
int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string); int encode_bitstring(uint8_t * apdu, BACNET_BIT_STRING * bit_string);
int encode_tagged_bitstring(uint8_t * apdu, int encode_tagged_bitstring(uint8_t * apdu,
BACNET_BIT_STRING * bit_string); BACNET_BIT_STRING * bit_string);
int encode_context_bitstring(uint8_t * apdu, int tag_number,
BACNET_BIT_STRING * bit_string);
/* 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 */
@@ -168,6 +171,8 @@ extern "C" {
int encode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime); int encode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime);
int encode_tagged_time(uint8_t * apdu, BACNET_TIME * btime); int encode_tagged_time(uint8_t * apdu, BACNET_TIME * btime);
int decode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime); int decode_bacnet_time(uint8_t * apdu, BACNET_TIME * btime);
int encode_context_time(uint8_t * apdu, int tag_number,
BACNET_TIME * btime);
/* BACnet Date */ /* BACnet Date */
/* year = years since 1900 */ /* year = years since 1900 */
+1 -1
View File
@@ -115,7 +115,7 @@ static void days_since_epoch_into_ymd(uint32_t days,
year++; year++;
} }
while (days >= month_days(year, month)) { while (days >= (uint32_t)month_days(year, month)) {
days -= month_days(year, month); days -= month_days(year, month);
month++; month++;
} }
+39 -5
View File
@@ -25,6 +25,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <errno.h> #include <errno.h>
#include <string.h>
#include "config.h" #include "config.h"
#include "config.h" #include "config.h"
#include "txbuf.h" #include "txbuf.h"
@@ -43,11 +44,12 @@
#include "txbuf.h" #include "txbuf.h"
/* returns the invoke ID for confirmed request, or zero on failure */ /* returns the invoke ID for confirmed request, or zero on failure */
uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */ uint8_t Send_Write_Property_Request_Data(uint32_t device_id,
BACNET_OBJECT_TYPE object_type, BACNET_OBJECT_TYPE object_type,
uint32_t object_instance, uint32_t object_instance,
BACNET_PROPERTY_ID object_property, BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE * object_value, uint8_t *application_data,
int application_data_len,
uint8_t priority, int32_t array_index) uint8_t priority, int32_t array_index)
{ {
BACNET_ADDRESS dest; BACNET_ADDRESS dest;
@@ -80,9 +82,8 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */
data.object_instance = object_instance; data.object_instance = object_instance;
data.object_property = object_property; data.object_property = object_property;
data.array_index = array_index; data.array_index = array_index;
data.application_data_len = data.application_data_len = application_data_len;
bacapp_encode_application_data(&data.application_data[0], memcpy(&data.application_data[0],&application_data[0], application_data_len);
object_value);
data.priority = priority; data.priority = priority;
len = wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len], len = wp_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
invoke_id, &data); invoke_id, &data);
@@ -117,3 +118,36 @@ uint8_t Send_Write_Property_Request(uint32_t device_id, /* destination device */
return invoke_id; return invoke_id;
} }
uint8_t Send_Write_Property_Request(uint32_t device_id,
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_PROPERTY_ID object_property,
BACNET_APPLICATION_DATA_VALUE * object_value,
uint8_t priority, int32_t array_index)
{
uint8_t application_data[MAX_APDU] = {0};
int apdu_len = 0, len = 0;
while (object_value) {
len = bacapp_encode_data(
&application_data[apdu_len],
object_value);
if ((len + apdu_len) < MAX_APDU) {
apdu_len += len;
} else {
return 0;
}
object_value = object_value->next;
}
return Send_Write_Property_Request_Data(
device_id,
object_type,
object_instance,
object_property,
&application_data[0],
apdu_len,
priority,
array_index);
}
+1 -2
View File
@@ -20,7 +20,7 @@ CFLAGS = -Wall -g $(INCLUDES) $(DEFINES)
TARGET = bacwp TARGET = bacwp
SRCS = writeprop.c \ SRCS = main.c \
$(BACNET_PORT)/bip-init.c \ $(BACNET_PORT)/bip-init.c \
$(BACNET_ROOT)/bip.c \ $(BACNET_ROOT)/bip.c \
$(BACNET_HANDLER)/txbuf.c \ $(BACNET_HANDLER)/txbuf.c \
@@ -51,7 +51,6 @@ SRCS = writeprop.c \
$(BACNET_ROOT)/bactext.c \ $(BACNET_ROOT)/bactext.c \
$(BACNET_ROOT)/datetime.c \ $(BACNET_ROOT)/datetime.c \
$(BACNET_ROOT)/indtext.c \ $(BACNET_ROOT)/indtext.c \
$(BACNET_ROOT)/bigend.c \
$(BACNET_ROOT)/whois.c \ $(BACNET_ROOT)/whois.c \
$(BACNET_ROOT)/iam.c \ $(BACNET_ROOT)/iam.c \
$(BACNET_ROOT)/tsm.c \ $(BACNET_ROOT)/tsm.c \
@@ -1,6 +1,6 @@
/************************************************************************** /**************************************************************************
* *
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net> * Copyright (C) 2006-2007 Steve Karg <skarg@users.sourceforge.net>
* *
* Permission is hereby granted, free of charge, to any person obtaining * Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the * a copy of this software and associated documentation files (the
@@ -23,7 +23,7 @@
* *
*********************************************************************/ *********************************************************************/
/* command line tool that sends a BACnet service, and displays the reply */ /* command line tool that sends a BACnet service, and displays the response */
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -60,9 +60,8 @@ static BACNET_OBJECT_TYPE Target_Object_Type = OBJECT_ANALOG_INPUT;
static BACNET_PROPERTY_ID Target_Object_Property = PROP_ACKED_TRANSITIONS; static BACNET_PROPERTY_ID Target_Object_Property = PROP_ACKED_TRANSITIONS;
/* array index value or BACNET_ARRAY_ALL */ /* array index value or BACNET_ARRAY_ALL */
static int32_t Target_Object_Property_Index = BACNET_ARRAY_ALL; static int32_t Target_Object_Property_Index = BACNET_ARRAY_ALL;
static BACNET_APPLICATION_TAG Target_Object_Property_Tag = #define MAX_PROPERTY_VALUES 16
BACNET_APPLICATION_TAG_NULL; static BACNET_APPLICATION_DATA_VALUE Target_Object_Property_Value[MAX_PROPERTY_VALUES];
static BACNET_APPLICATION_DATA_VALUE Target_Object_Property_Value = { 0 };
/* 0 if not set, 1..16 if set */ /* 0 if not set, 1..16 if set */
static uint8_t Target_Object_Property_Priority = 0; static uint8_t Target_Object_Property_Priority = 0;
@@ -156,11 +155,15 @@ int main(int argc, char *argv[])
bool found = false; bool found = false;
char *value_string = NULL; char *value_string = NULL;
bool status = false; bool status = false;
int args_remaining = 0, tag_value_arg = 0, i = 0;
BACNET_APPLICATION_TAG property_tag;
uint8_t context_tag = 0;
bool context_tagged = false;
if (argc < 7) { if (argc < 9) {
/* note: priority 16 and 0 should produce the same end results... */ /* note: priority 16 and 0 should produce the same end results... */
printf("Usage: %s device-instance object-type object-instance " printf("Usage: %s device-instance object-type object-instance "
"property tag value [priority] [index]\r\n", "property priority index tag value [tag value...]\r\n",
filename_remove_path(argv[0])); filename_remove_path(argv[0]));
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) { if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
printf("device-instance:\r\n" printf("device-instance:\r\n"
@@ -186,11 +189,25 @@ int main(int argc, char *argv[])
"writing to. For example, if you were writing to the Present Value\r\n" "writing to. For example, if you were writing to the Present Value\r\n"
"property, you would use 85 as the property.\r\n" "property, you would use 85 as the property.\r\n"
"\r\n" "\r\n"
"priority:\r\n"
"This parameter is used for setting the priority of the\r\n"
"write. If Priority 0 is given, no priority is sent. The BACnet \r\n"
"standard states that the value is written at the lowest \r\n"
"priority (16) if the object property supports priorities\r\n"
"when no priority is sent.\r\n"
"\r\n"
"index\r\n"
"This integer parameter is the index number of an array.\r\n"
"If the property is an array, individual elements can be written\r\n"
"to if supported. If this parameter is -1, the index is ignored.\r\n"
"\r\n"
"tag:\r\n" "tag:\r\n"
"Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n" "Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n"
"in bacenum.h. It is the data type of the value that you are\r\n" "in bacenum.h. It is the data type of the value that you are\r\n"
"writing. For example, if you were writing a REAL value, you would \r\n" "writing. For example, if you were writing a REAL value, you would \r\n"
"use a tag of 4." "use a tag of 4.\r\n"
"Context tags are created using two tags in a row. The context tag\r\n"
"is preceded by a C. Ctag tag. C2 4 creates a context 2 tagged REAL.\r\n"
"\r\n" "\r\n"
"value:\r\n" "value:\r\n"
"The value is an ASCII representation of some type of data that you\r\n" "The value is an ASCII representation of some type of data that you\r\n"
@@ -198,17 +215,6 @@ int main(int argc, char *argv[])
"example, if you were writing a REAL value of 100.0, you would use \r\n" "example, if you were writing a REAL value of 100.0, you would use \r\n"
"100.0 as the value.\r\n" "100.0 as the value.\r\n"
"\r\n" "\r\n"
"[priority]:\r\n"
"This optional parameter is used for setting the priority of the\r\n"
"write. If no priority is given, none is sent, and the BACnet \r\n"
"standard requires that the value is written at the lowest \r\n"
"priority (16) if the object property supports priorities.\r\n"
"\r\n"
"[index]\r\n"
"This optional integer parameter is the index number of an array.\r\n"
"If the property is an array, individual elements can be written\r\n"
"to if supported.\r\n"
"\r\n"
"Here is a brief overview of BACnet property and tags:\r\n" "Here is a brief overview of BACnet property and tags:\r\n"
"Certain properties are expected to be written with certain \r\n" "Certain properties are expected to be written with certain \r\n"
"application tags, so you probably need to know which ones to use\r\n" "application tags, so you probably need to know which ones to use\r\n"
@@ -237,15 +243,10 @@ int main(int argc, char *argv[])
Target_Object_Type = strtol(argv[2], NULL, 0); Target_Object_Type = strtol(argv[2], NULL, 0);
Target_Object_Instance = strtol(argv[3], NULL, 0); Target_Object_Instance = strtol(argv[3], NULL, 0);
Target_Object_Property = strtol(argv[4], NULL, 0); Target_Object_Property = strtol(argv[4], NULL, 0);
Target_Object_Property_Tag = strtol(argv[5], NULL, 0); Target_Object_Property_Priority = strtol(argv[5], NULL, 0);
value_string = argv[6]; Target_Object_Property_Index = strtol(argv[6], NULL, 0);
/* optional priority */ if (Target_Object_Property_Index == -1)
if (argc > 7) Target_Object_Property_Index = BACNET_ARRAY_ALL;
Target_Object_Property_Priority = strtol(argv[7], NULL, 0);
/* optional index */
if (argc > 8)
Target_Object_Property_Index = strtol(argv[8], NULL, 0);
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) { if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n", fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1); Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
@@ -266,19 +267,44 @@ int main(int argc, char *argv[])
Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1); Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
return 1; return 1;
} }
if (Target_Object_Property_Tag >= MAX_BACNET_APPLICATION_TAG) { args_remaining = (argc - 7);
fprintf(stderr, "tag=%u - it must be less than %u\r\n", for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
Target_Object_Property_Tag, MAX_BACNET_APPLICATION_TAG); tag_value_arg = 7+(i*2);
return 1; /* special case for context tagged values */
if (toupper(argv[tag_value_arg][0]) == 'C') {
context_tag = strtol(&argv[tag_value_arg][1], NULL, 0);
tag_value_arg++;
args_remaining--;
Target_Object_Property_Value[i].context_tag = context_tag;
Target_Object_Property_Value[i].context_specific = true;
} else {
Target_Object_Property_Value[i].context_specific = false;
}
property_tag = strtol(argv[tag_value_arg], NULL, 0);
value_string = argv[tag_value_arg+1];
args_remaining -= 2;
/* printf("tag[%d]=%u value[%d]=%s\r\n",
i, property_tag, i, value_string); */
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
fprintf(stderr, "tag=%u - it must be less than %u\r\n",
property_tag, MAX_BACNET_APPLICATION_TAG);
return 1;
}
status = bacapp_parse_application_data(property_tag,
value_string, &Target_Object_Property_Value[i]);
if (!status) {
/* FIXME: show the expected entry format for the tag */
fprintf(stderr, "unable to parse the tag value\r\n");
return 1;
}
Target_Object_Property_Value[i].next = NULL;
if (i > 0) {
Target_Object_Property_Value[i-1].next =
&Target_Object_Property_Value[i];
}
if (args_remaining <= 0)
break;
} }
status = bacapp_parse_application_data(Target_Object_Property_Tag,
value_string, &Target_Object_Property_Value);
if (!status) {
/* FIXME: show the expected entry format for the tag */
fprintf(stderr, "unable to parse the tag value\r\n");
return 1;
}
/* setup my info */ /* setup my info */
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE); Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
address_init(); address_init();
@@ -319,12 +345,12 @@ int main(int argc, char *argv[])
if (found) { if (found) {
if (invoke_id == 0) { if (invoke_id == 0) {
invoke_id = invoke_id =
Send_Write_Property_Request Send_Write_Property_Request(
(Target_Device_Object_Instance, Target_Object_Type, Target_Device_Object_Instance, Target_Object_Type,
Target_Object_Instance, Target_Object_Property, Target_Object_Instance, Target_Object_Property,
&Target_Object_Property_Value, &Target_Object_Property_Value[0],
Target_Object_Property_Priority, Target_Object_Property_Priority,
Target_Object_Property_Index); Target_Object_Property_Index);
} else if (tsm_invoke_id_free(invoke_id)) } else if (tsm_invoke_id_free(invoke_id))
break; break;
else if (tsm_invoke_id_failed(invoke_id)) { else if (tsm_invoke_id_failed(invoke_id)) {
+1 -2
View File
@@ -17,7 +17,7 @@ PRODUCT_EXE = $(PRODUCT).exe
# Choose the Data Link Layer to Enable # Choose the Data Link Layer to Enable
DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1;BIG_ENDIAN=0;PRINT_ENABLED=1 DEFINES = -DBACDL_BIP=1;TSM_ENABLED=1;BIG_ENDIAN=0;PRINT_ENABLED=1
SRCS = writeprop.c \ SRCS = main.c \
..\..\ports\win32\bip-init.c \ ..\..\ports\win32\bip-init.c \
..\..\filename.c \ ..\..\filename.c \
..\..\bip.c \ ..\..\bip.c \
@@ -34,7 +34,6 @@ SRCS = writeprop.c \
..\..\bactext.c \ ..\..\bactext.c \
..\..\datetime.c \ ..\..\datetime.c \
..\..\indtext.c \ ..\..\indtext.c \
..\..\bigend.c \
..\..\whois.c \ ..\..\whois.c \
..\..\iam.c \ ..\..\iam.c \
..\..\rp.c \ ..\..\rp.c \