Enhanced the WriteProperty service demo to allow multiple tagged data elements and to allow context data.
This commit is contained in:
+283
-103
@@ -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
@@ -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
@@ -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 */
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ extern "C" {
|
|||||||
BACNET_PROPERTY_ID object_property,
|
BACNET_PROPERTY_ID object_property,
|
||||||
BACNET_APPLICATION_DATA_VALUE * object_value,
|
BACNET_APPLICATION_DATA_VALUE * object_value,
|
||||||
uint8_t priority, int32_t array_index);
|
uint8_t priority, int32_t array_index);
|
||||||
|
|
||||||
/* returns the invoke ID for confirmed request, or 0 if failed */
|
/* returns the invoke ID for confirmed request, or 0 if failed */
|
||||||
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
|
uint8_t Send_Reinitialize_Device_Request(uint32_t device_id,
|
||||||
BACNET_REINITIALIZED_STATE state, char *password);
|
BACNET_REINITIALIZED_STATE state, char *password);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -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,349 +1,375 @@
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
*
|
*
|
||||||
* 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
|
||||||
* "Software"), to deal in the Software without restriction, including
|
* "Software"), to deal in the Software without restriction, including
|
||||||
* without limitation the rights to use, copy, modify, merge, publish,
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
* permit persons to whom the Software is furnished to do so, subject to
|
* permit persons to whom the Software is furnished to do so, subject to
|
||||||
* the following conditions:
|
* the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included
|
* The above copyright notice and this permission notice shall be included
|
||||||
* in all copies or substantial portions of the Software.
|
* in all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*
|
*
|
||||||
*********************************************************************/
|
*********************************************************************/
|
||||||
|
|
||||||
/* 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>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h> /* for time */
|
#include <time.h> /* for time */
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "bactext.h"
|
#include "bactext.h"
|
||||||
#include "iam.h"
|
#include "iam.h"
|
||||||
#include "arf.h"
|
#include "arf.h"
|
||||||
#include "tsm.h"
|
#include "tsm.h"
|
||||||
#include "address.h"
|
#include "address.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "bacdef.h"
|
#include "bacdef.h"
|
||||||
#include "npdu.h"
|
#include "npdu.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "datalink.h"
|
#include "datalink.h"
|
||||||
#include "whois.h"
|
#include "whois.h"
|
||||||
/* some demo stuff needed */
|
/* some demo stuff needed */
|
||||||
#include "filename.h"
|
#include "filename.h"
|
||||||
#include "handlers.h"
|
#include "handlers.h"
|
||||||
#include "client.h"
|
#include "client.h"
|
||||||
#include "txbuf.h"
|
#include "txbuf.h"
|
||||||
|
|
||||||
/* buffer used for receive */
|
/* buffer used for receive */
|
||||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||||
|
|
||||||
/* global variables used in this file */
|
/* global variables used in this file */
|
||||||
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
|
static uint32_t Target_Device_Object_Instance = BACNET_MAX_INSTANCE;
|
||||||
static uint32_t Target_Object_Instance = BACNET_MAX_INSTANCE;
|
static uint32_t Target_Object_Instance = BACNET_MAX_INSTANCE;
|
||||||
static BACNET_OBJECT_TYPE Target_Object_Type = OBJECT_ANALOG_INPUT;
|
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;
|
|
||||||
|
static BACNET_ADDRESS Target_Address;
|
||||||
static BACNET_ADDRESS Target_Address;
|
static bool Error_Detected = false;
|
||||||
static bool Error_Detected = false;
|
|
||||||
|
static void MyErrorHandler(BACNET_ADDRESS * src,
|
||||||
static void MyErrorHandler(BACNET_ADDRESS * src,
|
uint8_t invoke_id,
|
||||||
uint8_t invoke_id,
|
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
|
||||||
BACNET_ERROR_CLASS error_class, BACNET_ERROR_CODE error_code)
|
{
|
||||||
{
|
/* FIXME: verify src and invoke id */
|
||||||
/* FIXME: verify src and invoke id */
|
(void) src;
|
||||||
(void) src;
|
(void) invoke_id;
|
||||||
(void) invoke_id;
|
printf("\r\nBACnet Error!\r\n");
|
||||||
printf("\r\nBACnet Error!\r\n");
|
printf("Error Class: %s\r\n", bactext_error_class_name(error_class));
|
||||||
printf("Error Class: %s\r\n", bactext_error_class_name(error_class));
|
printf("Error Code: %s\r\n", bactext_error_code_name(error_code));
|
||||||
printf("Error Code: %s\r\n", bactext_error_code_name(error_code));
|
Error_Detected = true;
|
||||||
Error_Detected = true;
|
}
|
||||||
}
|
|
||||||
|
void MyAbortHandler(BACNET_ADDRESS * src,
|
||||||
void MyAbortHandler(BACNET_ADDRESS * src,
|
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
||||||
uint8_t invoke_id, uint8_t abort_reason, bool server)
|
{
|
||||||
{
|
/* FIXME: verify src and invoke id */
|
||||||
/* FIXME: verify src and invoke id */
|
(void) src;
|
||||||
(void) src;
|
(void) invoke_id;
|
||||||
(void) invoke_id;
|
(void) server;
|
||||||
(void) server;
|
printf("\r\nBACnet Abort!\r\n");
|
||||||
printf("\r\nBACnet Abort!\r\n");
|
printf("Abort Reason: %s\r\n",
|
||||||
printf("Abort Reason: %s\r\n",
|
bactext_abort_reason_name(abort_reason));
|
||||||
bactext_abort_reason_name(abort_reason));
|
Error_Detected = true;
|
||||||
Error_Detected = true;
|
}
|
||||||
}
|
|
||||||
|
void MyRejectHandler(BACNET_ADDRESS * src,
|
||||||
void MyRejectHandler(BACNET_ADDRESS * src,
|
uint8_t invoke_id, uint8_t reject_reason)
|
||||||
uint8_t invoke_id, uint8_t reject_reason)
|
{
|
||||||
{
|
/* FIXME: verify src and invoke id */
|
||||||
/* FIXME: verify src and invoke id */
|
(void) src;
|
||||||
(void) src;
|
(void) invoke_id;
|
||||||
(void) invoke_id;
|
printf("\r\nBACnet Reject!\r\n");
|
||||||
printf("\r\nBACnet Reject!\r\n");
|
printf("Reject Reason: %s\r\n",
|
||||||
printf("Reject Reason: %s\r\n",
|
bactext_reject_reason_name(reject_reason));
|
||||||
bactext_reject_reason_name(reject_reason));
|
Error_Detected = true;
|
||||||
Error_Detected = true;
|
}
|
||||||
}
|
|
||||||
|
void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
|
||||||
void MyWritePropertySimpleAckHandler(BACNET_ADDRESS * src,
|
uint8_t invoke_id)
|
||||||
uint8_t invoke_id)
|
{
|
||||||
{
|
(void) src;
|
||||||
(void) src;
|
(void) invoke_id;
|
||||||
(void) invoke_id;
|
printf("\r\nWriteProperty Acknowledged!\r\n");
|
||||||
printf("\r\nWriteProperty Acknowledged!\r\n");
|
}
|
||||||
}
|
|
||||||
|
static void Init_Service_Handlers(void)
|
||||||
static void Init_Service_Handlers(void)
|
{
|
||||||
{
|
/* we need to handle who-is
|
||||||
/* we need to handle who-is
|
to support dynamic device binding to us */
|
||||||
to support dynamic device binding to us */
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
|
handler_who_is);
|
||||||
handler_who_is);
|
/* handle i-am to support binding to other devices */
|
||||||
/* handle i-am to support binding to other devices */
|
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
||||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_I_AM,
|
handler_i_am_bind);
|
||||||
handler_i_am_bind);
|
/* set the handler for all the services we don't implement
|
||||||
/* set the handler for all the services we don't implement
|
It is required to send the proper reject message... */
|
||||||
It is required to send the proper reject message... */
|
apdu_set_unrecognized_service_handler_handler
|
||||||
apdu_set_unrecognized_service_handler_handler
|
(handler_unrecognized_service);
|
||||||
(handler_unrecognized_service);
|
/* we must implement read property - it's required! */
|
||||||
/* we must implement read property - it's required! */
|
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
||||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
|
handler_read_property);
|
||||||
handler_read_property);
|
/* handle the ack coming back */
|
||||||
/* handle the ack coming back */
|
apdu_set_confirmed_simple_ack_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
apdu_set_confirmed_simple_ack_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
MyWritePropertySimpleAckHandler);
|
||||||
MyWritePropertySimpleAckHandler);
|
/* handle any errors coming back */
|
||||||
/* handle any errors coming back */
|
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
||||||
apdu_set_error_handler(SERVICE_CONFIRMED_WRITE_PROPERTY,
|
MyErrorHandler);
|
||||||
MyErrorHandler);
|
apdu_set_abort_handler(MyAbortHandler);
|
||||||
apdu_set_abort_handler(MyAbortHandler);
|
apdu_set_reject_handler(MyRejectHandler);
|
||||||
apdu_set_reject_handler(MyRejectHandler);
|
}
|
||||||
}
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
int main(int argc, char *argv[])
|
{
|
||||||
{
|
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
uint16_t pdu_len = 0;
|
||||||
uint16_t pdu_len = 0;
|
unsigned timeout = 100; /* milliseconds */
|
||||||
unsigned timeout = 100; /* milliseconds */
|
unsigned max_apdu = 0;
|
||||||
unsigned max_apdu = 0;
|
time_t elapsed_seconds = 0;
|
||||||
time_t elapsed_seconds = 0;
|
time_t last_seconds = 0;
|
||||||
time_t last_seconds = 0;
|
time_t current_seconds = 0;
|
||||||
time_t current_seconds = 0;
|
time_t timeout_seconds = 0;
|
||||||
time_t timeout_seconds = 0;
|
uint8_t invoke_id = 0;
|
||||||
uint8_t invoke_id = 0;
|
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;
|
||||||
if (argc < 7) {
|
uint8_t context_tag = 0;
|
||||||
/* note: priority 16 and 0 should produce the same end results... */
|
bool context_tagged = false;
|
||||||
printf("Usage: %s device-instance object-type object-instance "
|
|
||||||
"property tag value [priority] [index]\r\n",
|
if (argc < 9) {
|
||||||
filename_remove_path(argv[0]));
|
/* note: priority 16 and 0 should produce the same end results... */
|
||||||
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
|
printf("Usage: %s device-instance object-type object-instance "
|
||||||
printf("device-instance:\r\n"
|
"property priority index tag value [tag value...]\r\n",
|
||||||
"BACnet Device Object Instance number that you are trying to\r\n"
|
filename_remove_path(argv[0]));
|
||||||
"communicate to. This number will be used to try and bind with\r\n"
|
if ((argc > 1) && (strcmp(argv[1], "--help") == 0)) {
|
||||||
"the device using Who-Is and I-Am services. For example, if you were\r\n"
|
printf("device-instance:\r\n"
|
||||||
"writing to Device Object 123, the device-instance would be 123.\r\n"
|
"BACnet Device Object Instance number that you are trying to\r\n"
|
||||||
"\r\n"
|
"communicate to. This number will be used to try and bind with\r\n"
|
||||||
"object-type:\r\n"
|
"the device using Who-Is and I-Am services. For example, if you were\r\n"
|
||||||
"The object type is the integer value of the enumeration\r\n"
|
"writing to Device Object 123, the device-instance would be 123.\r\n"
|
||||||
"BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\r\n"
|
"\r\n"
|
||||||
"writing to. For example if you were writing to Analog Output 2, \r\n"
|
"object-type:\r\n"
|
||||||
"the object-type would be 1.\r\n"
|
"The object type is the integer value of the enumeration\r\n"
|
||||||
"\r\n"
|
"BACNET_OBJECT_TYPE in bacenum.h. It is the object that you are\r\n"
|
||||||
"object-instance:\r\n"
|
"writing to. For example if you were writing to Analog Output 2, \r\n"
|
||||||
"This is the object instance number of the object that you are \r\n"
|
"the object-type would be 1.\r\n"
|
||||||
"writing to. For example, if you were writing to Analog Output 2, \r\n"
|
"\r\n"
|
||||||
"the object-instance would be 2.\r\n"
|
"object-instance:\r\n"
|
||||||
"\r\n"
|
"This is the object instance number of the object that you are \r\n"
|
||||||
"property:\r\n"
|
"writing to. For example, if you were writing to Analog Output 2, \r\n"
|
||||||
"The property is an integer value of the enumeration \r\n"
|
"the object-instance would be 2.\r\n"
|
||||||
"BACNET_PROPERTY_ID in bacenum.h. It is the property you are \r\n"
|
"\r\n"
|
||||||
"writing to. For example, if you were writing to the Present Value\r\n"
|
"property:\r\n"
|
||||||
"property, you would use 85 as the property.\r\n"
|
"The property is an integer value of the enumeration \r\n"
|
||||||
"\r\n"
|
"BACNET_PROPERTY_ID in bacenum.h. It is the property you are \r\n"
|
||||||
"tag:\r\n"
|
"writing to. For example, if you were writing to the Present Value\r\n"
|
||||||
"Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n"
|
"property, you would use 85 as the property.\r\n"
|
||||||
"in bacenum.h. It is the data type of the value that you are\r\n"
|
"\r\n"
|
||||||
"writing. For example, if you were writing a REAL value, you would \r\n"
|
"priority:\r\n"
|
||||||
"use a tag of 4."
|
"This parameter is used for setting the priority of the\r\n"
|
||||||
"\r\n"
|
"write. If Priority 0 is given, no priority is sent. The BACnet \r\n"
|
||||||
"value:\r\n"
|
"standard states that the value is written at the lowest \r\n"
|
||||||
"The value is an ASCII representation of some type of data that you\r\n"
|
"priority (16) if the object property supports priorities\r\n"
|
||||||
"are writing. It is encoded using the tag information provided. For\r\n"
|
"when no priority is sent.\r\n"
|
||||||
"example, if you were writing a REAL value of 100.0, you would use \r\n"
|
"\r\n"
|
||||||
"100.0 as the value.\r\n"
|
"index\r\n"
|
||||||
"\r\n"
|
"This integer parameter is the index number of an array.\r\n"
|
||||||
"[priority]:\r\n"
|
"If the property is an array, individual elements can be written\r\n"
|
||||||
"This optional parameter is used for setting the priority of the\r\n"
|
"to if supported. If this parameter is -1, the index is ignored.\r\n"
|
||||||
"write. If no priority is given, none is sent, and the BACnet \r\n"
|
"\r\n"
|
||||||
"standard requires that the value is written at the lowest \r\n"
|
"tag:\r\n"
|
||||||
"priority (16) if the object property supports priorities.\r\n"
|
"Tag is the integer value of the enumeration BACNET_APPLICATION_TAG \r\n"
|
||||||
"\r\n"
|
"in bacenum.h. It is the data type of the value that you are\r\n"
|
||||||
"[index]\r\n"
|
"writing. For example, if you were writing a REAL value, you would \r\n"
|
||||||
"This optional integer parameter is the index number of an array.\r\n"
|
"use a tag of 4.\r\n"
|
||||||
"If the property is an array, individual elements can be written\r\n"
|
"Context tags are created using two tags in a row. The context tag\r\n"
|
||||||
"to if supported.\r\n"
|
"is preceded by a C. Ctag tag. C2 4 creates a context 2 tagged REAL.\r\n"
|
||||||
"\r\n"
|
"\r\n"
|
||||||
"Here is a brief overview of BACnet property and tags:\r\n"
|
"value:\r\n"
|
||||||
"Certain properties are expected to be written with certain \r\n"
|
"The value is an ASCII representation of some type of data that you\r\n"
|
||||||
"application tags, so you probably need to know which ones to use\r\n"
|
"are writing. It is encoded using the tag information provided. For\r\n"
|
||||||
"with each property of each object. It is almost safe to say that\r\n"
|
"example, if you were writing a REAL value of 100.0, you would use \r\n"
|
||||||
"given a property and an object and a table, the tag could be looked\r\n"
|
"100.0 as the value.\r\n"
|
||||||
"up automatically. There may be a few exceptions to this, such as\r\n"
|
"\r\n"
|
||||||
"the Any property type in the schedule object and the Present Value\r\n"
|
"Here is a brief overview of BACnet property and tags:\r\n"
|
||||||
"accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n"
|
"Certain properties are expected to be written with certain \r\n"
|
||||||
"the demo to use this kind of table - but I also wanted to be able\r\n"
|
"application tags, so you probably need to know which ones to use\r\n"
|
||||||
"to do negative testing by passing the wrong tag and have the server\r\n"
|
"with each property of each object. It is almost safe to say that\r\n"
|
||||||
"return a reject message.\r\n"
|
"given a property and an object and a table, the tag could be looked\r\n"
|
||||||
"\r\n"
|
"up automatically. There may be a few exceptions to this, such as\r\n"
|
||||||
"Example:\r\n"
|
"the Any property type in the schedule object and the Present Value\r\n"
|
||||||
"If you want send a 100 to the Present-Value in the Analog Output\r\n"
|
"accepting REAL, BOOLEAN, NULL, etc. Perhaps it would be simpler for\r\n"
|
||||||
"at priority 16, you could send the following command:\r\n"
|
"the demo to use this kind of table - but I also wanted to be able\r\n"
|
||||||
"%s 123 1 0 85 4 100\r\n"
|
"to do negative testing by passing the wrong tag and have the server\r\n"
|
||||||
"You could also send a relinquish command:\r\n"
|
"return a reject message.\r\n"
|
||||||
"%s 123 1 0 85 0 0\r\n",
|
"\r\n"
|
||||||
filename_remove_path(argv[0]),
|
"Example:\r\n"
|
||||||
filename_remove_path(argv[0]));
|
"If you want send a 100 to the Present-Value in the Analog Output\r\n"
|
||||||
}
|
"at priority 16, you could send the following command:\r\n"
|
||||||
return 0;
|
"%s 123 1 0 85 4 100\r\n"
|
||||||
}
|
"You could also send a relinquish command:\r\n"
|
||||||
/* decode the command line parameters */
|
"%s 123 1 0 85 0 0\r\n",
|
||||||
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
|
filename_remove_path(argv[0]),
|
||||||
Target_Object_Type = strtol(argv[2], NULL, 0);
|
filename_remove_path(argv[0]));
|
||||||
Target_Object_Instance = strtol(argv[3], NULL, 0);
|
}
|
||||||
Target_Object_Property = strtol(argv[4], NULL, 0);
|
return 0;
|
||||||
Target_Object_Property_Tag = strtol(argv[5], NULL, 0);
|
}
|
||||||
value_string = argv[6];
|
/* decode the command line parameters */
|
||||||
/* optional priority */
|
Target_Device_Object_Instance = strtol(argv[1], NULL, 0);
|
||||||
if (argc > 7)
|
Target_Object_Type = strtol(argv[2], NULL, 0);
|
||||||
Target_Object_Property_Priority = strtol(argv[7], NULL, 0);
|
Target_Object_Instance = strtol(argv[3], NULL, 0);
|
||||||
/* optional index */
|
Target_Object_Property = strtol(argv[4], NULL, 0);
|
||||||
if (argc > 8)
|
Target_Object_Property_Priority = strtol(argv[5], NULL, 0);
|
||||||
Target_Object_Property_Index = strtol(argv[8], NULL, 0);
|
Target_Object_Property_Index = strtol(argv[6], NULL, 0);
|
||||||
|
if (Target_Object_Property_Index == -1)
|
||||||
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
|
Target_Object_Property_Index = BACNET_ARRAY_ALL;
|
||||||
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
if (Target_Device_Object_Instance > BACNET_MAX_INSTANCE) {
|
||||||
Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
|
fprintf(stderr, "device-instance=%u - it must be less than %u\r\n",
|
||||||
return 1;
|
Target_Device_Object_Instance, BACNET_MAX_INSTANCE + 1);
|
||||||
}
|
return 1;
|
||||||
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
|
}
|
||||||
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
if (Target_Object_Type > MAX_BACNET_OBJECT_TYPE) {
|
||||||
Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
|
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
||||||
return 1;
|
Target_Object_Type, MAX_BACNET_OBJECT_TYPE + 1);
|
||||||
}
|
return 1;
|
||||||
if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
|
}
|
||||||
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
|
if (Target_Object_Instance > BACNET_MAX_INSTANCE) {
|
||||||
Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
|
fprintf(stderr, "object-instance=%u - it must be less than %u\r\n",
|
||||||
return 1;
|
Target_Object_Instance, BACNET_MAX_INSTANCE + 1);
|
||||||
}
|
return 1;
|
||||||
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) {
|
}
|
||||||
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
if (Target_Object_Property > MAX_BACNET_PROPERTY_ID) {
|
||||||
Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
|
fprintf(stderr, "object-type=%u - it must be less than %u\r\n",
|
||||||
return 1;
|
Target_Object_Property, MAX_BACNET_PROPERTY_ID + 1);
|
||||||
}
|
return 1;
|
||||||
if (Target_Object_Property_Tag >= MAX_BACNET_APPLICATION_TAG) {
|
}
|
||||||
fprintf(stderr, "tag=%u - it must be less than %u\r\n",
|
args_remaining = (argc - 7);
|
||||||
Target_Object_Property_Tag, MAX_BACNET_APPLICATION_TAG);
|
for (i = 0; i < MAX_PROPERTY_VALUES; i++) {
|
||||||
return 1;
|
tag_value_arg = 7+(i*2);
|
||||||
}
|
/* special case for context tagged values */
|
||||||
status = bacapp_parse_application_data(Target_Object_Property_Tag,
|
if (toupper(argv[tag_value_arg][0]) == 'C') {
|
||||||
value_string, &Target_Object_Property_Value);
|
context_tag = strtol(&argv[tag_value_arg][1], NULL, 0);
|
||||||
if (!status) {
|
tag_value_arg++;
|
||||||
/* FIXME: show the expected entry format for the tag */
|
args_remaining--;
|
||||||
fprintf(stderr, "unable to parse the tag value\r\n");
|
Target_Object_Property_Value[i].context_tag = context_tag;
|
||||||
return 1;
|
Target_Object_Property_Value[i].context_specific = true;
|
||||||
}
|
} else {
|
||||||
|
Target_Object_Property_Value[i].context_specific = false;
|
||||||
/* setup my info */
|
}
|
||||||
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
property_tag = strtol(argv[tag_value_arg], NULL, 0);
|
||||||
address_init();
|
value_string = argv[tag_value_arg+1];
|
||||||
Init_Service_Handlers();
|
args_remaining -= 2;
|
||||||
/* configure standard BACnet/IP port */
|
/* printf("tag[%d]=%u value[%d]=%s\r\n",
|
||||||
bip_set_interface("eth0"); /* for linux */
|
i, property_tag, i, value_string); */
|
||||||
bip_set_port(0xBAC0);
|
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
|
||||||
if (!bip_init())
|
fprintf(stderr, "tag=%u - it must be less than %u\r\n",
|
||||||
return 1;
|
property_tag, MAX_BACNET_APPLICATION_TAG);
|
||||||
/* configure the timeout values */
|
return 1;
|
||||||
last_seconds = time(NULL);
|
}
|
||||||
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
status = bacapp_parse_application_data(property_tag,
|
||||||
Device_Number_Of_APDU_Retries();
|
value_string, &Target_Object_Property_Value[i]);
|
||||||
/* try to bind with the device */
|
if (!status) {
|
||||||
Send_WhoIs(Target_Device_Object_Instance,
|
/* FIXME: show the expected entry format for the tag */
|
||||||
Target_Device_Object_Instance);
|
fprintf(stderr, "unable to parse the tag value\r\n");
|
||||||
/* loop forever */
|
return 1;
|
||||||
for (;;) {
|
}
|
||||||
/* increment timer - exit if timed out */
|
Target_Object_Property_Value[i].next = NULL;
|
||||||
current_seconds = time(NULL);
|
if (i > 0) {
|
||||||
|
Target_Object_Property_Value[i-1].next =
|
||||||
/* returns 0 bytes on timeout */
|
&Target_Object_Property_Value[i];
|
||||||
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
}
|
||||||
|
if (args_remaining <= 0)
|
||||||
/* process */
|
break;
|
||||||
if (pdu_len) {
|
}
|
||||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
/* setup my info */
|
||||||
}
|
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
|
||||||
/* at least one second has passed */
|
address_init();
|
||||||
if (current_seconds != last_seconds)
|
Init_Service_Handlers();
|
||||||
tsm_timer_milliseconds(((current_seconds -
|
/* configure standard BACnet/IP port */
|
||||||
last_seconds) * 1000));
|
bip_set_interface("eth0"); /* for linux */
|
||||||
if (Error_Detected)
|
bip_set_port(0xBAC0);
|
||||||
break;
|
if (!bip_init())
|
||||||
/* wait until the device is bound, or timeout and quit */
|
return 1;
|
||||||
found = address_bind_request(Target_Device_Object_Instance,
|
/* configure the timeout values */
|
||||||
&max_apdu, &Target_Address);
|
last_seconds = time(NULL);
|
||||||
if (found) {
|
timeout_seconds = (Device_APDU_Timeout() / 1000) *
|
||||||
if (invoke_id == 0) {
|
Device_Number_Of_APDU_Retries();
|
||||||
invoke_id =
|
/* try to bind with the device */
|
||||||
Send_Write_Property_Request
|
Send_WhoIs(Target_Device_Object_Instance,
|
||||||
(Target_Device_Object_Instance, Target_Object_Type,
|
Target_Device_Object_Instance);
|
||||||
Target_Object_Instance, Target_Object_Property,
|
/* loop forever */
|
||||||
&Target_Object_Property_Value,
|
for (;;) {
|
||||||
Target_Object_Property_Priority,
|
/* increment timer - exit if timed out */
|
||||||
Target_Object_Property_Index);
|
current_seconds = time(NULL);
|
||||||
} else if (tsm_invoke_id_free(invoke_id))
|
|
||||||
break;
|
/* returns 0 bytes on timeout */
|
||||||
else if (tsm_invoke_id_failed(invoke_id)) {
|
pdu_len = bip_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||||
fprintf(stderr, "\rError: TSM Timeout!\r\n");
|
|
||||||
tsm_free_invoke_id(invoke_id);
|
/* process */
|
||||||
/* try again or abort? */
|
if (pdu_len) {
|
||||||
break;
|
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||||
}
|
}
|
||||||
} else {
|
/* at least one second has passed */
|
||||||
/* increment timer - exit if timed out */
|
if (current_seconds != last_seconds)
|
||||||
elapsed_seconds += (current_seconds - last_seconds);
|
tsm_timer_milliseconds(((current_seconds -
|
||||||
if (elapsed_seconds > timeout_seconds) {
|
last_seconds) * 1000));
|
||||||
printf("\rError: APDU Timeout!\r\n");
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
}
|
/* wait until the device is bound, or timeout and quit */
|
||||||
}
|
found = address_bind_request(Target_Device_Object_Instance,
|
||||||
/* keep track of time for next check */
|
&max_apdu, &Target_Address);
|
||||||
last_seconds = current_seconds;
|
if (found) {
|
||||||
}
|
if (invoke_id == 0) {
|
||||||
|
invoke_id =
|
||||||
return 0;
|
Send_Write_Property_Request(
|
||||||
}
|
Target_Device_Object_Instance, Target_Object_Type,
|
||||||
|
Target_Object_Instance, Target_Object_Property,
|
||||||
|
&Target_Object_Property_Value[0],
|
||||||
|
Target_Object_Property_Priority,
|
||||||
|
Target_Object_Property_Index);
|
||||||
|
} else if (tsm_invoke_id_free(invoke_id))
|
||||||
|
break;
|
||||||
|
else if (tsm_invoke_id_failed(invoke_id)) {
|
||||||
|
fprintf(stderr, "\rError: TSM Timeout!\r\n");
|
||||||
|
tsm_free_invoke_id(invoke_id);
|
||||||
|
/* try again or abort? */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* increment timer - exit if timed out */
|
||||||
|
elapsed_seconds += (current_seconds - last_seconds);
|
||||||
|
if (elapsed_seconds > timeout_seconds) {
|
||||||
|
printf("\rError: APDU Timeout!\r\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* keep track of time for next check */
|
||||||
|
last_seconds = current_seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -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 \
|
||||||
|
|||||||
Reference in New Issue
Block a user