Indented.

This commit is contained in:
skarg
2007-11-29 15:56:53 +00:00
parent c585241c03
commit 411d6c1b24
236 changed files with 17864 additions and 15724 deletions
+73 -62
View File
@@ -41,7 +41,8 @@ static uint8_t Present_Value[MAX_ANALOG_INPUTS];
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Input_Valid_Instance(uint32_t object_instance)
bool Analog_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_INPUTS)
return true;
@@ -50,18 +51,21 @@ bool Analog_Input_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Analog_Input_Count(void)
unsigned Analog_Input_Count(
void)
{
return MAX_ANALOG_INPUTS;
}
/* we simply have 0-n object instances. */
uint32_t Analog_Input_Index_To_Instance(unsigned index)
uint32_t Analog_Input_Index_To_Instance(
unsigned index)
{
return index;
}
char *Analog_Input_Name(uint32_t object_instance)
char *Analog_Input_Name(
uint32_t object_instance)
{
static char text_string[16] = ""; /* okay for single thread */
@@ -73,72 +77,78 @@ char *Analog_Input_Name(uint32_t object_instance)
return NULL;
}
static float Analog_Input_Present_Value(uint32_t object_instance)
static float Analog_Input_Present_Value(
uint32_t object_instance)
{
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
float value = 0.0;
if (object_instance < MAX_ANALOG_INPUTS)
value = Present_Value[object_instance];
return value;
}
/* return apdu length, or -1 on error */
/* assumption - object has already exists */
int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
int Analog_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
(void) array_index;
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_INPUT,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Input_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ANALOG_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len = encode_application_real(&apdu[0],
Analog_Input_Present_Value(object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -149,7 +159,8 @@ int Analog_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testAnalogInput(Test * pTest)
void testAnalogInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -165,8 +176,7 @@ void testAnalogInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Analog_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -179,7 +189,8 @@ void testAnalogInput(Test * pTest)
}
#ifdef TEST_ANALOG_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -196,5 +207,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
#endif /* TEST_ANALOG_INPUT */
#endif /* TEST */
+187 -169
View File
@@ -32,7 +32,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_ANALOG_VALUES 4
@@ -52,7 +52,8 @@ static uint8_t Present_Value[MAX_ANALOG_VALUES];
/* we need to have our arrays initialized before answering any calls */
static bool Analog_Value_Initialized = false;
void Analog_Value_Init(void)
void Analog_Value_Init(
void)
{
unsigned i;
@@ -71,7 +72,8 @@ void Analog_Value_Init(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Value_Valid_Instance(uint32_t object_instance)
bool Analog_Value_Valid_Instance(
uint32_t object_instance)
{
Analog_Value_Init();
if (object_instance < MAX_ANALOG_VALUES)
@@ -82,7 +84,8 @@ bool Analog_Value_Valid_Instance(uint32_t object_instance)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Value_Count(void)
unsigned Analog_Value_Count(
void)
{
Analog_Value_Init();
return MAX_ANALOG_VALUES;
@@ -91,7 +94,8 @@ unsigned Analog_Value_Count(void)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the instance */
/* that correlates to the correct index */
uint32_t Analog_Value_Index_To_Instance(unsigned index)
uint32_t Analog_Value_Index_To_Instance(
unsigned index)
{
Analog_Value_Init();
return index;
@@ -100,7 +104,8 @@ uint32_t Analog_Value_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
unsigned Analog_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_ANALOG_VALUES;
@@ -111,7 +116,8 @@ unsigned Analog_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static float Analog_Value_Present_Value(uint32_t object_instance)
static float Analog_Value_Present_Value(
uint32_t object_instance)
{
float value = ANALOG_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -127,7 +133,8 @@ static float Analog_Value_Present_Value(uint32_t object_instance)
}
/* note: the object name must be unique within this device */
char *Analog_Value_Name(uint32_t object_instance)
char *Analog_Value_Name(
uint32_t object_instance)
{
static char text_string[32] = ""; /* okay for single thread */
@@ -140,14 +147,16 @@ char *Analog_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
int Analog_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
float real_value = (float) 1.414;
@@ -157,110 +166,118 @@ int Analog_Value_Encode_Property_APDU(uint8_t * apdu,
Analog_Value_Init();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
encode_application_object_id(&apdu[0], OBJECT_ANALOG_VALUE,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Analog_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_ANALOG_VALUE);
break;
case PROP_PRESENT_VALUE:
real_value = Analog_Value_Present_Value(object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
#if 0
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] ==
ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len = encode_application_real(&apdu[apdu_len], real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len = encode_application_real(&apdu[0], real_value);
state = Analog_Value_Out_Of_Service[object_index];
#endif
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_UNITS:
apdu_len = encode_application_enumerated(&apdu[0], UNITS_PERCENT);
break;
#if 0
case PROP_PRIORITY_ARRAY:
/* Array element zero is the number of elements in the array */
if (array_index == 0)
apdu_len =
encode_application_unsigned(&apdu[0], BACNET_MAX_PRIORITY);
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (array_index == BACNET_ARRAY_ALL) {
object_index = Analog_Value_Instance_To_Index(object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Present_Value[object_index][i] == ANALOG_LEVEL_NULL)
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Present_Value[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
else {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
object_index = Analog_Value_Instance_To_Index(object_instance);
if (array_index <= BACNET_MAX_PRIORITY) {
if (Present_Value[object_index][array_index - 1] ==
ANALOG_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value =
Present_Value[object_index][array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
break;
case PROP_RELINQUISH_DEFAULT:
real_value = ANALOG_RELINQUISH_DEFAULT;
apdu_len = encode_application_real(&apdu[0], real_value);
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Analog_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -281,80 +298,80 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
level = (uint8_t) value.type.Real;
object_index =
Analog_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Present_Value[object_index] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_REAL) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Real >= 0.0) && (value.type.Real <= 100.0)) {
level = (uint8_t) value.type.Real;
object_index =
Analog_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
Present_Value[object_index] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
level = ANALOG_LEVEL_NULL;
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Present_Value[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Analog_Value_Instance_To_Index(wp_data->object_instance);
Analog_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -366,7 +383,8 @@ bool Analog_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testAnalog_Value(Test * pTest)
void testAnalog_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -381,8 +399,7 @@ void testAnalog_Value(Test * pTest)
len = Analog_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -395,7 +412,8 @@ void testAnalog_Value(Test * pTest)
}
#ifdef TEST_ANALOG_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -412,5 +430,5 @@ int main(void)
return 0;
}
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
#endif /* TEST_ANALOG_VALUE */
#endif /* TEST */
+81 -68
View File
@@ -37,21 +37,23 @@
static BACNET_BINARY_PV Present_Value[MAX_BINARY_INPUTS];
static void Binary_Input_Initialize(void)
static void Binary_Input_Initialize(
void)
{
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* we simply have 0-n object instances. */
bool Binary_Input_Valid_Instance(uint32_t object_instance)
bool Binary_Input_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_INPUTS)
return true;
@@ -60,13 +62,15 @@ bool Binary_Input_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Binary_Input_Count(void)
unsigned Binary_Input_Count(
void)
{
return MAX_BINARY_INPUTS;
}
/* we simply have 0-n object instances.*/
uint32_t Binary_Input_Index_To_Instance(unsigned index)
uint32_t Binary_Input_Index_To_Instance(
unsigned index)
{
return index;
}
@@ -74,7 +78,8 @@ uint32_t Binary_Input_Index_To_Instance(unsigned index)
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need to return the index */
/* that correlates to the correct instance number */
unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Input_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_INPUTS;
@@ -84,8 +89,8 @@ unsigned Binary_Input_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
@@ -93,13 +98,14 @@ static BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t
Binary_Input_Initialize();
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
value = Present_Value[index];
value = Present_Value[index];
}
return value;
}
char *Binary_Input_Name(uint32_t object_instance)
char *Binary_Input_Name(
uint32_t object_instance)
{
static char text_string[16] = ""; /* okay for single thread */
@@ -113,13 +119,15 @@ char *Binary_Input_Name(uint32_t object_instance)
/* return apdu length, or -1 on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
int Binary_Input_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_POLARITY polarity = POLARITY_NORMAL;
@@ -129,48 +137,52 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
(void) array_index;
Binary_Input_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* note: object name must be unique in our device */
characterstring_init_ansi(&char_string,
Binary_Input_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0],value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
/* note: object name must be unique in our device */
characterstring_init_ansi(&char_string,
Binary_Input_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_INPUT);
break;
case PROP_PRESENT_VALUE:
value = Binary_Input_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
@@ -181,7 +193,8 @@ int Binary_Input_Encode_Property_APDU(uint8_t * apdu,
#include <string.h>
#include "ctest.h"
void testBinaryInput(Test * pTest)
void testBinaryInput(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -197,8 +210,7 @@ void testBinaryInput(Test * pTest)
/* FIXME: we should do a lot more testing here... */
len = Binary_Input_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len >= 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -211,7 +223,8 @@ void testBinaryInput(Test * pTest)
}
#ifdef TEST_BINARY_INPUT
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -228,5 +241,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
#endif /* TEST_BINARY_INPUT */
#endif /* TEST */
+152 -137
View File
@@ -31,28 +31,30 @@
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "wp.h"
#define MAX_BINARY_VALUES 8
static BACNET_BINARY_PV Present_Value[MAX_BINARY_VALUES];
static void Binary_Value_Initialize(void)
static void Binary_Value_Initialize(
void)
{
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
static bool initialized = false;
unsigned i;
if (!initialized) {
initialized = true;
for (i = 0; i < MAX_BINARY_VALUES; i++) {
Present_Value[i] = BINARY_INACTIVE;
}
}
}
}
/* we simply have 0-n object instances. */
bool Binary_Value_Valid_Instance(uint32_t object_instance)
bool Binary_Value_Valid_Instance(
uint32_t object_instance)
{
if (object_instance < MAX_BINARY_VALUES)
return true;
@@ -61,19 +63,22 @@ bool Binary_Value_Valid_Instance(uint32_t object_instance)
}
/* we simply have 0-n object instances. */
unsigned Binary_Value_Count(void)
unsigned Binary_Value_Count(
void)
{
return MAX_BINARY_VALUES;
}
/* we simply have 0-n object instances. */
uint32_t Binary_Value_Index_To_Instance(unsigned index)
uint32_t Binary_Value_Index_To_Instance(
unsigned index)
{
return index;
}
/* we simply have 0-n object instances. */
unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
unsigned Binary_Value_Instance_To_Index(
uint32_t object_instance)
{
unsigned index = MAX_BINARY_VALUES;
@@ -83,8 +88,8 @@ unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
return index;
}
static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
object_instance)
static BACNET_BINARY_PV Binary_Value_Present_Value(
uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
@@ -97,7 +102,8 @@ static BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t
}
/* note: the object name must be unique within this device */
char *Binary_Value_Name(uint32_t object_instance)
char *Binary_Value_Name(
uint32_t object_instance)
{
static char text_string[16] = ""; /* okay for single thread */
@@ -110,14 +116,16 @@ char *Binary_Value_Name(uint32_t object_instance)
}
/* return apdu len, or -1 on error */
int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
int Binary_Value_Encode_Property_APDU(
uint8_t * apdu,
uint32_t object_instance,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int len = 0;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
@@ -128,58 +136,64 @@ int Binary_Value_Encode_Property_APDU(uint8_t * apdu,
Binary_Value_Initialize();
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len = encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
Binary_Value_Name(object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value = Binary_Value_Present_Value(object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_FAULT, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE, false);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
/* note: see the details in the standard on how to use this */
apdu_len =
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case PROP_POLARITY:
/* FIXME: figure out the polarity */
apdu_len = encode_application_enumerated(&apdu[0], polarity);
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
/* returns true if successful */
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
unsigned int object_index = 0;
@@ -199,85 +213,85 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = value.type.Enumerated;
object_index =
Binary_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
/* NOTE: this Binary value has no priority array */
Present_Value[object_index] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. */
status = true;
} else if (priority == 6) {
case PROP_PRESENT_VALUE:
if (value.tag == BACNET_APPLICATION_TAG_ENUMERATED) {
priority = wp_data->priority;
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value.type.Enumerated >= MIN_BINARY_PV) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = value.type.Enumerated;
object_index =
Binary_Value_Instance_To_Index(wp_data->
object_instance);
priority--;
/* NOTE: this Binary value has no priority array */
Present_Value[object_index] = level;
/* Note: you could set the physical output here if we
are the highest priority.
However, if Out of Service is TRUE, then don't set the
physical output. */
status = true;
} else if (priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
#else
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
#endif
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else if (value.tag == BACNET_APPLICATION_TAG_NULL) {
break;
#if 0
/* NOTE: this Binary Value has no priority array */
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Value_Level[object_index][priority] = level;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
However, if Out of Service is TRUE, then don't set the
physical output. This comment may apply to the
main loop (i.e. check out of service before changing output) */
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
#else
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
break;
#endif
} else {
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#if 0
case PROP_OUT_OF_SERVICE:
if (value.tag == BACNET_APPLICATION_TAG_BOOLEAN) {
object_index =
Binary_Value_Instance_To_Index(wp_data->object_instance);
Binary_Value_Out_Of_Service[object_index] = value.type.Boolean;
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
#endif
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
@@ -288,7 +302,8 @@ bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
#include <string.h>
#include "ctest.h"
void testBinary_Value(Test * pTest)
void testBinary_Value(
Test * pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
int len = 0;
@@ -303,8 +318,7 @@ void testBinary_Value(Test * pTest)
len = Binary_Value_Encode_Property_APDU(&apdu[0],
instance,
PROP_OBJECT_IDENTIFIER,
BACNET_ARRAY_ALL, &error_class, &error_code);
PROP_OBJECT_IDENTIFIER, BACNET_ARRAY_ALL, &error_class, &error_code);
ct_test(pTest, len != 0);
len = decode_tag_number_and_value(&apdu[0], &tag_number, &len_value);
ct_test(pTest, tag_number == BACNET_APPLICATION_TAG_OBJECT_ID);
@@ -317,7 +331,8 @@ void testBinary_Value(Test * pTest)
}
#ifdef TEST_BINARY_VALUE
int main(void)
int main(
void)
{
Test *pTest;
bool rc;
@@ -334,5 +349,5 @@ int main(void)
return 0;
}
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
#endif /* TEST_BINARY_VALUE */
#endif /* TEST */
+337 -299
View File
@@ -25,14 +25,14 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <string.h> /* for memmove */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacstr.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "device.h" /* me */
#include "device.h" /* me */
#include "dlmstp.h"
#include "rs485.h"
#include "ai.h"
@@ -53,13 +53,15 @@ static BACNET_DEVICE_STATUS System_Status = STATUS_OPERATIONAL;
BACNET_REINITIALIZED_STATE_OF_DEVICE Reinitialize_State =
REINITIALIZED_STATE_IDLE;
void Device_Reinit(void)
void Device_Reinit(
void)
{
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
Device_Set_Object_Instance_Number(BACNET_MAX_INSTANCE);
}
void Device_Init(void)
void Device_Init(
void)
{
Reinitialize_State = REINITIALIZED_STATE_IDLE;
dcc_set_status_duration(COMMUNICATION_ENABLE, 0);
@@ -71,14 +73,16 @@ void Device_Init(void)
}
/* methods to manipulate the data */
uint32_t Device_Object_Instance_Number(void)
uint32_t Device_Object_Instance_Number(
void)
{
return Object_Instance_Number;
}
bool Device_Set_Object_Instance_Number(uint32_t object_id)
bool Device_Set_Object_Instance_Number(
uint32_t object_id)
{
bool status = true; /* return value */
bool status = true; /* return value */
if (object_id <= BACNET_MAX_INSTANCE) {
Object_Instance_Number = object_id;
@@ -94,71 +98,83 @@ bool Device_Set_Object_Instance_Number(uint32_t object_id)
return status;
}
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
{
/* BACnet allows for a wildcard instance number */
return ((Object_Instance_Number == object_id) ||
(object_id == BACNET_MAX_INSTANCE));
}
BACNET_DEVICE_STATUS Device_System_Status(void)
BACNET_DEVICE_STATUS Device_System_Status(
void)
{
return System_Status;
}
void Device_Set_System_Status(BACNET_DEVICE_STATUS status)
void Device_Set_System_Status(
BACNET_DEVICE_STATUS status)
{
if (status < MAX_DEVICE_STATUS)
System_Status = status;
}
uint16_t Device_Vendor_Identifier(void)
uint16_t Device_Vendor_Identifier(
void)
{
return BACNET_VENDOR_ID;
}
uint8_t Device_Protocol_Version(void)
uint8_t Device_Protocol_Version(
void)
{
return 1;
}
uint8_t Device_Protocol_Revision(void)
uint8_t Device_Protocol_Revision(
void)
{
return 5;
}
/* FIXME: MAX_APDU is defined in config.ini - set it! */
uint16_t Device_Max_APDU_Length_Accepted(void)
uint16_t Device_Max_APDU_Length_Accepted(
void)
{
return MAX_APDU;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
BACNET_SEGMENTATION Device_Segmentation_Supported(
void)
{
return SEGMENTATION_NONE;
}
uint16_t Device_APDU_Timeout(void)
uint16_t Device_APDU_Timeout(
void)
{
return 60000;
}
uint8_t Device_Number_Of_APDU_Retries(void)
uint8_t Device_Number_Of_APDU_Retries(
void)
{
return 0;
}
uint8_t Device_Database_Revision(void)
uint8_t Device_Database_Revision(
void)
{
return 0;
}
/* Since many network clients depend on the object list */
/* for discovery, it must be consistent! */
unsigned Device_Object_List_Count(void)
unsigned Device_Object_List_Count(
void)
{
unsigned count = 1; /* at least 1 for device object */
unsigned count = 1; /* at least 1 for device object */
/* FIXME: add objects as needed */
count += Binary_Value_Count();
@@ -171,8 +187,10 @@ unsigned Device_Object_List_Count(void)
/* Since many network clients depend on the object list */
/* for discovery, it must be consistent! */
bool Device_Object_List_Identifier(unsigned array_index,
int *object_type, uint32_t * instance)
bool Device_Object_List_Identifier(
unsigned array_index,
int *object_type,
uint32_t * instance)
{
bool status = false;
unsigned object_index = 0;
@@ -242,13 +260,15 @@ bool Device_Object_List_Identifier(unsigned array_index,
}
/* return the length of the apdu encoded or -1 for error */
int Device_Encode_Property_APDU(uint8_t * apdu,
int Device_Encode_Property_APDU(
uint8_t * apdu,
BACNET_PROPERTY_ID property,
int32_t array_index,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
int apdu_len = 0; /* return value */
int len = 0; /* apdu len intermediate value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned i = 0;
@@ -263,208 +283,226 @@ int Device_Encode_Property_APDU(uint8_t * apdu,
/* FIXME: change the hardcoded names to suit your application */
switch (property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
(void) strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
(void) strcpypgm2ram(&string_buffer[0], "BACnet Demo");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_SYSTEM_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0], Device_System_Status());
break;
case PROP_VENDOR_NAME:
(void) strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
(void) strcpypgm2ram(&string_buffer[0], "GNU Demo");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
(void) strcpypgm2ram(&string_buffer[0], "1.0");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_LOCATION:
(void) strcpypgm2ram(&string_buffer[0], "USA");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len = encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Protocol_Version());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
case PROP_OBJECT_IDENTIFIER:
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
(void) strcpypgm2ram(&string_buffer[0], "PIC18F6720 Device");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_DEVICE);
break;
case PROP_DESCRIPTION:
(void) strcpypgm2ram(&string_buffer[0], "BACnet Demo");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_SYSTEM_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
Device_System_Status());
break;
case PROP_VENDOR_NAME:
(void) strcpypgm2ram(&string_buffer[0], BACNET_VENDOR_NAME);
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Vendor_Identifier());
break;
case PROP_MODEL_NAME:
(void) strcpypgm2ram(&string_buffer[0], "GNU Demo");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FIRMWARE_REVISION:
characterstring_init_ansi(&char_string, BACnet_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
(void) strcpypgm2ram(&string_buffer[0], "1.0");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_LOCATION:
(void) strcpypgm2ram(&string_buffer[0], "USA");
characterstring_init_ansi(&char_string, string_buffer);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Version());
break;
case PROP_PROTOCOL_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Protocol_Revision());
break;
/* BACnet Legacy Support */
case PROP_PROTOCOL_CONFORMANCE_CLASS:
apdu_len = encode_application_unsigned(&apdu[0], 1);
break;
case PROP_PROTOCOL_SERVICES_SUPPORTED:
/* Note: list of services that are executed, not initiated. */
bitstring_init(&bit_string);
for (i = 0; i < MAX_BACNET_SERVICES_SUPPORTED; i++) {
/* automatic lookup based on handlers set */
bitstring_set_bit(&bit_string, (uint8_t) i,
apdu_service_supported(i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED:
/* Note: this is the list of objects that can be in this device,
not a list of objects that this device can access */
bitstring_init(&bit_string);
for (i = 0; i < MAX_ASHRAE_OBJECT_TYPE; i++) {
/* initialize all the object types to not-supported */
bitstring_set_bit(&bit_string, (uint8_t) i, false);
}
/* FIXME: indicate the objects that YOU support */
bitstring_set_bit(&bit_string, OBJECT_DEVICE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_VALUE, true);
bitstring_set_bit(&bit_string, OBJECT_ANALOG_INPUT, true);
bitstring_set_bit(&bit_string, OBJECT_BINARY_INPUT, true);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_OBJECT_LIST:
count = Device_Object_List_Count();
/* Array element zero is the number of objects in the list */
if (array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], count);
/* if no index was specified, then try to encode the entire list */
/* into one packet. Note that more than likely you will have */
/* to return an error if the number of encoded objects exceeds */
/* your maximum APDU size. */
else if (array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
if (Device_Object_List_Identifier(i, &object_type,
&instance)) {
len =
encode_application_object_id(&apdu[apdu_len],
object_type, instance);
apdu_len += len;
/* assume next one is the same size as this one */
/* can we all fit into the APDU? */
if ((apdu_len + len) >= MAX_APDU) {
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_NO_SPACE_FOR_OBJECT;
*error_code = ERROR_CODE_OTHER;
apdu_len = -1;
break;
}
} else {
/* error: internal error? */
*error_class = ERROR_CLASS_SERVICES;
*error_code = ERROR_CODE_OTHER;
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
break;
}
}
} else {
if (Device_Object_List_Identifier(array_index, &object_type,
&instance))
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = -1;
}
}
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Device_Database_Revision());
break;
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len = encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
case PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* EST */ );
break;
case PROP_LOCAL_DATE:
/* FIXME: if you support date */
local_date.year = 2006; /* AD */
local_date.month = 4; /* Jan=1..Dec=12 */
local_date.day = 11; /* 1..31 */
local_date.wday = 0; /* 1=Mon..7=Sun */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len = encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
break;
case PROP_MAX_APDU_LENGTH_ACCEPTED:
apdu_len = encode_application_unsigned(&apdu[0],
Device_Max_APDU_Length_Accepted());
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len = encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len =
encode_application_unsigned(&apdu[0], Device_APDU_Timeout());
break;
case PROP_NUMBER_OF_APDU_RETRIES:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Number_Of_APDU_Retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: encode the list here, if it exists */
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_Database_Revision());
break;
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0],
dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len =
encode_application_unsigned(&apdu[0], dlmstp_max_master());
break;
case PROP_LOCAL_TIME:
/* FIXME: if you support time */
local_time.hour = 0;
local_time.min = 0;
local_time.sec = 0;
local_time.hundredths = 0;
apdu_len = encode_application_time(&apdu[0], &local_time);
break;
case PROP_UTC_OFFSET:
/* Note: BACnet Time Zone is inverse of everybody else */
apdu_len = encode_application_signed(&apdu[0], 5 /* EST */ );
break;
case PROP_LOCAL_DATE:
/* FIXME: if you support date */
local_date.year = 2006; /* AD */
local_date.month = 4; /* Jan=1..Dec=12 */
local_date.day = 11; /* 1..31 */
local_date.wday = 0; /* 1=Mon..7=Sun */
apdu_len = encode_application_date(&apdu[0], &local_date);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
/* FIXME: if you support time/date */
apdu_len = encode_application_boolean(&apdu[0], false);
break;
case 9600:
apdu_len =
encode_application_unsigned(&apdu[0], RS485_Get_Baud_Rate());
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_UNKNOWN_PROPERTY;
apdu_len = -1;
break;
}
return apdu_len;
}
bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class, BACNET_ERROR_CODE * error_code)
bool Device_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
{
bool status = false; /* return value */
int len = 0;
@@ -481,98 +519,98 @@ bool Device_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data,
/* FIXME: len < application_data_len: more data? */
/* FIXME: len == 0: unable to decode? */
switch (wp_data->object_property) {
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
case PROP_OBJECT_IDENTIFIER:
if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* we could send an I-Am broadcast to let the world know */
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
break;
case PROP_MAX_INFO_FRAMES:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int <= 255) {
dlmstp_set_max_info_frames(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
} else {
break;
case PROP_MAX_MASTER:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if ((value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= 127)) {
dlmstp_set_max_master(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_OBJECT_NAME:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
uint8_t encoding;
size_t len;
encoding =
characterstring_encoding(&value.type.Character_String);
len = characterstring_length(&value.type.Character_String);
if (encoding == CHARACTER_ANSI_X34) {
if (len <= 20) {
/* FIXME: set the name */
/* Display_Set_Name(
characterstring_value(&value.type.Character_String)); */
/* FIXME: All the object names in a device must be unique.
Disallow setting the Device Object Name to any objects in
the device. */
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case 9600:
if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) {
if (value.type.Unsigned_Int > 115200) {
RS485_Set_Baud_Rate(value.type.Unsigned_Int);
status = true;
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
default:
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;
}
return status;
+49 -33
View File
@@ -49,12 +49,14 @@ volatile struct mstp_port_struct_t MSTP_Port;
#define INCREMENT_AND_LIMIT_UINT16(x) {if (x < 0xFFFF) x++;}
void dlmstp_millisecond_timer(void)
void dlmstp_millisecond_timer(
void)
{
INCREMENT_AND_LIMIT_UINT16(MSTP_Port.SilenceTimer);
}
void dlmstp_reinit(void)
void dlmstp_reinit(
void)
{
RS485_Reinit();
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
@@ -62,7 +64,8 @@ void dlmstp_reinit(void)
dlmstp_set_max_master(DEFAULT_MAX_MASTER);
}
void dlmstp_init(void)
void dlmstp_init(
void)
{
uint8_t data;
@@ -74,17 +77,17 @@ void dlmstp_init(void)
MSTP_Port.InputBuffer = &Receive_Buffer.pdu[0];
MSTP_Init(&MSTP_Port);
/* FIXME: implement your data storage */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
data = 64; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAC_ADDR); */
if (data <= 127)
MSTP_Port.This_Station = data;
else
dlmstp_set_my_address(DEFAULT_MAC_ADDRESS);
/* FIXME: implement your data storage */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
data = 127; /* I2C_Read_Byte(
EEPROM_DEVICE_ADDRESS,
EEPROM_MSTP_MAX_MASTER_ADDR); */
if ((data <= 127) && (data >= MSTP_Port.This_Station))
MSTP_Port.Nmax_master = data;
else
@@ -100,30 +103,31 @@ void dlmstp_init(void)
dlmstp_set_max_info_frames(DEFAULT_MAX_INFO_FRAMES);
}
void dlmstp_cleanup(void)
void dlmstp_cleanup(
void)
{
/* nothing to do for static buffers */
}
/* returns number of bytes sent on success, zero on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
int dlmstp_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len)
{ /* number of bytes of data */
{ /* number of bytes of data */
int bytes_sent = 0;
unsigned npdu_len = 0;
uint8_t frame_type = 0;
uint8_t destination = 0; /* destination address */
BACNET_ADDRESS src;
unsigned i = 0; /* loop counter */
unsigned i = 0; /* loop counter */
if (MSTP_Port.TxReady == false) {
if (npdu_data->data_expecting_reply)
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_EXPECTING_REPLY;
else
MSTP_Port.TxFrameType =
FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
MSTP_Port.TxFrameType = FRAME_TYPE_BACNET_DATA_NOT_EXPECTING_REPLY;
/* load destination MAC address */
if (dest && dest->mac_len == 1) {
@@ -148,7 +152,8 @@ int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
return bytes_sent;
}
void dlmstp_task(void)
void dlmstp_task(
void)
{
uint8_t bytes_remaining;
bool received_frame;
@@ -184,7 +189,9 @@ void dlmstp_task(void)
return;
}
void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_address)
void dlmstp_fill_bacnet_address(
BACNET_ADDRESS * src,
uint8_t mstp_address)
{
int i = 0;
@@ -208,17 +215,19 @@ void dlmstp_fill_bacnet_address(BACNET_ADDRESS * src, uint8_t mstp_address)
}
/* for the MS/TP state machine to use for putting received data */
uint16_t dlmstp_put_receive(uint8_t src, /* source MS/TP address */
uint8_t * pdu, /* PDU data */
uint16_t dlmstp_put_receive(
uint8_t src, /* source MS/TP address */
uint8_t * pdu, /* PDU data */
uint16_t pdu_len)
{ /* amount of PDU data */
{ /* amount of PDU data */
/* PDU is already in the Receive_Buffer */
dlmstp_fill_bacnet_address(&Receive_Buffer.address, src);
Receive_Buffer.pdu_len = pdu_len;
Receive_Buffer.ready = true;
}
void dlmstp_set_my_address(uint8_t mac_address)
void dlmstp_set_my_address(
uint8_t mac_address)
{
/* Master Nodes can only have address 0-127 */
if (mac_address <= 127) {
@@ -235,7 +244,8 @@ void dlmstp_set_my_address(uint8_t mac_address)
return;
}
uint8_t dlmstp_my_address(void)
uint8_t dlmstp_my_address(
void)
{
return MSTP_Port.This_Station;
}
@@ -247,7 +257,8 @@ uint8_t dlmstp_my_address(void)
/* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */
void dlmstp_set_max_info_frames(uint8_t max_info_frames)
void dlmstp_set_max_info_frames(
uint8_t max_info_frames)
{
if (max_info_frames >= 1) {
MSTP_Port.Nmax_info_frames = max_info_frames;
@@ -261,7 +272,8 @@ void dlmstp_set_max_info_frames(uint8_t max_info_frames)
return;
}
unsigned dlmstp_max_info_frames(void)
unsigned dlmstp_max_info_frames(
void)
{
return MSTP_Port.Nmax_info_frames;
}
@@ -271,7 +283,8 @@ unsigned dlmstp_max_info_frames(void)
/* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */
void dlmstp_set_max_master(uint8_t max_master)
void dlmstp_set_max_master(
uint8_t max_master)
{
if (max_master <= 127) {
if (MSTP_Port.This_Station <= max_master) {
@@ -287,14 +300,16 @@ void dlmstp_set_max_master(uint8_t max_master)
return;
}
uint8_t dlmstp_max_master(void)
uint8_t dlmstp_max_master(
void)
{
return MSTP_Port.Nmax_master;
}
void dlmstp_get_my_address(BACNET_ADDRESS * my_address)
void dlmstp_get_my_address(
BACNET_ADDRESS * my_address)
{
int i = 0; /* counter */
int i = 0; /* counter */
my_address->mac_len = 1;
my_address->mac[0] = MSTP_Port.This_Station;
@@ -307,15 +322,16 @@ void dlmstp_get_my_address(BACNET_ADDRESS * my_address)
return;
}
void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
void dlmstp_get_broadcast_address(
BACNET_ADDRESS * dest)
{ /* destination address */
int i = 0; /* counter */
if (dest) {
dest->mac_len = 1;
dest->mac[0] = MSTP_BROADCAST_ADDRESS;
dest->net = BACNET_BROADCAST_NETWORK;
dest->len = 0; /* always zero when DNET is broadcast */
dest->len = 0; /* always zero when DNET is broadcast */
for (i = 0; i < MAX_MAC_LEN; i++) {
dest->adr[i] = 0;
}
+37 -22
View File
@@ -46,10 +46,10 @@
#define MAX_MPDU (MAX_HEADER+MAX_PDU)
typedef struct dlmstp_packet {
bool ready; /* true if ready to be sent or received */
bool ready; /* true if ready to be sent or received */
BACNET_ADDRESS address; /* source address */
uint8_t frame_type; /* type of message */
unsigned pdu_len; /* packet length */
uint8_t frame_type; /* type of message */
unsigned pdu_len; /* packet length */
uint8_t pdu[MAX_MPDU]; /* packet */
} DLMSTP_PACKET;
@@ -58,18 +58,24 @@ extern uint16_t MSTP_Packets;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void dlmstp_reinit(void);
void dlmstp_init(void);
void dlmstp_cleanup(void);
void dlmstp_millisecond_timer(void);
void dlmstp_task(void);
void dlmstp_reinit(
void);
void dlmstp_init(
void);
void dlmstp_cleanup(
void);
void dlmstp_millisecond_timer(
void);
void dlmstp_task(
void);
/* returns number of bytes sent on success, negative on failure */
int dlmstp_send_pdu(BACNET_ADDRESS * dest, /* destination address */
int dlmstp_send_pdu(
BACNET_ADDRESS * dest, /* destination address */
BACNET_NPDU_DATA * npdu_data, /* network information */
uint8_t * pdu, /* any data to be sent - may be null */
uint8_t * pdu, /* any data to be sent - may be null */
unsigned pdu_len); /* number of bytes of data */
/* This parameter represents the value of the Max_Info_Frames property of */
@@ -79,32 +85,41 @@ extern "C" {
/* nodes. This may be used to allocate more or less of the available link */
/* bandwidth to particular nodes. If Max_Info_Frames is not writable in a */
/* node, its value shall be 1. */
void dlmstp_set_max_info_frames(uint8_t max_info_frames);
unsigned dlmstp_max_info_frames(void);
void dlmstp_set_max_info_frames(
uint8_t max_info_frames);
unsigned dlmstp_max_info_frames(
void);
/* This parameter represents the value of the Max_Master property of the */
/* node's Device object. The value of Max_Master specifies the highest */
/* allowable address for master nodes. The value of Max_Master shall be */
/* less than or equal to 127. If Max_Master is not writable in a node, */
/* its value shall be 127. */
void dlmstp_set_max_master(uint8_t max_master);
uint8_t dlmstp_max_master(void);
void dlmstp_set_max_master(
uint8_t max_master);
uint8_t dlmstp_max_master(
void);
/* MAC address for MS/TP */
void dlmstp_set_my_address(uint8_t my_address);
uint8_t dlmstp_my_address(void);
void dlmstp_set_my_address(
uint8_t my_address);
uint8_t dlmstp_my_address(
void);
/* BACnet address used in datalink */
void dlmstp_get_my_address(BACNET_ADDRESS * my_address);
void dlmstp_get_broadcast_address(BACNET_ADDRESS * dest); /* destination address */
void dlmstp_get_my_address(
BACNET_ADDRESS * my_address);
void dlmstp_get_broadcast_address(
BACNET_ADDRESS * dest); /* destination address */
/* MS/TP state machine functions */
uint16_t dlmstp_put_receive(uint8_t src, /* source MS/TP address */
uint8_t * pdu, /* PDU data */
uint16_t dlmstp_put_receive(
uint8_t src, /* source MS/TP address */
uint8_t * pdu, /* PDU data */
uint16_t pdu_len);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+92 -90
View File
@@ -46,9 +46,11 @@
static uint8_t Temp_Buf[MAX_APDU] = { 0 };
void handler_read_property(uint8_t * service_request,
void handler_read_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
BACNET_READ_PROPERTY_DATA data;
int len = 0;
@@ -83,98 +85,98 @@ void handler_read_property(uint8_t * service_request,
/* most cases will be error */
error = true;
switch (data.object_type) {
case OBJECT_DEVICE:
/* FIXME: probably need a length limitation sent with encode */
if (Device_Valid_Object_Instance_Number(data.object_instance)) {
len = Device_Encode_Property_APDU(&Temp_Buf[0],
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
case OBJECT_DEVICE:
/* FIXME: probably need a length limitation sent with encode */
if (Device_Valid_Object_Instance_Number(data.object_instance)) {
len = Device_Encode_Property_APDU(&Temp_Buf[0],
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance)) {
len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_ANALOG_INPUT:
if (Analog_Input_Valid_Instance(data.object_instance)) {
len = Analog_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(data.object_instance)) {
len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_BINARY_INPUT:
if (Binary_Input_Valid_Instance(data.object_instance)) {
len = Binary_Input_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(data.object_instance)) {
len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Valid_Instance(data.object_instance)) {
len = Binary_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(data.object_instance)) {
len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Valid_Instance(data.object_instance)) {
len = Analog_Value_Encode_Property_APDU(&Temp_Buf[0],
data.object_instance,
data.object_property,
data.array_index, &error_class, &error_code);
if (len >= 0) {
/* encode the APDU portion of the packet */
data.application_data = &Temp_Buf[0];
data.application_data_len = len;
/* FIXME: probably need a length limitation sent with encode */
len =
rp_ack_encode_apdu(&Handler_Transmit_Buffer
[pdu_len], service_data->invoke_id, &data);
error = false;
}
}
}
break;
default:
break;
break;
default:
break;
}
if (error) {
if (len == -2) {
@@ -188,7 +190,7 @@ void handler_read_property(uint8_t * service_request,
service_data->invoke_id,
SERVICE_CONFIRMED_READ_PROPERTY, error_class, error_code);
}
RP_ABORT:
RP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+86 -94
View File
@@ -45,9 +45,11 @@
/* too big to reside on stack frame for PIC */
static BACNET_WRITE_PROPERTY_DATA wp_data;
void handler_write_property(uint8_t * service_request,
void handler_write_property(
uint8_t * service_request,
uint16_t service_len,
BACNET_ADDRESS * src, BACNET_CONFIRMED_SERVICE_DATA * service_data)
BACNET_ADDRESS * src,
BACNET_CONFIRMED_SERVICE_DATA * service_data)
{
int len = 0;
int pdu_len = 0;
@@ -69,104 +71,94 @@ void handler_write_property(uint8_t * service_request,
goto WP_ABORT;
}
/* decode the service request only */
len = wp_decode_service_request(service_request,
service_len, &wp_data);
len = wp_decode_service_request(service_request, service_len, &wp_data);
/* bad decoding or something we didn't understand - send an abort */
if (len <= 0) {
len = abort_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, ABORT_REASON_OTHER, true);
goto WP_ABORT;
}
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class,
error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for AV!\n");
#endif
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
switch (wp_data.object_type) {
case OBJECT_DEVICE:
if (Device_Write_Property(&wp_data, &error_class, &error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr,
"Sending Write Property Simple Ack for Device!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Error for Device!\n");
#endif
}
break;
case OBJECT_ANALOG_INPUT:
case OBJECT_BINARY_INPUT:
error_class = ERROR_CLASS_PROPERTY;
error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error!\n");
#endif
break;
case OBJECT_BINARY_VALUE:
if (Binary_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Simple Ack for BV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for BV!\n");
#endif
}
break;
case OBJECT_ANALOG_VALUE:
if (Analog_Value_Write_Property(&wp_data, &error_class,
&error_code)) {
len =
encode_simple_ack(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Property Simple Ack for AV!\n");
#endif
} else {
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id,
SERVICE_CONFIRMED_WRITE_PROPERTY, error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Write Access Error for AV!\n");
#endif
}
break;
default:
len =
bacerror_encode_apdu(&Handler_Transmit_Buffer[pdu_len],
service_data->invoke_id, SERVICE_CONFIRMED_WRITE_PROPERTY,
error_class, error_code);
#if PRINT_ENABLED
fprintf(stderr, "Sending Unknown Object Error!\n");
#endif
break;
}
WP_ABORT:
pdu_len += len;
bytes_sent = datalink_send_pdu(src, &npdu_data,
&Handler_Transmit_Buffer[0], pdu_len);
+19 -19
View File
@@ -132,8 +132,8 @@ typedef union {
uint8_t Program:1;
uint8_t Run:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input1:1;
uint8_t Input2:1;
uint8_t Input3:1;
@@ -141,35 +141,35 @@ typedef union {
uint8_t Input5:1;
uint8_t Input6:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input7:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Input8:1;
uint8_t Photocell:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Remote:1;
uint8_t Relay8:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Relay7:1;
uint8_t Relay6:1;
uint8_t Relay5:1;
uint8_t Relay4:1;
uint8_t Relay3:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t:1;
uint8_t Relay2:1;
uint8_t Relay1:1;
uint8_t Holiday:1;
@@ -268,4 +268,4 @@ extern volatile LED_REGS Blink;
extern uint8_t Piezo_Timer;
extern volatile bool DataPortLocked;
#endif /* HARDWARE_H */
#endif /* HARDWARE_H */
+34 -17
View File
@@ -31,30 +31,42 @@
/* from main.c */
extern volatile uint8_t Milliseconds;
void InterruptHandlerHigh(void);
void InterruptHandlerLow(void);
void Interrupt_Timer2(void);
void Interrupt_Timer3(void);
void Interrupt_Timer4(void);
void Interrupt_USART_Rx(void);
void Interrupt_USART_Tx(void);
void Interrupt_CCP2(void);
void INT0_Interrupt(void);
void InterruptHandlerHigh(
void);
void InterruptHandlerLow(
void);
void Interrupt_Timer2(
void);
void Interrupt_Timer3(
void);
void Interrupt_Timer4(
void);
void Interrupt_USART_Rx(
void);
void Interrupt_USART_Tx(
void);
void Interrupt_CCP2(
void);
void INT0_Interrupt(
void);
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh(void)
void InterruptVectorHigh(
void)
{
/* jump to interrupt routine */
_asm goto InterruptHandlerHigh _endasm}
#pragma code
#pragma code InterruptVectorLow = 0x18
void InterruptVectorLow(void)
void InterruptVectorLow(
void)
{
/* jump to interrupt routine */
_asm goto InterruptHandlerLow _endasm}
#pragma code
#pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh(void)
void InterruptHandlerHigh(
void)
{
#if 0
/* check for USART Rx int */
@@ -84,7 +96,8 @@ void InterruptHandlerHigh(void)
#pragma interruptlow InterruptHandlerLow save = PROD, section(".tmpdata"), TABLAT, TBLPTR, section \
("MATH_DATA")
void InterruptHandlerLow(void)
void InterruptHandlerLow(
void)
{
/* check for timer2 int */
if ((PIR1bits.TMR2IF) && (PIE1bits.TMR2IE)) {
@@ -168,23 +181,27 @@ void InterruptHandlerLow(void)
*/
}
void Interrupt_Timer2(void)
void Interrupt_Timer2(
void)
{
}
void Interrupt_Timer3(void)
void Interrupt_Timer3(
void)
{
}
/* Timer4 is set to go off every 1ms. This is our system tick */
void Interrupt_Timer4(void)
void Interrupt_Timer4(
void)
{
/* Milisecond is our system tick */
if (Milliseconds < 0xFF)
++Milliseconds;
}
void Interrupt_CCP2(void)
void Interrupt_CCP2(
void)
{
}
+33 -28
View File
@@ -25,7 +25,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <string.h> /* for memmove */
#include <p18F6720.h>
#include <stdlib.h>
#include <string.h>
@@ -87,16 +87,16 @@
#else
#pragma config WDT = ON, WDTPS = 128
#pragma config DEBUG = OFF
#endif /* USE_ICD */
#endif /* USE_ICD */
volatile uint8_t Milliseconds = 0;
volatile uint8_t Zero_Cross_Timeout = 0;
static void BACnet_Service_Handlers_Init(void)
static void BACnet_Service_Handlers_Init(
void)
{
/* we need to handle who-is to support dynamic device binding */
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS,
handler_who_is);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
/* Set the handlers for any confirmed services that we support. */
/* We must implement read property - it's required! */
apdu_set_confirmed_handler(SERVICE_CONFIRMED_READ_PROPERTY,
@@ -107,8 +107,7 @@ static void BACnet_Service_Handlers_Init(void)
handler_write_property);
#if 0
apdu_set_unconfirmed_handler
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION,
handler_timesync_utc);
(SERVICE_UNCONFIRMED_UTC_TIME_SYNCHRONIZATION, handler_timesync_utc);
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_TIME_SYNCHRONIZATION,
handler_timesync);
#endif
@@ -118,7 +117,8 @@ static void BACnet_Service_Handlers_Init(void)
handler_device_communication_control);
}
void Reinitialize(void)
void Reinitialize(
void)
{
uint8_t i;
char name = 0;
@@ -126,30 +126,32 @@ void Reinitialize(void)
_asm reset _endasm return;
}
void Global_Int(enum INT_STATE state)
void Global_Int(
enum INT_STATE state)
{
static uint8_t intstate = 0;
switch (state) {
case INT_DISABLED:
intstate >>= 2;
intstate |= (INTCON & 0xC0);
break;
case INT_ENABLED:
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
intstate <<= 2;
break;
case INT_RESTORE:
INTCON |= (intstate & 0xC0);
intstate <<= 2;
break;
default:
break;
case INT_DISABLED:
intstate >>= 2;
intstate |= (INTCON & 0xC0);
break;
case INT_ENABLED:
INTCONbits.GIE = 1;
INTCONbits.PEIE = 1;
intstate <<= 2;
break;
case INT_RESTORE:
INTCON |= (intstate & 0xC0);
intstate <<= 2;
break;
default:
break;
}
}
void Hardware_Initialize(void)
void Hardware_Initialize(
void)
{
/* PORTA.0 Input - Photocell PORTA.1 Output - LED Row6 PORTA.2 Output
* - LED Row5 PORTA.3 Output - LED Row4 PORTA.4 Input - Square Wave
@@ -247,7 +249,8 @@ void Hardware_Initialize(void)
Global_Int(INT_ENABLED);
}
void Initialize_Variables(void)
void Initialize_Variables(
void)
{
/* Check to see if we need to initialize our eeproms */
ENABLE_TIMER4_INT();
@@ -259,7 +262,8 @@ void Initialize_Variables(void)
Milliseconds = 0;
}
void MainTasks(void)
void MainTasks(
void)
{
static uint16_t millisecond_counter = 0;
/* Handle our millisecond counters */
@@ -274,7 +278,8 @@ void MainTasks(void)
}
}
void main(void)
void main(
void)
{
RCONbits.NOT_POR = 1;
RCONbits.NOT_RI = 1;
File diff suppressed because it is too large Load Diff
+15 -10
View File
@@ -199,7 +199,7 @@ struct mstp_port_struct_t {
/* This array is only used for APDU messages */
uint8_t TxBuffer[MAX_MPDU];
unsigned TxLength;
bool TxReady; /* true if ready to be sent or received */
bool TxReady; /* true if ready to be sent or received */
uint8_t TxFrameType; /* type of message - needed by MS/TP */
};
@@ -220,27 +220,32 @@ struct mstp_port_struct_t {
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void MSTP_Init(volatile struct mstp_port_struct_t *mstp_port);
void MSTP_Receive_Frame_FSM(volatile struct mstp_port_struct_t
void MSTP_Init(
volatile struct mstp_port_struct_t *mstp_port);
void MSTP_Receive_Frame_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
bool MSTP_Master_Node_FSM(volatile struct mstp_port_struct_t
bool MSTP_Master_Node_FSM(
volatile struct mstp_port_struct_t
*mstp_port);
/* returns true if line is active */
bool MSTP_Line_Active(volatile struct mstp_port_struct_t *mstp_port);
bool MSTP_Line_Active(
volatile struct mstp_port_struct_t *mstp_port);
unsigned MSTP_Create_Frame(uint8_t * buffer, /* where frame is loaded */
unsigned MSTP_Create_Frame(
uint8_t * buffer, /* where frame is loaded */
unsigned buffer_len, /* amount of space available */
uint8_t frame_type, /* type of frame to send - see defines */
uint8_t destination, /* destination address */
uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */
uint8_t source, /* source address */
uint8_t * data, /* any data to be sent - may be null */
unsigned data_len); /* number of bytes of data (up to 501) */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+65 -56
View File
@@ -57,11 +57,12 @@ volatile uint8_t RS485_Tx_Buffer[MAX_MPDU];
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
void RS485_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes)
{ /* number of bytes of data (up to 501) */
uint16_t i = 0; /* loop counter */
{ /* number of bytes of data (up to 501) */
uint16_t i = 0; /* loop counter */
uint8_t turnaround_time;
if (!buffer)
@@ -117,8 +118,8 @@ void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
mstp_port)
uint8_t RS485_Check_UART_Data(
volatile struct mstp_port_struct_t * mstp_port)
{
/* check for data */
if (RS485_Comstat.Rx_Bytes) {
@@ -151,7 +152,8 @@ uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Rx(void)
void RS485_Interrupt_Rx(
void)
{
char dummy;
@@ -184,7 +186,8 @@ void RS485_Interrupt_Rx(void)
NOTES: none
*************************************************************************** */
void RS485_Interrupt_Tx(void)
void RS485_Interrupt_Tx(
void)
{
if (RS485_Comstat.Tx_Bytes) {
/* Get the data byte */
@@ -214,7 +217,8 @@ void RS485_Interrupt_Tx(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
uint32_t RS485_Get_Baud_Rate(void)
uint32_t RS485_Get_Baud_Rate(
void)
{
return RS485_Baud_Rate;
}
@@ -225,22 +229,23 @@ uint32_t RS485_Get_Baud_Rate(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool RS485_Set_Baud_Rate(uint32_t baud)
bool RS485_Set_Baud_Rate(
uint32_t baud)
{
bool valid = true;
switch (baud) {
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
RS485_Baud_Rate = baud;
break;
default:
valid = false;
break;
case 9600:
case 19200:
case 38400:
case 57600:
case 76800:
case 115200:
RS485_Baud_Rate = baud;
break;
default:
valid = false;
break;
}
if (valid) {
@@ -262,7 +267,8 @@ bool RS485_Set_Baud_Rate(uint32_t baud)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize_Port(void)
void RS485_Initialize_Port(
void)
{
/* Reset USART registers to POR state */
@@ -292,35 +298,35 @@ void RS485_Initialize_Port(void)
1250000 0
*/
switch (RS485_Baud_Rate) {
case 19200:
SPBRG2 = 64;
TXSTA2bits.BRGH = 1;
break;
case 38400:
SPBRG2 = 32;
TXSTA2bits.BRGH = 1;
break;
case 57600:
SPBRG2 = 21;
TXSTA2bits.BRGH = 1;
break;
case 76800:
SPBRG2 = 3;
TXSTA2bits.BRGH = 0;
break;
case 115200:
SPBRG2 = 10;
TXSTA2bits.BRGH = 1;
break;
case 9600:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
break;
default:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
RS485_Set_Baud_Rate(9600);
break;
case 19200:
SPBRG2 = 64;
TXSTA2bits.BRGH = 1;
break;
case 38400:
SPBRG2 = 32;
TXSTA2bits.BRGH = 1;
break;
case 57600:
SPBRG2 = 21;
TXSTA2bits.BRGH = 1;
break;
case 76800:
SPBRG2 = 3;
TXSTA2bits.BRGH = 0;
break;
case 115200:
SPBRG2 = 10;
TXSTA2bits.BRGH = 1;
break;
case 9600:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
break;
default:
SPBRG2 = 129;
TXSTA2bits.BRGH = 1;
RS485_Set_Baud_Rate(9600);
break;
}
/* select async mode */
TXSTA2bits.SYNC = 0;
@@ -341,14 +347,16 @@ void RS485_Initialize_Port(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Disable_Port(void)
void RS485_Disable_Port(
void)
{
RCSTA2 &= 0x4F; /* Disable the receiver */
RCSTA2 &= 0x4F; /* Disable the receiver */
TXSTA2bits.TXEN = 0; /* and transmitter */
PIE3 &= 0xCF; /* Disable both interrupts */
PIE3 &= 0xCF; /* Disable both interrupts */
}
void RS485_Reinit(void)
void RS485_Reinit(
void)
{
RS485_Set_Baud_Rate(38400);
}
@@ -359,7 +367,8 @@ void RS485_Reinit(void)
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void RS485_Initialize(void)
void RS485_Initialize(
void)
{
/* Init the Rs485 buffers */
RS485_Comstat.RxHead = 0;
+20 -11
View File
@@ -58,27 +58,36 @@ extern uint32_t RS485_Baud_Rate;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
void RS485_Reinit(void);
void RS485_Initialize(void);
void RS485_Reinit(
void);
void RS485_Initialize(
void);
void RS485_Disable(void);
void RS485_Disable(
void);
void RS485_Send_Frame(volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
void RS485_Send_Frame(
volatile struct mstp_port_struct_t *mstp_port, /* port specific data */
uint8_t * buffer, /* frame to send (up to 501 bytes of data) */
uint16_t nbytes); /* number of bytes of data (up to 501) */
uint8_t RS485_Check_UART_Data(volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
uint8_t RS485_Check_UART_Data(
volatile struct mstp_port_struct_t *mstp_port); /* port specific data */
void RS485_Interrupt_Rx(void);
void RS485_Interrupt_Rx(
void);
void RS485_Interrupt_Tx(void);
void RS485_Interrupt_Tx(
void);
uint32_t RS485_Get_Baud_Rate(void);
bool RS485_Set_Baud_Rate(uint32_t baud);
uint32_t RS485_Get_Baud_Rate(
void);
bool RS485_Set_Baud_Rate(
uint32_t baud);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __cplusplus */
#endif
+1 -1
View File
@@ -15,4 +15,4 @@ typedef signed long int32_t; /* 4 bytes -2147483647 to 2147483647 */
/* typedef signed long long int64_t; */
/* typedef unsigned long long uint64_t; */
#endif /* STDINT_H */
#endif /* STDINT_H */