added clang format C and H files.

This commit is contained in:
Steve Karg
2019-10-24 16:23:10 -05:00
parent da91a11454
commit 710173d6e0
205 changed files with 19377 additions and 25754 deletions
+113 -146
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the credential to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the credential to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access Credential Objects - customize for your use */
@@ -33,7 +33,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"
#include "access_credential.h"
#include "handlers.h"
@@ -43,35 +43,28 @@ static bool Access_Credential_Initialized = false;
static ACCESS_CREDENTIAL_DESCR ac_descr[MAX_ACCESS_CREDENTIALS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_CREDENTIAL_STATUS,
PROP_REASON_FOR_DISABLE,
PROP_AUTHENTICATION_FACTORS,
PROP_ACTIVATION_TIME,
PROP_EXPIRATION_TIME,
PROP_CREDENTIAL_DISABLE,
PROP_ASSIGNED_ACCESS_RIGHTS,
-1
};
static const int Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_CREDENTIAL_STATUS,
PROP_REASON_FOR_DISABLE,
PROP_AUTHENTICATION_FACTORS,
PROP_ACTIVATION_TIME,
PROP_EXPIRATION_TIME,
PROP_CREDENTIAL_DISABLE,
PROP_ASSIGNED_ACCESS_RIGHTS,
-1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_Credential_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_Credential_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -83,8 +76,7 @@ void Access_Credential_Property_Lists(
return;
}
void Access_Credential_Init(
void)
void Access_Credential_Init(void)
{
unsigned i;
@@ -92,7 +84,8 @@ void Access_Credential_Init(
Access_Credential_Initialized = true;
for (i = 0; i < MAX_ACCESS_CREDENTIALS; i++) {
ac_descr[i].global_identifier = 0; /* set to some meaningful value */
ac_descr[i].global_identifier =
0; /* set to some meaningful value */
ac_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED;
ac_descr[i].credential_status = false;
ac_descr[i].reasons_count = 0;
@@ -110,8 +103,7 @@ void Access_Credential_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_Credential_Valid_Instance(
uint32_t object_instance)
bool Access_Credential_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_CREDENTIALS)
return true;
@@ -121,8 +113,7 @@ bool Access_Credential_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_Credential_Count(
void)
unsigned Access_Credential_Count(void)
{
return MAX_ACCESS_CREDENTIALS;
}
@@ -130,8 +121,7 @@ unsigned Access_Credential_Count(
/* 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 Access_Credential_Index_To_Instance(
unsigned index)
uint32_t Access_Credential_Index_To_Instance(unsigned index)
{
return index;
}
@@ -139,8 +129,7 @@ uint32_t Access_Credential_Index_To_Instance(
/* 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 Access_Credential_Instance_To_Index(
uint32_t object_instance)
unsigned Access_Credential_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_CREDENTIALS;
@@ -151,16 +140,15 @@ unsigned Access_Credential_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Access_Credential_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_Credential_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_CREDENTIALS) {
sprintf(text_string, "ACCESS CREDENTIAL %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -168,11 +156,10 @@ bool Access_Credential_Object_Name(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Credential_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_Credential_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -184,29 +171,25 @@ int Access_Credential_Read_Property(
return 0;
}
apdu = rpdata->application_data;
object_index =
Access_Credential_Instance_To_Index(rpdata->object_instance);
object_index = Access_Credential_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_ACCESS_CREDENTIAL, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_CREDENTIAL, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_Credential_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_ACCESS_CREDENTIAL);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_ACCESS_CREDENTIAL);
break;
case PROP_GLOBAL_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
ac_descr[object_index].global_identifier);
apdu_len = encode_application_unsigned(
&apdu[0], ac_descr[object_index].global_identifier);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -217,20 +200,17 @@ int Access_Credential_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
ac_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], ac_descr[object_index].reliability);
break;
case PROP_CREDENTIAL_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
ac_descr[object_index].credential_status);
apdu_len = encode_application_enumerated(
&apdu[0], ac_descr[object_index].credential_status);
break;
case PROP_REASON_FOR_DISABLE:
for (i = 0; i < ac_descr[object_index].reasons_count; i++) {
len =
encode_application_enumerated(&apdu[0],
ac_descr[object_index].reason_for_disable[i]);
len = encode_application_enumerated(
&apdu[0], ac_descr[object_index].reason_for_disable[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -243,14 +223,13 @@ int Access_Credential_Read_Property(
break;
case PROP_AUTHENTICATION_FACTORS:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
ac_descr[object_index].auth_factors_count);
apdu_len = encode_application_unsigned(
&apdu[0], ac_descr[object_index].auth_factors_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0; i < ac_descr[object_index].auth_factors_count; i++) {
len =
bacapp_encode_credential_authentication_factor(&apdu
[0], &ac_descr[object_index].auth_factors[i]);
for (i = 0; i < ac_descr[object_index].auth_factors_count;
i++) {
len = bacapp_encode_credential_authentication_factor(
&apdu[0], &ac_descr[object_index].auth_factors[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -263,11 +242,9 @@ int Access_Credential_Read_Property(
} else {
if (rpdata->array_index <=
ac_descr[object_index].auth_factors_count) {
apdu_len =
bacapp_encode_credential_authentication_factor(&apdu
[0],
&ac_descr[object_index].
auth_factors[rpdata->array_index - 1]);
apdu_len = bacapp_encode_credential_authentication_factor(
&apdu[0], &ac_descr[object_index]
.auth_factors[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -276,31 +253,28 @@ int Access_Credential_Read_Property(
}
break;
case PROP_ACTIVATION_TIME:
apdu_len =
bacapp_encode_datetime(&apdu[0],
&ac_descr[object_index].activation_time);
apdu_len = bacapp_encode_datetime(
&apdu[0], &ac_descr[object_index].activation_time);
break;
case PROP_EXPIRATION_TIME:
apdu_len =
bacapp_encode_datetime(&apdu[0],
&ac_descr[object_index].expiration_time);
apdu_len = bacapp_encode_datetime(
&apdu[0], &ac_descr[object_index].expiration_time);
break;
case PROP_CREDENTIAL_DISABLE:
apdu_len =
encode_application_enumerated(&apdu[0],
ac_descr[object_index].credential_disable);
apdu_len = encode_application_enumerated(
&apdu[0], ac_descr[object_index].credential_disable);
break;
case PROP_ASSIGNED_ACCESS_RIGHTS:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
ac_descr[object_index].assigned_access_rights_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0;
i < ac_descr[object_index].assigned_access_rights_count;
i++) {
len =
bacapp_encode_assigned_access_rights(&apdu[0],
i < ac_descr[object_index].assigned_access_rights_count;
i++) {
len = bacapp_encode_assigned_access_rights(
&apdu[0],
&ac_descr[object_index].assigned_access_rights[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
@@ -314,10 +288,10 @@ int Access_Credential_Read_Property(
} else {
if (rpdata->array_index <=
ac_descr[object_index].assigned_access_rights_count) {
apdu_len =
bacapp_encode_assigned_access_rights(&apdu[0],
&ac_descr[object_index].
assigned_access_rights[rpdata->array_index - 1]);
apdu_len = bacapp_encode_assigned_access_rights(
&apdu[0],
&ac_descr[object_index]
.assigned_access_rights[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -333,9 +307,9 @@ int Access_Credential_Read_Property(
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(rpdata->object_property != PROP_AUTHENTICATION_FACTORS)
&& (rpdata->object_property != PROP_ASSIGNED_ACCESS_RIGHTS)
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
(rpdata->object_property != PROP_AUTHENTICATION_FACTORS) &&
(rpdata->object_property != PROP_ASSIGNED_ACCESS_RIGHTS) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
@@ -345,18 +319,16 @@ int Access_Credential_Read_Property(
}
/* returns true if successful */
bool Access_Credential_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_Credential_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -365,9 +337,9 @@ bool Access_Credential_Write_Property(
return false;
}
/* only array properties can have array options */
if ((wp_data->object_property != PROP_AUTHENTICATION_FACTORS)
&& (wp_data->object_property != PROP_ASSIGNED_ACCESS_RIGHTS)
&& (wp_data->array_index != BACNET_ARRAY_ALL)) {
if ((wp_data->object_property != PROP_AUTHENTICATION_FACTORS) &&
(wp_data->object_property != PROP_ASSIGNED_ACCESS_RIGHTS) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
@@ -378,7 +350,7 @@ bool Access_Credential_Write_Property(
case PROP_GLOBAL_IDENTIFIER:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
ac_descr[object_index].global_identifier =
value.type.Unsigned_Int;
@@ -408,17 +380,14 @@ bool Access_Credential_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -428,10 +397,9 @@ bool WPValidateArgType(
return false;
}
void testAccessCredential(
Test * pTest)
void testAccessCredential(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -458,8 +426,7 @@ void testAccessCredential(
}
#ifdef TEST_ACCESS_CREDENTIAL
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -471,7 +438,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+133 -184
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access Door Objects - customize for your use */
@@ -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"
#include "access_door.h"
#include "handlers.h"
@@ -42,40 +42,30 @@ static bool Access_Door_Initialized = false;
static ACCESS_DOOR_DESCR ad_descr[MAX_ACCESS_DOORS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
PROP_DOOR_PULSE_TIME,
PROP_DOOR_EXTENDED_PULSE_TIME,
PROP_DOOR_OPEN_TOO_LONG_TIME,
-1
};
static const int Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
PROP_DOOR_PULSE_TIME,
PROP_DOOR_EXTENDED_PULSE_TIME,
PROP_DOOR_OPEN_TOO_LONG_TIME,
-1};
static const int Properties_Optional[] = {
PROP_DOOR_STATUS,
PROP_LOCK_STATUS,
PROP_SECURED_STATUS,
PROP_DOOR_UNLOCK_DELAY_TIME,
PROP_DOOR_ALARM_STATE,
-1
};
PROP_DOOR_STATUS, PROP_LOCK_STATUS,
PROP_SECURED_STATUS, PROP_DOOR_UNLOCK_DELAY_TIME,
PROP_DOOR_ALARM_STATE, -1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_Door_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_Door_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -87,8 +77,7 @@ void Access_Door_Property_Lists(
return;
}
void Access_Door_Init(
void)
void Access_Door_Init(void)
{
unsigned i, j;
@@ -104,10 +93,10 @@ void Access_Door_Init(
ad_descr[i].door_status = DOOR_STATUS_CLOSED;
ad_descr[i].lock_status = LOCK_STATUS_LOCKED;
ad_descr[i].secured_status = DOOR_SECURED_STATUS_SECURED;
ad_descr[i].door_pulse_time = 30; /* 3s */
ad_descr[i].door_extended_pulse_time = 50; /* 5s */
ad_descr[i].door_unlock_delay_time = 0; /* 0s */
ad_descr[i].door_open_too_long_time = 300; /* 30s */
ad_descr[i].door_pulse_time = 30; /* 3s */
ad_descr[i].door_extended_pulse_time = 50; /* 5s */
ad_descr[i].door_unlock_delay_time = 0; /* 0s */
ad_descr[i].door_open_too_long_time = 300; /* 30s */
ad_descr[i].door_alarm_state = DOOR_ALARM_STATE_NORMAL;
for (j = 0; j < BACNET_MAX_PRIORITY; j++) {
ad_descr[i].value_active[j] = false;
@@ -123,8 +112,7 @@ void Access_Door_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_Door_Valid_Instance(
uint32_t object_instance)
bool Access_Door_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_DOORS)
return true;
@@ -134,8 +122,7 @@ bool Access_Door_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_Door_Count(
void)
unsigned Access_Door_Count(void)
{
return MAX_ACCESS_DOORS;
}
@@ -143,8 +130,7 @@ unsigned Access_Door_Count(
/* 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 Access_Door_Index_To_Instance(
unsigned index)
uint32_t Access_Door_Index_To_Instance(unsigned index)
{
return index;
}
@@ -152,8 +138,7 @@ uint32_t Access_Door_Index_To_Instance(
/* 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 Access_Door_Instance_To_Index(
uint32_t object_instance)
unsigned Access_Door_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_DOORS;
@@ -163,8 +148,7 @@ unsigned Access_Door_Instance_To_Index(
return index;
}
BACNET_DOOR_VALUE Access_Door_Present_Value(
uint32_t object_instance)
BACNET_DOOR_VALUE Access_Door_Present_Value(uint32_t object_instance)
{
unsigned index = 0;
unsigned i = 0;
@@ -183,12 +167,11 @@ BACNET_DOOR_VALUE Access_Door_Present_Value(
return value;
}
unsigned Access_Door_Present_Value_Priority(
uint32_t object_instance)
unsigned Access_Door_Present_Value_Priority(uint32_t object_instance)
{
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
index = Access_Door_Instance_To_Index(object_instance);
if (index < MAX_ACCESS_DOORS) {
@@ -203,10 +186,8 @@ unsigned Access_Door_Present_Value_Priority(
return priority;
}
bool Access_Door_Present_Value_Set(
uint32_t object_instance,
BACNET_DOOR_VALUE value,
unsigned priority)
bool Access_Door_Present_Value_Set(uint32_t object_instance,
BACNET_DOOR_VALUE value, unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -214,8 +195,7 @@ bool Access_Door_Present_Value_Set(
index = Access_Door_Instance_To_Index(object_instance);
if (index < MAX_ACCESS_DOORS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value >= DOOR_VALUE_LOCK) &&
(priority != 6 /* reserved */) && (value >= DOOR_VALUE_LOCK) &&
(value <= DOOR_VALUE_EXTENDED_PULSE_UNLOCK)) {
ad_descr[index].value_active[priority - 1] = true;
ad_descr[index].priority_array[priority - 1] = value;
@@ -232,9 +212,8 @@ bool Access_Door_Present_Value_Set(
return status;
}
bool Access_Door_Present_Value_Relinquish(
uint32_t object_instance,
unsigned priority)
bool Access_Door_Present_Value_Relinquish(uint32_t object_instance,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -242,7 +221,7 @@ bool Access_Door_Present_Value_Relinquish(
index = Access_Door_Instance_To_Index(object_instance);
if (index < MAX_ACCESS_DOORS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
(priority != 6 /* reserved */)) {
ad_descr[index].value_active[priority - 1] = false;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
@@ -257,8 +236,7 @@ bool Access_Door_Present_Value_Relinquish(
return status;
}
BACNET_DOOR_VALUE Access_Door_Relinquish_Default(
uint32_t object_instance)
BACNET_DOOR_VALUE Access_Door_Relinquish_Default(uint32_t object_instance)
{
BACNET_DOOR_VALUE status = -1;
unsigned index = 0;
@@ -271,24 +249,21 @@ BACNET_DOOR_VALUE Access_Door_Relinquish_Default(
}
/* note: the object name must be unique within this device */
bool Access_Door_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_Door_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_DOORS) {
sprintf(text_string, "ACCESS DOOR %lu",
(unsigned long) object_instance);
sprintf(text_string, "ACCESS DOOR %lu", (unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Access_Door_Out_Of_Service(
uint32_t instance)
bool Access_Door_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -301,9 +276,7 @@ bool Access_Door_Out_Of_Service(
return oos_flag;
}
void Access_Door_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Access_Door_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -314,11 +287,10 @@ void Access_Door_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Door_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_Door_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -334,9 +306,8 @@ int Access_Door_Read_Property(
object_index = Access_Door_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ACCESS_DOOR,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_DOOR, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_Door_Object_Name(rpdata->object_instance, &char_string);
@@ -348,9 +319,8 @@ int Access_Door_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_ACCESS_DOOR);
break;
case PROP_PRESENT_VALUE:
apdu_len =
encode_application_enumerated(&apdu[0],
Access_Door_Present_Value(rpdata->object_instance));
apdu_len = encode_application_enumerated(
&apdu[0], Access_Door_Present_Value(rpdata->object_instance));
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -362,14 +332,12 @@ int Access_Door_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].event_state);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].event_state);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].reliability);
break;
case PROP_OUT_OF_SERVICE:
state = Access_Door_Out_Of_Service(rpdata->object_instance);
@@ -388,8 +356,8 @@ int Access_Door_Read_Property(
if (ad_descr[object_index].value_active[i])
len = encode_application_null(&apdu[apdu_len]);
else
len =
encode_application_enumerated(&apdu[apdu_len],
len = encode_application_enumerated(
&apdu[apdu_len],
ad_descr[object_index].priority_array[i]);
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
@@ -406,8 +374,8 @@ int Access_Door_Read_Property(
if (ad_descr[object_index].value_active[i])
apdu_len = encode_application_null(&apdu[0]);
else {
apdu_len =
encode_application_enumerated(&apdu[apdu_len],
apdu_len = encode_application_enumerated(
&apdu[apdu_len],
ad_descr[object_index].priority_array[i]);
}
} else {
@@ -418,49 +386,41 @@ int Access_Door_Read_Property(
}
break;
case PROP_RELINQUISH_DEFAULT:
apdu_len =
encode_application_enumerated(&apdu[0],
apdu_len = encode_application_enumerated(
&apdu[0],
Access_Door_Relinquish_Default(rpdata->object_instance));
break;
case PROP_DOOR_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].door_status);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].door_status);
break;
case PROP_LOCK_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].lock_status);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].lock_status);
break;
case PROP_SECURED_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].secured_status);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].secured_status);
break;
case PROP_DOOR_PULSE_TIME:
apdu_len =
encode_application_unsigned(&apdu[0],
ad_descr[object_index].door_pulse_time);
apdu_len = encode_application_unsigned(
&apdu[0], ad_descr[object_index].door_pulse_time);
break;
case PROP_DOOR_EXTENDED_PULSE_TIME:
apdu_len =
encode_application_unsigned(&apdu[0],
ad_descr[object_index].door_extended_pulse_time);
apdu_len = encode_application_unsigned(
&apdu[0], ad_descr[object_index].door_extended_pulse_time);
break;
case PROP_DOOR_UNLOCK_DELAY_TIME:
apdu_len =
encode_application_unsigned(&apdu[0],
ad_descr[object_index].door_unlock_delay_time);
apdu_len = encode_application_unsigned(
&apdu[0], ad_descr[object_index].door_unlock_delay_time);
break;
case PROP_DOOR_OPEN_TOO_LONG_TIME:
apdu_len =
encode_application_unsigned(&apdu[0],
ad_descr[object_index].door_open_too_long_time);
apdu_len = encode_application_unsigned(
&apdu[0], ad_descr[object_index].door_open_too_long_time);
break;
case PROP_DOOR_ALARM_STATE:
apdu_len =
encode_application_enumerated(&apdu[0],
ad_descr[object_index].door_alarm_state);
apdu_len = encode_application_enumerated(
&apdu[0], ad_descr[object_index].door_alarm_state);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -480,18 +440,16 @@ int Access_Door_Read_Property(
}
/* returns true if successful */
bool Access_Door_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_Door_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -513,9 +471,9 @@ bool Access_Door_Write_Property(
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Access_Door_Present_Value_Set(wp_data->object_instance,
value.type.Enumerated, wp_data->priority);
status = Access_Door_Present_Value_Set(wp_data->object_instance,
value.type.Enumerated,
wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
@@ -527,13 +485,12 @@ bool Access_Door_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
status =
Access_Door_Present_Value_Relinquish
(wp_data->object_instance, wp_data->priority);
status = Access_Door_Present_Value_Relinquish(
wp_data->object_instance, wp_data->priority);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -544,18 +501,17 @@ bool Access_Door_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Access_Door_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_DOOR_STATUS:
if (Access_Door_Out_Of_Service(wp_data->object_instance)) {
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class,
&wp_data->error_code);
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
if (status) {
ad_descr[object_index].door_status = value.type.Enumerated;
}
@@ -566,10 +522,9 @@ bool Access_Door_Write_Property(
break;
case PROP_LOCK_STATUS:
if (Access_Door_Out_Of_Service(wp_data->object_instance)) {
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class,
&wp_data->error_code);
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
if (status) {
ad_descr[object_index].lock_status = value.type.Enumerated;
}
@@ -580,10 +535,9 @@ bool Access_Door_Write_Property(
break;
case PROP_DOOR_ALARM_STATE:
if (Access_Door_Out_Of_Service(wp_data->object_instance)) {
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class,
&wp_data->error_code);
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
if (status) {
ad_descr[object_index].door_alarm_state =
value.type.Enumerated;
@@ -618,17 +572,14 @@ bool Access_Door_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -638,10 +589,9 @@ bool WPValidateArgType(
return false;
}
void testAccessDoor(
Test * pTest)
void testAccessDoor(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -668,8 +618,7 @@ void testAccessDoor(
}
#ifdef TEST_ACCESS_DOOR
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -681,7 +630,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+84 -122
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access Point Objects - customize for your use */
@@ -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"
#include "access_point.h"
#include "handlers.h"
@@ -60,21 +60,14 @@ static const int Properties_Required[] = {
PROP_ACCESS_EVENT_CREDENTIAL,
PROP_ACCESS_DOORS,
PROP_PRIORITY_FOR_WRITING,
-1
};
-1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_Point_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_Point_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -86,8 +79,7 @@ void Access_Point_Property_Lists(
return;
}
void Access_Point_Init(
void)
void Access_Point_Init(void)
{
unsigned i;
@@ -98,8 +90,7 @@ void Access_Point_Init(
ap_descr[i].event_state = EVENT_STATE_NORMAL;
ap_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED;
ap_descr[i].out_of_service = false;
ap_descr[i].authentication_status =
AUTHENTICATION_STATUS_NOT_READY;
ap_descr[i].authentication_status = AUTHENTICATION_STATUS_NOT_READY;
ap_descr[i].active_authentication_policy = 0;
ap_descr[i].number_of_authentication_policies = 0;
ap_descr[i].authorization_mode = AUTHORIZATION_MODE_AUTHORIZE;
@@ -108,7 +99,7 @@ void Access_Point_Init(
/* access_event_credential should be set to some meaningful value */
ap_descr[i].num_doors = 0;
/* fill in the access doors with proper ids */
ap_descr[i].priority_for_writing = 16; /* lowest possible for now */
ap_descr[i].priority_for_writing = 16; /* lowest possible for now */
}
}
@@ -118,8 +109,7 @@ void Access_Point_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_Point_Valid_Instance(
uint32_t object_instance)
bool Access_Point_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_POINTS)
return true;
@@ -129,8 +119,7 @@ bool Access_Point_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_Point_Count(
void)
unsigned Access_Point_Count(void)
{
return MAX_ACCESS_POINTS;
}
@@ -138,8 +127,7 @@ unsigned Access_Point_Count(
/* 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 Access_Point_Index_To_Instance(
unsigned index)
uint32_t Access_Point_Index_To_Instance(unsigned index)
{
return index;
}
@@ -147,8 +135,7 @@ uint32_t Access_Point_Index_To_Instance(
/* 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 Access_Point_Instance_To_Index(
uint32_t object_instance)
unsigned Access_Point_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_POINTS;
@@ -159,24 +146,22 @@ unsigned Access_Point_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Access_Point_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_Point_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_POINTS) {
sprintf(text_string, "ACCESS POINT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Access_Point_Out_Of_Service(
uint32_t instance)
bool Access_Point_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -189,9 +174,7 @@ bool Access_Point_Out_Of_Service(
return oos_flag;
}
void Access_Point_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Access_Point_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -202,11 +185,10 @@ void Access_Point_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Point_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_Point_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -222,9 +204,8 @@ int Access_Point_Read_Property(
object_index = Access_Point_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ACCESS_POINT,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_POINT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_Point_Object_Name(rpdata->object_instance, &char_string);
@@ -245,69 +226,58 @@ int Access_Point_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0],
ap_descr[object_index].event_state);
apdu_len = encode_application_enumerated(
&apdu[0], ap_descr[object_index].event_state);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
ap_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], ap_descr[object_index].reliability);
break;
case PROP_OUT_OF_SERVICE:
state = Access_Point_Out_Of_Service(rpdata->object_instance);
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_AUTHENTICATION_STATUS:
apdu_len =
encode_application_enumerated(&apdu[0],
ap_descr[object_index].authentication_status);
apdu_len = encode_application_enumerated(
&apdu[0], ap_descr[object_index].authentication_status);
break;
case PROP_ACTIVE_AUTHENTICATION_POLICY:
apdu_len =
encode_application_unsigned(&apdu[0],
ap_descr[object_index].active_authentication_policy);
apdu_len = encode_application_unsigned(
&apdu[0], ap_descr[object_index].active_authentication_policy);
break;
case PROP_NUMBER_OF_AUTHENTICATION_POLICIES:
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
ap_descr[object_index].number_of_authentication_policies);
break;
case PROP_AUTHORIZATION_MODE:
apdu_len =
encode_application_enumerated(&apdu[0],
ap_descr[object_index].authorization_mode);
apdu_len = encode_application_enumerated(
&apdu[0], ap_descr[object_index].authorization_mode);
break;
case PROP_ACCESS_EVENT:
apdu_len =
encode_application_enumerated(&apdu[0],
ap_descr[object_index].access_event);
apdu_len = encode_application_enumerated(
&apdu[0], ap_descr[object_index].access_event);
break;
case PROP_ACCESS_EVENT_TAG:
apdu_len =
encode_application_unsigned(&apdu[0],
ap_descr[object_index].access_event_tag);
apdu_len = encode_application_unsigned(
&apdu[0], ap_descr[object_index].access_event_tag);
break;
case PROP_ACCESS_EVENT_TIME:
apdu_len =
bacapp_encode_timestamp(&apdu[0],
&ap_descr[object_index].access_event_time);
apdu_len = bacapp_encode_timestamp(
&apdu[0], &ap_descr[object_index].access_event_time);
break;
case PROP_ACCESS_EVENT_CREDENTIAL:
apdu_len =
bacapp_encode_device_obj_ref(&apdu[0],
&ap_descr[object_index].access_event_credential);
apdu_len = bacapp_encode_device_obj_ref(
&apdu[0], &ap_descr[object_index].access_event_credential);
break;
case PROP_ACCESS_DOORS:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
ap_descr[object_index].num_doors);
apdu_len = encode_application_unsigned(
&apdu[0], ap_descr[object_index].num_doors);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0; i < ap_descr[object_index].num_doors; i++) {
len =
bacapp_encode_device_obj_ref(&apdu[0],
&ap_descr[object_index].access_doors[i]);
len = bacapp_encode_device_obj_ref(
&apdu[0], &ap_descr[object_index].access_doors[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -319,10 +289,9 @@ int Access_Point_Read_Property(
}
} else {
if (rpdata->array_index <= ap_descr[object_index].num_doors) {
apdu_len =
bacapp_encode_device_obj_ref(&apdu[0],
&ap_descr[object_index].access_doors[rpdata->
array_index - 1]);
apdu_len = bacapp_encode_device_obj_ref(
&apdu[0], &ap_descr[object_index]
.access_doors[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -348,17 +317,15 @@ int Access_Point_Read_Property(
}
/* returns true if successful */
bool Access_Point_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -404,17 +371,14 @@ bool Access_Point_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -424,10 +388,9 @@ bool WPValidateArgType(
return false;
}
void testAccessPoint(
Test * pTest)
void testAccessPoint(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -454,8 +417,7 @@ void testAccessPoint(
}
#ifdef TEST_ACCESS_POINT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -467,7 +429,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+97 -122
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access Rights Objects - customize for your use */
@@ -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"
#include "access_rights.h"
#include "handlers.h"
@@ -42,31 +42,23 @@ static bool Access_Rights_Initialized = false;
static ACCESS_RIGHTS_DESCR ar_descr[MAX_ACCESS_RIGHTSS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_ENABLE,
PROP_NEGATIVE_ACCESS_RULES,
PROP_POSITIVE_ACCESS_RULES,
-1
};
static const int Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_ENABLE,
PROP_NEGATIVE_ACCESS_RULES,
PROP_POSITIVE_ACCESS_RULES,
-1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_Rights_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_Rights_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -78,8 +70,7 @@ void Access_Rights_Property_Lists(
return;
}
void Access_Rights_Init(
void)
void Access_Rights_Init(void)
{
unsigned i;
@@ -87,7 +78,8 @@ void Access_Rights_Init(
Access_Rights_Initialized = true;
for (i = 0; i < MAX_ACCESS_RIGHTSS; i++) {
ar_descr[i].global_identifier = 0; /* set to some meaningful value */
ar_descr[i].global_identifier =
0; /* set to some meaningful value */
ar_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED;
ar_descr[i].enable = false;
ar_descr[i].negative_access_rules_count = 0;
@@ -102,8 +94,7 @@ void Access_Rights_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_Rights_Valid_Instance(
uint32_t object_instance)
bool Access_Rights_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_RIGHTSS)
return true;
@@ -113,8 +104,7 @@ bool Access_Rights_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_Rights_Count(
void)
unsigned Access_Rights_Count(void)
{
return MAX_ACCESS_RIGHTSS;
}
@@ -122,8 +112,7 @@ unsigned Access_Rights_Count(
/* 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 Access_Rights_Index_To_Instance(
unsigned index)
uint32_t Access_Rights_Index_To_Instance(unsigned index)
{
return index;
}
@@ -131,8 +120,7 @@ uint32_t Access_Rights_Index_To_Instance(
/* 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 Access_Rights_Instance_To_Index(
uint32_t object_instance)
unsigned Access_Rights_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_RIGHTSS;
@@ -143,16 +131,15 @@ unsigned Access_Rights_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Access_Rights_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_Rights_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_RIGHTSS) {
sprintf(text_string, "ACCESS RIGHTS %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -160,11 +147,10 @@ bool Access_Rights_Object_Name(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Rights_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_Rights_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -179,9 +165,8 @@ int Access_Rights_Read_Property(
object_index = Access_Rights_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ACCESS_RIGHTS,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_RIGHTS, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_Rights_Object_Name(rpdata->object_instance, &char_string);
@@ -193,9 +178,8 @@ int Access_Rights_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_ACCESS_RIGHTS);
break;
case PROP_GLOBAL_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
ar_descr[object_index].global_identifier);
apdu_len = encode_application_unsigned(
&apdu[0], ar_descr[object_index].global_identifier);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -206,26 +190,24 @@ int Access_Rights_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
ar_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], ar_descr[object_index].reliability);
break;
case PROP_ENABLE:
apdu_len =
encode_application_boolean(&apdu[0],
ar_descr[object_index].enable);
apdu_len = encode_application_boolean(
&apdu[0], ar_descr[object_index].enable);
break;
case PROP_NEGATIVE_ACCESS_RULES:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
ar_descr[object_index].negative_access_rules_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0;
i < ar_descr[object_index].negative_access_rules_count;
i++) {
len =
bacapp_encode_access_rule(&apdu[0],
i < ar_descr[object_index].negative_access_rules_count;
i++) {
len = bacapp_encode_access_rule(
&apdu[0],
&ar_descr[object_index].negative_access_rules[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
@@ -239,10 +221,10 @@ int Access_Rights_Read_Property(
} else {
if (rpdata->array_index <=
ar_descr[object_index].negative_access_rules_count) {
apdu_len =
bacapp_encode_access_rule(&apdu[0],
&ar_descr[object_index].
negative_access_rules[rpdata->array_index - 1]);
apdu_len = bacapp_encode_access_rule(
&apdu[0],
&ar_descr[object_index]
.negative_access_rules[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -252,15 +234,15 @@ int Access_Rights_Read_Property(
break;
case PROP_POSITIVE_ACCESS_RULES:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
ar_descr[object_index].positive_access_rules_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0;
i < ar_descr[object_index].positive_access_rules_count;
i++) {
len =
bacapp_encode_access_rule(&apdu[0],
i < ar_descr[object_index].positive_access_rules_count;
i++) {
len = bacapp_encode_access_rule(
&apdu[0],
&ar_descr[object_index].positive_access_rules[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
@@ -274,10 +256,10 @@ int Access_Rights_Read_Property(
} else {
if (rpdata->array_index <=
ar_descr[object_index].positive_access_rules_count) {
apdu_len =
bacapp_encode_access_rule(&apdu[0],
&ar_descr[object_index].
positive_access_rules[rpdata->array_index - 1]);
apdu_len = bacapp_encode_access_rule(
&apdu[0],
&ar_descr[object_index]
.positive_access_rules[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -293,9 +275,9 @@ int Access_Rights_Read_Property(
}
/* only array properties can have array options */
if ((apdu_len >= 0) &&
(rpdata->object_property != PROP_NEGATIVE_ACCESS_RULES)
&& (rpdata->object_property != PROP_POSITIVE_ACCESS_RULES)
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
(rpdata->object_property != PROP_NEGATIVE_ACCESS_RULES) &&
(rpdata->object_property != PROP_POSITIVE_ACCESS_RULES) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
@@ -305,18 +287,16 @@ int Access_Rights_Read_Property(
}
/* returns true if successful */
bool Access_Rights_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_Rights_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -325,9 +305,9 @@ bool Access_Rights_Write_Property(
return false;
}
/* only array properties can have array options */
if ((wp_data->object_property != PROP_NEGATIVE_ACCESS_RULES)
&& (wp_data->object_property != PROP_POSITIVE_ACCESS_RULES)
&& (wp_data->array_index != BACNET_ARRAY_ALL)) {
if ((wp_data->object_property != PROP_NEGATIVE_ACCESS_RULES) &&
(wp_data->object_property != PROP_POSITIVE_ACCESS_RULES) &&
(wp_data->array_index != BACNET_ARRAY_ALL)) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
@@ -337,7 +317,7 @@ bool Access_Rights_Write_Property(
case PROP_GLOBAL_IDENTIFIER:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
ar_descr[object_index].global_identifier =
value.type.Unsigned_Int;
@@ -363,17 +343,14 @@ bool Access_Rights_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -383,10 +360,9 @@ bool WPValidateArgType(
return false;
}
void testAccessRights(
Test * pTest)
void testAccessRights(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -413,8 +389,7 @@ void testAccessRights(
}
#ifdef TEST_ACCESS_RIGHTS
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -426,7 +401,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+66 -98
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access User Objects - customize for your use */
@@ -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"
#include "access_user.h"
#include "handlers.h"
@@ -43,29 +43,16 @@ static ACCESS_USER_DESCR au_descr[MAX_ACCESS_USERS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_USER_TYPE,
PROP_CREDENTIALS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER, PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_USER_TYPE, PROP_CREDENTIALS, -1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_User_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_User_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -77,8 +64,7 @@ void Access_User_Property_Lists(
return;
}
void Access_User_Init(
void)
void Access_User_Init(void)
{
unsigned i;
@@ -86,7 +72,8 @@ void Access_User_Init(
Access_User_Initialized = true;
for (i = 0; i < MAX_ACCESS_USERS; i++) {
au_descr[i].global_identifier = 0; /* set to some meaningful value */
au_descr[i].global_identifier =
0; /* set to some meaningful value */
au_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED;
au_descr[i].user_type = ACCESS_USER_TYPE_PERSON;
au_descr[i].credentials_count = 0;
@@ -100,8 +87,7 @@ void Access_User_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_User_Valid_Instance(
uint32_t object_instance)
bool Access_User_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_USERS)
return true;
@@ -111,8 +97,7 @@ bool Access_User_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_User_Count(
void)
unsigned Access_User_Count(void)
{
return MAX_ACCESS_USERS;
}
@@ -120,8 +105,7 @@ unsigned Access_User_Count(
/* 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 Access_User_Index_To_Instance(
unsigned index)
uint32_t Access_User_Index_To_Instance(unsigned index)
{
return index;
}
@@ -129,8 +113,7 @@ uint32_t Access_User_Index_To_Instance(
/* 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 Access_User_Instance_To_Index(
uint32_t object_instance)
unsigned Access_User_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_USERS;
@@ -141,16 +124,14 @@ unsigned Access_User_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Access_User_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_User_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_USERS) {
sprintf(text_string, "ACCESS USER %lu",
(unsigned long) object_instance);
sprintf(text_string, "ACCESS USER %lu", (unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -158,11 +139,10 @@ bool Access_User_Object_Name(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_User_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_User_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -177,9 +157,8 @@ int Access_User_Read_Property(
object_index = Access_User_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ACCESS_USER,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_USER, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_User_Object_Name(rpdata->object_instance, &char_string);
@@ -191,9 +170,8 @@ int Access_User_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_ACCESS_USER);
break;
case PROP_GLOBAL_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
au_descr[object_index].global_identifier);
apdu_len = encode_application_unsigned(
&apdu[0], au_descr[object_index].global_identifier);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -204,20 +182,17 @@ int Access_User_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
au_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], au_descr[object_index].reliability);
break;
case PROP_USER_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
au_descr[object_index].user_type);
apdu_len = encode_application_enumerated(
&apdu[0], au_descr[object_index].user_type);
break;
case PROP_CREDENTIALS:
for (i = 0; i < au_descr[object_index].credentials_count; i++) {
len =
bacapp_encode_device_obj_ref(&apdu[0],
&au_descr[object_index].credentials[i]);
len = bacapp_encode_device_obj_ref(
&apdu[0], &au_descr[object_index].credentials[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -245,18 +220,16 @@ int Access_User_Read_Property(
}
/* returns true if successful */
bool Access_User_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_User_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -275,7 +248,7 @@ bool Access_User_Write_Property(
case PROP_GLOBAL_IDENTIFIER:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
au_descr[object_index].global_identifier =
value.type.Unsigned_Int;
@@ -301,17 +274,14 @@ bool Access_User_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -321,10 +291,9 @@ bool WPValidateArgType(
return false;
}
void testAccessUser(
Test * pTest)
void testAccessUser(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -351,8 +320,7 @@ void testAccessUser(
}
#ifdef TEST_ACCESS_USER
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -364,7 +332,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+76 -116
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Access Zone Objects - customize for your use */
@@ -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"
#include "access_zone.h"
#include "handlers.h"
@@ -43,32 +43,17 @@ static ACCESS_ZONE_DESCR az_descr[MAX_ACCESS_ZONES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER,
PROP_OCCUPANCY_STATE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_ENTRY_POINTS,
PROP_EXIT_POINTS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_GLOBAL_IDENTIFIER, PROP_OCCUPANCY_STATE, PROP_STATUS_FLAGS,
PROP_EVENT_STATE, PROP_RELIABILITY, PROP_OUT_OF_SERVICE,
PROP_ENTRY_POINTS, PROP_EXIT_POINTS, -1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Access_Zone_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Access_Zone_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -80,8 +65,7 @@ void Access_Zone_Property_Lists(
return;
}
void Access_Zone_Init(
void)
void Access_Zone_Init(void)
{
unsigned i;
@@ -89,7 +73,8 @@ void Access_Zone_Init(
Access_Zone_Initialized = true;
for (i = 0; i < MAX_ACCESS_ZONES; i++) {
az_descr[i].global_identifier = 0; /* set to some meaningful value */
az_descr[i].global_identifier =
0; /* set to some meaningful value */
az_descr[i].occupancy_state = ACCESS_ZONE_OCCUPANCY_STATE_DISABLED;
az_descr[i].event_state = EVENT_STATE_NORMAL;
az_descr[i].reliability = RELIABILITY_NO_FAULT_DETECTED;
@@ -106,8 +91,7 @@ void Access_Zone_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Access_Zone_Valid_Instance(
uint32_t object_instance)
bool Access_Zone_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ACCESS_ZONES)
return true;
@@ -117,8 +101,7 @@ bool Access_Zone_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Access_Zone_Count(
void)
unsigned Access_Zone_Count(void)
{
return MAX_ACCESS_ZONES;
}
@@ -126,8 +109,7 @@ unsigned Access_Zone_Count(
/* 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 Access_Zone_Index_To_Instance(
unsigned index)
uint32_t Access_Zone_Index_To_Instance(unsigned index)
{
return index;
}
@@ -135,8 +117,7 @@ uint32_t Access_Zone_Index_To_Instance(
/* 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 Access_Zone_Instance_To_Index(
uint32_t object_instance)
unsigned Access_Zone_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ACCESS_ZONES;
@@ -147,24 +128,21 @@ unsigned Access_Zone_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Access_Zone_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Access_Zone_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ACCESS_ZONES) {
sprintf(text_string, "ACCESS ZONE %lu",
(unsigned long) object_instance);
sprintf(text_string, "ACCESS ZONE %lu", (unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Access_Zone_Out_Of_Service(
uint32_t instance)
bool Access_Zone_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -177,9 +155,7 @@ bool Access_Zone_Out_Of_Service(
return oos_flag;
}
void Access_Zone_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Access_Zone_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -190,11 +166,10 @@ void Access_Zone_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Access_Zone_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Access_Zone_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -210,9 +185,8 @@ int Access_Zone_Read_Property(
object_index = Access_Zone_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ACCESS_ZONE,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ACCESS_ZONE, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Access_Zone_Object_Name(rpdata->object_instance, &char_string);
@@ -224,14 +198,12 @@ int Access_Zone_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_ACCESS_ZONE);
break;
case PROP_GLOBAL_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0],
az_descr[object_index].global_identifier);
apdu_len = encode_application_unsigned(
&apdu[0], az_descr[object_index].global_identifier);
break;
case PROP_OCCUPANCY_STATE:
apdu_len =
encode_application_enumerated(&apdu[0],
az_descr[object_index].occupancy_state);
apdu_len = encode_application_enumerated(
&apdu[0], az_descr[object_index].occupancy_state);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -243,14 +215,12 @@ int Access_Zone_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_EVENT_STATE:
apdu_len =
encode_application_enumerated(&apdu[0],
az_descr[object_index].event_state);
apdu_len = encode_application_enumerated(
&apdu[0], az_descr[object_index].event_state);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
az_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], az_descr[object_index].reliability);
break;
case PROP_OUT_OF_SERVICE:
state = Access_Zone_Out_Of_Service(rpdata->object_instance);
@@ -258,9 +228,8 @@ int Access_Zone_Read_Property(
break;
case PROP_ENTRY_POINTS:
for (i = 0; i < az_descr[object_index].entry_points_count; i++) {
len =
bacapp_encode_device_obj_ref(&apdu[0],
&az_descr[object_index].entry_points[i]);
len = bacapp_encode_device_obj_ref(
&apdu[0], &az_descr[object_index].entry_points[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -273,9 +242,8 @@ int Access_Zone_Read_Property(
break;
case PROP_EXIT_POINTS:
for (i = 0; i < az_descr[object_index].exit_points_count; i++) {
len =
bacapp_encode_device_obj_ref(&apdu[0],
&az_descr[object_index].exit_points[i]);
len = bacapp_encode_device_obj_ref(
&apdu[0], &az_descr[object_index].exit_points[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
else {
@@ -303,18 +271,16 @@ int Access_Zone_Read_Property(
}
/* returns true if successful */
bool Access_Zone_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Access_Zone_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -333,7 +299,7 @@ bool Access_Zone_Write_Property(
case PROP_GLOBAL_IDENTIFIER:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
az_descr[object_index].global_identifier =
value.type.Unsigned_Int;
@@ -341,10 +307,9 @@ bool Access_Zone_Write_Property(
break;
case PROP_RELIABILITY:
if (Access_Zone_Out_Of_Service(wp_data->object_instance)) {
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class,
&wp_data->error_code);
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
if (status) {
az_descr[object_index].reliability = value.type.Enumerated;
}
@@ -374,17 +339,14 @@ bool Access_Zone_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -394,10 +356,9 @@ bool WPValidateArgType(
return false;
}
void testAccessZone(
Test * pTest)
void testAccessZone(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -424,8 +385,7 @@ void testAccessZone(
}
#ifdef TEST_ACCESS_ZONE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -437,7 +397,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+316 -357
View File
File diff suppressed because it is too large Load Diff
+105 -137
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Analog Output Objects - customize for your use */
@@ -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"
#include "ao.h"
#include "handlers.h"
@@ -60,32 +60,24 @@ static bool Out_Of_Service[MAX_ANALOG_OUTPUTS];
static bool Analog_Output_Initialized = false;
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_UNITS,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Analog_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Analog_Output_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -97,8 +89,7 @@ void Analog_Output_Property_Lists(
return;
}
void Analog_Output_Init(
void)
void Analog_Output_Init(void)
{
unsigned i, j;
@@ -119,8 +110,7 @@ void Analog_Output_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Analog_Output_Valid_Instance(
uint32_t object_instance)
bool Analog_Output_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_ANALOG_OUTPUTS)
return true;
@@ -130,8 +120,7 @@ bool Analog_Output_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Analog_Output_Count(
void)
unsigned Analog_Output_Count(void)
{
return MAX_ANALOG_OUTPUTS;
}
@@ -139,8 +128,7 @@ unsigned Analog_Output_Count(
/* 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_Output_Index_To_Instance(
unsigned index)
uint32_t Analog_Output_Index_To_Instance(unsigned index)
{
return index;
}
@@ -148,8 +136,7 @@ uint32_t Analog_Output_Index_To_Instance(
/* 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_Output_Instance_To_Index(
uint32_t object_instance)
unsigned Analog_Output_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_ANALOG_OUTPUTS;
@@ -159,8 +146,7 @@ unsigned Analog_Output_Instance_To_Index(
return index;
}
float Analog_Output_Present_Value(
uint32_t object_instance)
float Analog_Output_Present_Value(uint32_t object_instance)
{
float value = AO_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -179,12 +165,11 @@ float Analog_Output_Present_Value(
return value;
}
unsigned Analog_Output_Present_Value_Priority(
uint32_t object_instance)
unsigned Analog_Output_Present_Value_Priority(uint32_t object_instance)
{
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
unsigned index = 0; /* instance to index conversion */
unsigned i = 0; /* loop counter */
unsigned priority = 0; /* return value */
index = Analog_Output_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_OUTPUTS) {
@@ -199,10 +184,8 @@ unsigned Analog_Output_Present_Value_Priority(
return priority;
}
bool Analog_Output_Present_Value_Set(
uint32_t object_instance,
float value,
unsigned priority)
bool Analog_Output_Present_Value_Set(uint32_t object_instance, float value,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -210,9 +193,9 @@ bool Analog_Output_Present_Value_Set(
index = Analog_Output_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(value >= 0.0) && (value <= 100.0)) {
Analog_Output_Level[index][priority - 1] = (uint8_t) value;
(priority != 6 /* reserved */) && (value >= 0.0) &&
(value <= 100.0)) {
Analog_Output_Level[index][priority - 1] = (uint8_t)value;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
priorities are set.
@@ -226,9 +209,8 @@ bool Analog_Output_Present_Value_Set(
return status;
}
bool Analog_Output_Present_Value_Relinquish(
uint32_t object_instance,
unsigned priority)
bool Analog_Output_Present_Value_Relinquish(uint32_t object_instance,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -236,7 +218,7 @@ bool Analog_Output_Present_Value_Relinquish(
index = Analog_Output_Instance_To_Index(object_instance);
if (index < MAX_ANALOG_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
(priority != 6 /* reserved */)) {
Analog_Output_Level[index][priority - 1] = AO_LEVEL_NULL;
/* Note: you could set the physical output here to the next
highest priority, or to the relinquish default if no
@@ -252,24 +234,22 @@ bool Analog_Output_Present_Value_Relinquish(
}
/* note: the object name must be unique within this device */
bool Analog_Output_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Analog_Output_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_ANALOG_OUTPUTS) {
sprintf(text_string, "ANALOG OUTPUT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Analog_Output_Out_Of_Service(
uint32_t instance)
bool Analog_Output_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -282,9 +262,7 @@ bool Analog_Output_Out_Of_Service(
return oos_flag;
}
void Analog_Output_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Analog_Output_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -295,14 +273,13 @@ void Analog_Output_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Analog_Output_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Analog_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
float real_value = (float)1.414;
unsigned object_index = 0;
unsigned i = 0;
bool state = false;
@@ -315,9 +292,8 @@ int Analog_Output_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_ANALOG_OUTPUT,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_ANALOG_OUTPUT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Analog_Output_Object_Name(rpdata->object_instance, &char_string);
@@ -368,9 +344,8 @@ int Analog_Output_Read_Property(
len = encode_application_null(&apdu[apdu_len]);
else {
real_value = Analog_Output_Level[object_index][i];
len =
encode_application_real(&apdu[apdu_len],
real_value);
len = encode_application_real(&apdu[apdu_len],
real_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
@@ -387,11 +362,12 @@ int Analog_Output_Read_Property(
Analog_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Analog_Output_Level[object_index][rpdata->array_index -
1] == AO_LEVEL_NULL)
1] == AO_LEVEL_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
real_value = Analog_Output_Level[object_index]
[rpdata->array_index - 1];
real_value =
Analog_Output_Level[object_index]
[rpdata->array_index - 1];
apdu_len =
encode_application_real(&apdu[0], real_value);
}
@@ -424,17 +400,15 @@ int Analog_Output_Read_Property(
}
/* returns true if successful */
bool Analog_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Analog_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -455,9 +429,9 @@ bool Analog_Output_Write_Property(
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Analog_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
status = Analog_Output_Present_Value_Set(
wp_data->object_instance, value.type.Real,
wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
@@ -469,13 +443,12 @@ bool Analog_Output_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
status =
Analog_Output_Present_Value_Relinquish
(wp_data->object_instance, wp_data->priority);
status = Analog_Output_Present_Value_Relinquish(
wp_data->object_instance, wp_data->priority);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -486,10 +459,10 @@ bool Analog_Output_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Analog_Output_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -512,38 +485,34 @@ bool Analog_Output_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
bool bResult;
bool bResult;
/*
* start out assuming success and only set up error
* response if validation fails.
*/
bResult = true;
if (pValue->tag != ucExpectedTag) {
bResult = false;
/*
* start out assuming success and only set up error
* response if validation fails.
*/
bResult = true;
if (pValue->tag != ucExpectedTag) {
bResult = false;
*pErrorClass = ERROR_CLASS_PROPERTY;
*pErrorCode = ERROR_CODE_INVALID_DATA_TYPE;
}
}
return (bResult);
return (bResult);
}
void testAnalogOutput(
Test * pTest)
void testAnalogOutput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -570,8 +539,7 @@ void testAnalogOutput(
}
#ifdef TEST_ANALOG_OUTPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -583,7 +551,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+295 -326
View File
File diff suppressed because it is too large Load Diff
+114 -145
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -57,36 +57,27 @@ static BACNET_FILE_LISTING BACnet_File_Listing[] = {
{0, "temp_0.txt"},
{1, "temp_1.txt"},
{2, "temp_2.txt"},
{0, NULL} /* last file indication */
{0, NULL} /* last file indication */
};
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int bacfile_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_FILE_TYPE,
PROP_FILE_SIZE,
PROP_MODIFICATION_DATE,
PROP_ARCHIVE,
PROP_READ_ONLY,
PROP_FILE_ACCESS_METHOD,
-1
};
static const int bacfile_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_FILE_TYPE,
PROP_FILE_SIZE,
PROP_MODIFICATION_DATE,
PROP_ARCHIVE,
PROP_READ_ONLY,
PROP_FILE_ACCESS_METHOD,
-1};
static const int bacfile_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int bacfile_Properties_Optional[] = {PROP_DESCRIPTION, -1};
static const int bacfile_Properties_Proprietary[] = {
-1
};
static const int bacfile_Properties_Proprietary[] = {-1};
void BACfile_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void BACfile_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = bacfile_Properties_Required;
@@ -98,8 +89,7 @@ void BACfile_Property_Lists(
return;
}
static char *bacfile_name(
uint32_t instance)
static char *bacfile_name(uint32_t instance)
{
uint32_t index = 0;
char *filename = NULL;
@@ -116,9 +106,8 @@ static char *bacfile_name(
return filename;
}
bool bacfile_object_name(
uint32_t instance,
BACNET_CHARACTER_STRING * object_name)
bool bacfile_object_name(uint32_t instance,
BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
char *filename = NULL;
@@ -131,14 +120,12 @@ bool bacfile_object_name(
return status;
}
bool bacfile_valid_instance(
uint32_t object_instance)
bool bacfile_valid_instance(uint32_t object_instance)
{
return bacfile_name(object_instance) ? true : false;
}
uint32_t bacfile_count(
void)
uint32_t bacfile_count(void)
{
uint32_t index = 0;
@@ -150,8 +137,7 @@ uint32_t bacfile_count(
return index;
}
uint32_t bacfile_index_to_instance(
unsigned find_index)
uint32_t bacfile_index_to_instance(unsigned find_index)
{
uint32_t instance = BACNET_MAX_INSTANCE + 1;
uint32_t index = 0;
@@ -168,8 +154,7 @@ uint32_t bacfile_index_to_instance(
return instance;
}
static long fsize(
FILE * pFile)
static long fsize(FILE *pFile)
{
long size = 0;
long origin = 0;
@@ -183,8 +168,7 @@ static long fsize(
return (size);
}
unsigned bacfile_file_size(
uint32_t object_instance)
unsigned bacfile_file_size(uint32_t object_instance)
{
char *pFilename = NULL;
FILE *pFile = NULL;
@@ -203,11 +187,10 @@ unsigned bacfile_file_size(
}
/* return the number of bytes used, or -1 on error */
int bacfile_read_property(
BACNET_READ_PROPERTY_DATA * rpdata)
int bacfile_read_property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
char text_string[32] = { "" };
int apdu_len = 0; /* return value */
char text_string[32] = {""};
BACNET_CHARACTER_STRING char_string;
BACNET_DATE bdate;
BACNET_TIME btime;
@@ -220,13 +203,12 @@ int bacfile_read_property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_FILE,
rpdata->object_instance);
apdu_len = encode_application_object_id(&apdu[0], OBJECT_FILE,
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
sprintf(text_string, "FILE %lu",
(unsigned long) rpdata->object_instance);
(unsigned long)rpdata->object_instance);
characterstring_init_ansi(&char_string, text_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
@@ -236,7 +218,7 @@ int bacfile_read_property(
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
bacfile_name(rpdata->object_instance));
bacfile_name(rpdata->object_instance));
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -246,16 +228,15 @@ int bacfile_read_property(
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_FILE_SIZE:
apdu_len =
encode_application_unsigned(&apdu[0],
bacfile_file_size(rpdata->object_instance));
apdu_len = encode_application_unsigned(
&apdu[0], bacfile_file_size(rpdata->object_instance));
break;
case PROP_MODIFICATION_DATE:
/* FIXME: get the actual value instead of April Fool's Day */
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 1; /* 1..31 */
bdate.wday = 6; /* 1=Monday */
bdate.year = 2006; /* AD */
bdate.month = 4; /* 1=Jan */
bdate.day = 1; /* 1..31 */
bdate.wday = 6; /* 1=Monday */
apdu_len = encode_application_date(&apdu[0], &bdate);
/* FIXME: get the actual value */
btime.hour = 7;
@@ -280,9 +261,8 @@ int bacfile_read_property(
apdu_len = encode_application_boolean(&apdu[0], true);
break;
case PROP_FILE_ACCESS_METHOD:
apdu_len =
encode_application_enumerated(&apdu[0],
FILE_RECORD_AND_STREAM_ACCESS);
apdu_len = encode_application_enumerated(
&apdu[0], FILE_RECORD_AND_STREAM_ACCESS);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -295,10 +275,9 @@ int bacfile_read_property(
}
/* returns true if successful */
bool bacfile_write_property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool bacfile_write_property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
@@ -314,9 +293,8 @@ bool bacfile_write_property(
return false;
}
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -334,7 +312,7 @@ bool bacfile_write_property(
Access Services since the last time the object was archived. */
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Boolean) {
/* FIXME: do something to wp_data->object_instance */
@@ -349,7 +327,7 @@ bool bacfile_write_property(
shall be writable. */
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
/* FIXME: do something with value.type.Unsigned
to wp_data->object_instance */
@@ -375,8 +353,7 @@ bool bacfile_write_property(
return status;
}
uint32_t bacfile_instance(
char *filename)
uint32_t bacfile_instance(char *filename)
{
uint32_t index = 0;
uint32_t instance = BACNET_MAX_INSTANCE + 1;
@@ -399,36 +376,33 @@ uint32_t bacfile_instance(
/* Another way would be to store the */
/* invokeID and file instance in a list or table */
/* when the request was sent */
uint32_t bacfile_instance_from_tsm(
uint8_t invokeID)
uint32_t bacfile_instance_from_tsm(uint8_t invokeID)
{
BACNET_NPDU_DATA npdu_data = { 0 }; /* dummy for getting npdu length */
BACNET_CONFIRMED_SERVICE_DATA service_data = { 0 };
BACNET_NPDU_DATA npdu_data = {0}; /* dummy for getting npdu length */
BACNET_CONFIRMED_SERVICE_DATA service_data = {0};
uint8_t service_choice = 0;
uint8_t *service_request = NULL;
uint16_t service_request_len = 0;
BACNET_ADDRESS dest; /* where the original packet was destined */
uint8_t apdu[MAX_PDU] = { 0 }; /* original APDU packet */
uint16_t apdu_len = 0; /* original APDU packet length */
int len = 0; /* apdu header length */
BACNET_ATOMIC_READ_FILE_DATA data = { 0 };
BACNET_ADDRESS dest; /* where the original packet was destined */
uint8_t apdu[MAX_PDU] = {0}; /* original APDU packet */
uint16_t apdu_len = 0; /* original APDU packet length */
int len = 0; /* apdu header length */
BACNET_ATOMIC_READ_FILE_DATA data = {0};
uint32_t object_instance = BACNET_MAX_INSTANCE + 1; /* return value */
bool found = false;
found =
tsm_get_transaction_pdu(invokeID, &dest, &npdu_data, &apdu[0],
&apdu_len);
found = tsm_get_transaction_pdu(invokeID, &dest, &npdu_data, &apdu[0],
&apdu_len);
if (found) {
if (!npdu_data.network_layer_message && npdu_data.data_expecting_reply
&& (apdu[0] == PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
len =
apdu_decode_confirmed_service_request(&apdu[0], apdu_len,
&service_data, &service_choice, &service_request,
&service_request_len);
if (!npdu_data.network_layer_message &&
npdu_data.data_expecting_reply &&
(apdu[0] == PDU_TYPE_CONFIRMED_SERVICE_REQUEST)) {
len = apdu_decode_confirmed_service_request(
&apdu[0], apdu_len, &service_data, &service_choice,
&service_request, &service_request_len);
if (service_choice == SERVICE_CONFIRMED_ATOMIC_READ_FILE) {
len =
arf_decode_service_request(service_request,
service_request_len, &data);
len = arf_decode_service_request(service_request,
service_request_len, &data);
if (len > 0) {
if (data.object_type == OBJECT_FILE)
object_instance = data.object_instance;
@@ -441,8 +415,7 @@ uint32_t bacfile_instance_from_tsm(
}
#endif
bool bacfile_read_stream_data(
BACNET_ATOMIC_READ_FILE_DATA * data)
bool bacfile_read_stream_data(BACNET_ATOMIC_READ_FILE_DATA *data)
{
char *pFilename = NULL;
bool found = false;
@@ -454,10 +427,9 @@ bool bacfile_read_stream_data(
found = true;
pFile = fopen(pFilename, "rb");
if (pFile) {
(void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
len =
fread(octetstring_value(&data->fileData[0]), 1,
data->type.stream.requestedOctetCount, pFile);
(void)fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
len = fread(octetstring_value(&data->fileData[0]), 1,
data->type.stream.requestedOctetCount, pFile);
if (len < data->type.stream.requestedOctetCount)
data->endOfFile = true;
else
@@ -476,8 +448,7 @@ bool bacfile_read_stream_data(
return found;
}
bool bacfile_write_stream_data(
BACNET_ATOMIC_WRITE_FILE_DATA * data)
bool bacfile_write_stream_data(BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
char *pFilename = NULL;
bool found = false;
@@ -500,11 +471,11 @@ bool bacfile_write_stream_data(
}
if (pFile) {
if (data->type.stream.fileStartPosition != -1) {
(void) fseek(pFile, data->type.stream.fileStartPosition,
SEEK_SET);
(void)fseek(pFile, data->type.stream.fileStartPosition,
SEEK_SET);
}
if (fwrite(octetstring_value(&data->fileData[0]),
octetstring_length(&data->fileData[0]), 1, pFile) != 1) {
octetstring_length(&data->fileData[0]), 1, pFile) != 1) {
/* do something if it fails? */
}
fclose(pFile);
@@ -514,8 +485,7 @@ bool bacfile_write_stream_data(
return found;
}
bool bacfile_write_record_data(
BACNET_ATOMIC_WRITE_FILE_DATA * data)
bool bacfile_write_record_data(BACNET_ATOMIC_WRITE_FILE_DATA *data)
{
char *pFilename = NULL;
bool found = false;
@@ -542,7 +512,8 @@ bool bacfile_write_record_data(
if (pFile) {
if ((data->type.record.fileStartRecord != -1) &&
(data->type.record.fileStartRecord > 0)) {
for (i = 0; i < (uint32_t)data->type.record.fileStartRecord; i++) {
for (i = 0; i < (uint32_t)data->type.record.fileStartRecord;
i++) {
pData = fgets(&dummy_data[0], sizeof(dummy_data), pFile);
if ((pData == NULL) || feof(pFile)) {
break;
@@ -551,8 +522,8 @@ bool bacfile_write_record_data(
}
for (i = 0; i < data->type.record.returnedRecordCount; i++) {
if (fwrite(octetstring_value(&data->fileData[i]),
octetstring_length(&data->fileData[i]), 1,
pFile) != 1) {
octetstring_length(&data->fileData[i]), 1,
pFile) != 1) {
/* do something if it fails? */
}
}
@@ -563,9 +534,8 @@ bool bacfile_write_record_data(
return found;
}
bool bacfile_read_ack_stream_data(
uint32_t instance,
BACNET_ATOMIC_READ_FILE_DATA * data)
bool bacfile_read_ack_stream_data(uint32_t instance,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
bool found = false;
FILE *pFile = NULL;
@@ -576,12 +546,12 @@ bool bacfile_read_ack_stream_data(
found = true;
pFile = fopen(pFilename, "rb");
if (pFile) {
(void) fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
(void)fseek(pFile, data->type.stream.fileStartPosition, SEEK_SET);
if (fwrite(octetstring_value(&data->fileData[0]),
octetstring_length(&data->fileData[0]), 1, pFile) != 1) {
octetstring_length(&data->fileData[0]), 1, pFile) != 1) {
#if PRINT_ENABLED
fprintf(stderr, "Failed to write to %s (%lu)!\n", pFilename,
(unsigned long) instance);
(unsigned long)instance);
#endif
}
fclose(pFile);
@@ -591,15 +561,14 @@ bool bacfile_read_ack_stream_data(
return found;
}
bool bacfile_read_ack_record_data(
uint32_t instance,
BACNET_ATOMIC_READ_FILE_DATA * data)
bool bacfile_read_ack_record_data(uint32_t instance,
BACNET_ATOMIC_READ_FILE_DATA *data)
{
bool found = false;
FILE *pFile = NULL;
char *pFilename = NULL;
uint32_t i = 0;
char dummy_data[MAX_OCTET_STRING_BYTES] = { 0 };
char dummy_data[MAX_OCTET_STRING_BYTES] = {0};
char *pData = NULL;
pFilename = bacfile_name(instance);
@@ -608,7 +577,8 @@ bool bacfile_read_ack_record_data(
pFile = fopen(pFilename, "rb");
if (pFile) {
if (data->type.record.fileStartRecord > 0) {
for (i = 0; i < (uint32_t)data->type.record.fileStartRecord; i++) {
for (i = 0; i < (uint32_t)data->type.record.fileStartRecord;
i++) {
pData = fgets(&dummy_data[0], sizeof(dummy_data), pFile);
if ((pData == NULL) || feof(pFile)) {
break;
@@ -617,11 +587,11 @@ bool bacfile_read_ack_record_data(
}
for (i = 0; i < data->type.record.RecordCount; i++) {
if (fwrite(octetstring_value(&data->fileData[i]),
octetstring_length(&data->fileData[i]), 1,
pFile) != 1) {
octetstring_length(&data->fileData[i]), 1,
pFile) != 1) {
#if PRINT_ENABLED
fprintf(stderr, "Failed to write to %s (%lu)!\n",
pFilename, (unsigned long) instance);
fprintf(stderr, "Failed to write to %s (%lu)!\n", pFilename,
(unsigned long)instance);
#endif
}
}
@@ -632,7 +602,6 @@ bool bacfile_read_ack_record_data(
return found;
}
void bacfile_init(
void)
void bacfile_init(void)
{
}
+87 -125
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Input Objects customize for your use */
@@ -35,7 +35,7 @@
#include "rp.h"
#include "wp.h"
#include "cov.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "bi.h"
#include "handlers.h"
@@ -54,30 +54,16 @@ static BACNET_POLARITY Polarity[MAX_BINARY_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Input_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_POLARITY, -1};
static const int Binary_Input_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Binary_Input_Properties_Optional[] = {PROP_DESCRIPTION, -1};
static const int Binary_Input_Properties_Proprietary[] = {
-1
};
static const int Binary_Input_Properties_Proprietary[] = {-1};
void Binary_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Binary_Input_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired) {
*pRequired = Binary_Input_Properties_Required;
@@ -95,8 +81,7 @@ void Binary_Input_Property_Lists(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
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;
@@ -107,8 +92,7 @@ bool Binary_Input_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Input_Count(
void)
unsigned Binary_Input_Count(void)
{
return MAX_BINARY_INPUTS;
}
@@ -116,14 +100,12 @@ unsigned Binary_Input_Count(
/* 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 Binary_Input_Index_To_Instance(
unsigned index)
uint32_t Binary_Input_Index_To_Instance(unsigned index)
{
return index;
}
void Binary_Input_Init(
void)
void Binary_Input_Init(void)
{
static bool initialized = false;
unsigned i;
@@ -143,8 +125,7 @@ void Binary_Input_Init(
/* 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;
@@ -155,8 +136,7 @@ unsigned Binary_Input_Instance_To_Index(
return index;
}
BACNET_BINARY_PV Binary_Input_Present_Value(
uint32_t object_instance)
BACNET_BINARY_PV Binary_Input_Present_Value(uint32_t object_instance)
{
BACNET_BINARY_PV value = BINARY_INACTIVE;
unsigned index = 0;
@@ -176,8 +156,7 @@ BACNET_BINARY_PV Binary_Input_Present_Value(
return value;
}
bool Binary_Input_Out_Of_Service(
uint32_t object_instance)
bool Binary_Input_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -190,8 +169,7 @@ bool Binary_Input_Out_Of_Service(
return value;
}
bool Binary_Input_Change_Of_Value(
uint32_t object_instance)
bool Binary_Input_Change_Of_Value(uint32_t object_instance)
{
bool status = false;
unsigned index;
@@ -204,8 +182,7 @@ bool Binary_Input_Change_Of_Value(
return status;
}
void Binary_Input_Change_Of_Value_Clear(
uint32_t object_instance)
void Binary_Input_Change_Of_Value_Clear(uint32_t object_instance)
{
unsigned index;
@@ -225,9 +202,8 @@ void Binary_Input_Change_Of_Value_Clear(
*
* @return true if the value list is encoded
*/
bool Binary_Input_Encode_Value_List(
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list)
bool Binary_Input_Encode_Value_List(uint32_t object_instance,
BACNET_PROPERTY_VALUE *value_list)
{
bool status = false;
@@ -250,17 +226,17 @@ bool Binary_Input_Encode_Value_List(
value_list->value.next = NULL;
bitstring_init(&value_list->value.type.Bit_String);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_IN_ALARM, false);
STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&value_list->value.type.Bit_String, STATUS_FLAG_FAULT,
false);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_FAULT, false);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OVERRIDDEN, false);
STATUS_FLAG_OVERRIDDEN, false);
if (Binary_Input_Out_Of_Service(object_instance)) {
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OUT_OF_SERVICE, true);
STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OUT_OF_SERVICE, false);
STATUS_FLAG_OUT_OF_SERVICE, false);
}
value_list->priority = BACNET_NO_PRIORITY;
value_list->next = NULL;
@@ -270,9 +246,8 @@ bool Binary_Input_Encode_Value_List(
return status;
}
bool Binary_Input_Present_Value_Set(
uint32_t object_instance,
BACNET_BINARY_PV value)
bool Binary_Input_Present_Value_Set(uint32_t object_instance,
BACNET_BINARY_PV value)
{
unsigned index = 0;
bool status = false;
@@ -296,9 +271,7 @@ bool Binary_Input_Present_Value_Set(
return status;
}
void Binary_Input_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
void Binary_Input_Out_Of_Service_Set(uint32_t object_instance, bool value)
{
unsigned index = 0;
@@ -313,26 +286,24 @@ void Binary_Input_Out_Of_Service_Set(
return;
}
bool Binary_Input_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Binary_Input_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
unsigned index = 0;
index = Binary_Input_Instance_To_Index(object_instance);
if (index < MAX_BINARY_INPUTS) {
sprintf(text_string, "BINARY INPUT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
BACNET_POLARITY Binary_Input_Polarity(
uint32_t object_instance)
BACNET_POLARITY Binary_Input_Polarity(uint32_t object_instance)
{
BACNET_POLARITY polarity = POLARITY_NORMAL;
unsigned index = 0;
@@ -345,9 +316,8 @@ BACNET_POLARITY Binary_Input_Polarity(
return polarity;
}
bool Binary_Input_Polarity_Set(
uint32_t object_instance,
BACNET_POLARITY polarity)
bool Binary_Input_Polarity_Set(uint32_t object_instance,
BACNET_POLARITY polarity)
{
bool status = false;
unsigned index = 0;
@@ -362,10 +332,9 @@ bool Binary_Input_Polarity_Set(
/* return apdu length, or BACNET_STATUS_ERROR on error */
/* assumption - object already exists, and has been bounds checked */
int Binary_Input_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Binary_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
@@ -378,9 +347,8 @@ int Binary_Input_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_INPUT,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_BINARY_INPUT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
@@ -395,9 +363,8 @@ int Binary_Input_Read_Property(
break;
case PROP_PRESENT_VALUE:
/* note: you need to look up the actual value */
apdu_len =
encode_application_enumerated(&apdu[0],
Binary_Input_Present_Value(rpdata->object_instance));
apdu_len = encode_application_enumerated(
&apdu[0], Binary_Input_Present_Value(rpdata->object_instance));
break;
case PROP_STATUS_FLAGS:
/* note: see the details in the standard on how to use these */
@@ -419,9 +386,8 @@ int Binary_Input_Read_Property(
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_POLARITY:
apdu_len =
encode_application_enumerated(&apdu[0],
Binary_Input_Polarity(rpdata->object_instance));
apdu_len = encode_application_enumerated(
&apdu[0], Binary_Input_Polarity(rpdata->object_instance));
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -440,17 +406,15 @@ int Binary_Input_Read_Property(
}
/* returns true if successful */
bool Binary_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Binary_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -468,11 +432,12 @@ bool Binary_Input_Write_Property(
case PROP_PRESENT_VALUE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Enumerated <= MAX_BINARY_PV) {
Binary_Input_Present_Value_Set(wp_data->object_instance,
(BACNET_BINARY_PV) value.type.Enumerated);
Binary_Input_Present_Value_Set(
wp_data->object_instance,
(BACNET_BINARY_PV)value.type.Enumerated);
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -483,20 +448,21 @@ bool Binary_Input_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Binary_Input_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_POLARITY:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Enumerated < MAX_POLARITY) {
Binary_Input_Polarity_Set(wp_data->object_instance,
(BACNET_POLARITY) value.type.Enumerated);
Binary_Input_Polarity_Set(
wp_data->object_instance,
(BACNET_POLARITY)value.type.Enumerated);
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -527,11 +493,9 @@ bool Binary_Input_Write_Property(
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -541,11 +505,10 @@ bool WPValidateArgType(
return false;
}
void testBinaryInput(
Test * pTest)
void testBinaryInput(Test *pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -571,8 +534,7 @@ void testBinaryInput(
}
#ifdef TEST_BINARY_INPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -584,7 +546,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+95 -124
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Output Objects - customize for your use */
@@ -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 "rp.h"
#include "wp.h"
#include "bo.h"
@@ -46,42 +46,32 @@
/* the Relinquish Default value */
#define RELINQUISH_DEFAULT BINARY_INACTIVE
/* Here is our Priority Array.*/
static BACNET_BINARY_PV
Binary_Output_Level[MAX_BINARY_OUTPUTS][BACNET_MAX_PRIORITY];
static BACNET_BINARY_PV Binary_Output_Level[MAX_BINARY_OUTPUTS]
[BACNET_MAX_PRIORITY];
/* Writable out-of-service allows others to play with our Present Value */
/* without changing the physical output */
static bool Out_Of_Service[MAX_BINARY_OUTPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Output_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
static const int Binary_Output_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_POLARITY,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1};
static const int Binary_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_ACTIVE_TEXT,
PROP_INACTIVE_TEXT,
-1
};
PROP_DESCRIPTION, PROP_ACTIVE_TEXT, PROP_INACTIVE_TEXT, -1};
static const int Binary_Output_Properties_Proprietary[] = {
-1
};
static const int Binary_Output_Properties_Proprietary[] = {-1};
void Binary_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Binary_Output_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Binary_Output_Properties_Required;
@@ -93,8 +83,7 @@ void Binary_Output_Property_Lists(
return;
}
void Binary_Output_Init(
void)
void Binary_Output_Init(void)
{
unsigned i, j;
static bool initialized = false;
@@ -116,8 +105,7 @@ void Binary_Output_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Binary_Output_Valid_Instance(
uint32_t object_instance)
bool Binary_Output_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_BINARY_OUTPUTS)
return true;
@@ -127,8 +115,7 @@ bool Binary_Output_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Output_Count(
void)
unsigned Binary_Output_Count(void)
{
return MAX_BINARY_OUTPUTS;
}
@@ -136,8 +123,7 @@ unsigned Binary_Output_Count(
/* 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 Binary_Output_Index_To_Instance(
unsigned index)
uint32_t Binary_Output_Index_To_Instance(unsigned index)
{
return index;
}
@@ -145,8 +131,7 @@ uint32_t Binary_Output_Index_To_Instance(
/* 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_Output_Instance_To_Index(
uint32_t object_instance)
unsigned Binary_Output_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_BINARY_OUTPUTS;
@@ -156,8 +141,7 @@ unsigned Binary_Output_Instance_To_Index(
return index;
}
BACNET_BINARY_PV Binary_Output_Present_Value(
uint32_t object_instance)
BACNET_BINARY_PV Binary_Output_Present_Value(uint32_t object_instance)
{
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -176,8 +160,7 @@ BACNET_BINARY_PV Binary_Output_Present_Value(
return value;
}
bool Binary_Output_Out_Of_Service(
uint32_t object_instance)
bool Binary_Output_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -191,16 +174,15 @@ bool Binary_Output_Out_Of_Service(
}
/* note: the object name must be unique within this device */
bool Binary_Output_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Binary_Output_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_BINARY_OUTPUTS) {
sprintf(text_string, "BINARY OUTPUT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -208,11 +190,10 @@ bool Binary_Output_Object_Name(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Binary_Output_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Binary_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
@@ -229,9 +210,8 @@ int Binary_Output_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_OUTPUT,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_BINARY_OUTPUT, rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
@@ -289,9 +269,8 @@ int Binary_Output_Read_Property(
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Output_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
len = encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
@@ -308,14 +287,14 @@ int Binary_Output_Read_Property(
Binary_Output_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Output_Level[object_index][rpdata->array_index -
1] == BINARY_NULL)
1] == BINARY_NULL)
apdu_len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Output_Level[object_index]
[rpdata->array_index - 1];
apdu_len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
present_value =
Binary_Output_Level[object_index]
[rpdata->array_index - 1];
apdu_len = encode_application_enumerated(
&apdu[apdu_len], present_value);
}
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -357,10 +336,9 @@ int Binary_Output_Read_Property(
}
/* returns true if successful */
bool Binary_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Binary_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
unsigned int priority = 0;
BACNET_BINARY_PV level = BINARY_NULL;
@@ -368,9 +346,8 @@ bool Binary_Output_Write_Property(
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -393,19 +370,19 @@ bool Binary_Output_Write_Property(
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(priority != 6 /* reserved */) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV) value.type.Enumerated;
object_index =
Binary_Output_Instance_To_Index
(wp_data->object_instance);
level = (BACNET_BINARY_PV)value.type.Enumerated;
object_index = Binary_Output_Instance_To_Index(
wp_data->object_instance);
priority--;
Binary_Output_Level[object_index][priority] = 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) */
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
@@ -418,24 +395,24 @@ bool Binary_Output_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
level = BINARY_NULL;
object_index =
Binary_Output_Instance_To_Index
(wp_data->object_instance);
object_index = Binary_Output_Instance_To_Index(
wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Binary_Output_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) */
/* 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) */
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -447,12 +424,11 @@ bool Binary_Output_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
object_index =
Binary_Output_Instance_To_Index(wp_data->object_instance);
Out_Of_Service[object_index] =
value.type.Boolean;
Out_Of_Service[object_index] = value.type.Boolean;
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -478,17 +454,14 @@ bool Binary_Output_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -498,10 +471,9 @@ bool WPValidateArgType(
return false;
}
void testBinaryOutput(
Test * pTest)
void testBinaryOutput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -528,8 +500,7 @@ void testBinaryOutput(
}
#ifdef TEST_BINARY_OUTPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -541,7 +512,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+89 -124
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Binary Output Objects - customize for your use */
@@ -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"
#include "rp.h"
#include "bv.h"
@@ -46,39 +46,26 @@
/* the Relinquish Default value */
#define RELINQUISH_DEFAULT BINARY_INACTIVE
/* Here is our Priority Array.*/
static BACNET_BINARY_PV
Binary_Value_Level[MAX_BINARY_VALUES][BACNET_MAX_PRIORITY];
static BACNET_BINARY_PV Binary_Value_Level[MAX_BINARY_VALUES]
[BACNET_MAX_PRIORITY];
/* Writable out-of-service allows others to play with our Present Value */
/* without changing the physical output */
static bool Out_Of_Service[MAX_BINARY_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Binary_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, -1};
static const int Binary_Value_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
PROP_DESCRIPTION, PROP_PRIORITY_ARRAY, PROP_RELINQUISH_DEFAULT, -1};
static const int Binary_Value_Properties_Proprietary[] = {
-1
};
static const int Binary_Value_Properties_Proprietary[] = {-1};
void Binary_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Binary_Value_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Binary_Value_Properties_Required;
@@ -90,8 +77,7 @@ void Binary_Value_Property_Lists(
return;
}
void Binary_Value_Init(
void)
void Binary_Value_Init(void)
{
unsigned i, j;
static bool initialized = false;
@@ -113,8 +99,7 @@ void Binary_Value_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
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;
@@ -124,8 +109,7 @@ bool Binary_Value_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Binary_Value_Count(
void)
unsigned Binary_Value_Count(void)
{
return MAX_BINARY_VALUES;
}
@@ -133,8 +117,7 @@ unsigned Binary_Value_Count(
/* 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 Binary_Value_Index_To_Instance(
unsigned index)
uint32_t Binary_Value_Index_To_Instance(unsigned index)
{
return index;
}
@@ -142,8 +125,7 @@ uint32_t Binary_Value_Index_To_Instance(
/* 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_Value_Instance_To_Index(
uint32_t object_instance)
unsigned Binary_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_BINARY_VALUES;
@@ -153,8 +135,7 @@ unsigned Binary_Value_Instance_To_Index(
return index;
}
BACNET_BINARY_PV Binary_Value_Present_Value(
uint32_t object_instance)
BACNET_BINARY_PV Binary_Value_Present_Value(uint32_t object_instance)
{
BACNET_BINARY_PV value = RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -174,24 +155,22 @@ BACNET_BINARY_PV Binary_Value_Present_Value(
}
/* note: the object name must be unique within this device */
bool Binary_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Binary_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_BINARY_VALUES) {
sprintf(text_string, "BINARY VALUE %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Binary_Value_Out_Of_Service(
uint32_t instance)
bool Binary_Value_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -204,9 +183,7 @@ bool Binary_Value_Out_Of_Service(
return oos_flag;
}
void Binary_Value_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Binary_Value_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -217,11 +194,10 @@ void Binary_Value_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Binary_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Binary_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
@@ -237,9 +213,8 @@ int Binary_Value_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_BINARY_VALUE,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_BINARY_VALUE, rpdata->object_instance);
break;
/* note: Name and Description don't have to be the same.
You could make Description writable and different */
@@ -254,8 +229,7 @@ int Binary_Value_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_BINARY_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value =
Binary_Value_Present_Value(rpdata->object_instance);
present_value = Binary_Value_Present_Value(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], present_value);
break;
case PROP_STATUS_FLAGS:
@@ -293,9 +267,8 @@ int Binary_Value_Read_Property(
len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Value_Level[object_index][i];
len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
len = encode_application_enumerated(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
@@ -311,15 +284,14 @@ int Binary_Value_Read_Property(
object_index =
Binary_Value_Instance_To_Index(rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Binary_Value_Level[object_index][rpdata->array_index]
== BINARY_NULL)
if (Binary_Value_Level[object_index][rpdata->array_index] ==
BINARY_NULL)
apdu_len = encode_application_null(&apdu[apdu_len]);
else {
present_value = Binary_Value_Level[object_index]
[rpdata->array_index];
apdu_len =
encode_application_enumerated(&apdu[apdu_len],
present_value);
[rpdata->array_index];
apdu_len = encode_application_enumerated(
&apdu[apdu_len], present_value);
}
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -350,10 +322,9 @@ int Binary_Value_Read_Property(
}
/* returns true if successful */
bool Binary_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Binary_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
unsigned int priority = 0;
BACNET_BINARY_PV level = BINARY_NULL;
@@ -361,9 +332,8 @@ bool Binary_Value_Write_Property(
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -386,19 +356,19 @@ bool Binary_Value_Write_Property(
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(priority != 6 /* reserved */) &&
(value.type.Enumerated <= MAX_BINARY_PV)) {
level = (BACNET_BINARY_PV) value.type.Enumerated;
object_index =
Binary_Value_Instance_To_Index
(wp_data->object_instance);
level = (BACNET_BINARY_PV)value.type.Enumerated;
object_index = Binary_Value_Instance_To_Index(
wp_data->object_instance);
priority--;
Binary_Value_Level[object_index][priority] = 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) */
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
@@ -411,24 +381,24 @@ bool Binary_Value_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
level = BINARY_NULL;
object_index =
Binary_Value_Instance_To_Index
(wp_data->object_instance);
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) */
/* 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) */
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -440,10 +410,10 @@ bool Binary_Value_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Binary_Value_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -466,17 +436,14 @@ bool Binary_Value_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -486,10 +453,9 @@ bool WPValidateArgType(
return false;
}
void testBinary_Value(
Test * pTest)
void testBinary_Value(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -516,8 +482,7 @@ void testBinary_Value(
}
#ifdef TEST_BINARY_VALUE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -529,7 +494,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+251 -308
View File
File diff suppressed because it is too large Load Diff
+153 -223
View File
@@ -47,87 +47,78 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bactext.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "device.h"
#include "handlers.h"
#include "proplist.h"
#include "timestamp.h"
#include "command.h"
/*BACnetActionCommand ::= SEQUENCE {
deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
objectIdentifier [1] BACnetObjectIdentifier,
propertyIdentifier [2] BACnetPropertyIdentifier,
propertyArrayIndex [3] Unsigned OPTIONAL, --used only with array datatype
propertyValue [4] ABSTRACT-SYNTAX.&Type,
priority [5] Unsigned (1..16) OPTIONAL, --used only when property is commandable
postDelay [6] Unsigned OPTIONAL,
quitOnFailure [7] BOOLEAN,
writeSuccessful [8] BOOLEAN
}*/
/*BACnetActionCommand ::= SEQUENCE {
deviceIdentifier [0] BACnetObjectIdentifier OPTIONAL,
objectIdentifier [1] BACnetObjectIdentifier,
propertyIdentifier [2] BACnetPropertyIdentifier,
propertyArrayIndex [3] Unsigned OPTIONAL, --used only with array datatype
propertyValue [4] ABSTRACT-SYNTAX.&Type,
priority [5] Unsigned (1..16) OPTIONAL, --used only when property is commandable
postDelay [6] Unsigned OPTIONAL,
quitOnFailure [7] BOOLEAN,
writeSuccessful [8] BOOLEAN
}*/
int cl_encode_apdu(
uint8_t * apdu,
BACNET_ACTION_LIST * bcl)
int cl_encode_apdu(uint8_t *apdu, BACNET_ACTION_LIST *bcl)
{
int len = 0;
int apdu_len = 0;
if (bcl->Device_Id.instance >= 0 &&
bcl->Device_Id.instance <= BACNET_MAX_INSTANCE) {
len =
encode_context_object_id(&apdu[apdu_len], 0, bcl->Device_Id.type,
bcl->Device_Id.instance);
len = encode_context_object_id(&apdu[apdu_len], 0, bcl->Device_Id.type,
bcl->Device_Id.instance);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
}
/* TODO: Check for object type and instance limits */
len =
encode_context_object_id(&apdu[apdu_len], 1, bcl->Object_Id.type,
bcl->Object_Id.instance);
len = encode_context_object_id(&apdu[apdu_len], 1, bcl->Object_Id.type,
bcl->Object_Id.instance);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
len =
encode_context_enumerated(&apdu[apdu_len], 2,
bcl->Property_Identifier);
encode_context_enumerated(&apdu[apdu_len], 2, bcl->Property_Identifier);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
if (bcl->Property_Array_Index != BACNET_ARRAY_ALL) {
len =
encode_context_unsigned(&apdu[apdu_len], 3,
bcl->Property_Array_Index);
len = encode_context_unsigned(&apdu[apdu_len], 3,
bcl->Property_Array_Index);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
}
/* BACnet Testing Observed Incident oi00108
Command Action not correctly formatted
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00031
BC 135.1: 9.20.1.7
BC 135.1: 9.20.1.9
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes have been reviewed
by all interested parties. Say 6 months -> September 2016 */
len = encode_opening_tag(&apdu[apdu_len], 4);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
len = bacapp_encode_application_data(&apdu[apdu_len], &bcl->Value);
/* BACnet Testing Observed Incident oi00108
Command Action not correctly formatted
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00031 BC
135.1: 9.20.1.7 BC 135.1: 9.20.1.9 Any discussions can be directed to
edward@bac-test.com Please feel free to remove this comment when my
changes have been reviewed by all interested parties. Say 6 months ->
September 2016 */
len = encode_opening_tag(&apdu[apdu_len], 4);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
len = bacapp_encode_application_data(&apdu[apdu_len], &bcl->Value);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
len = encode_closing_tag(&apdu[apdu_len], 4);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
len = encode_closing_tag(&apdu[apdu_len], 4);
if (len < 0)
return BACNET_STATUS_REJECT;
apdu_len += len;
if (bcl->Priority != BACNET_NO_PRIORITY) {
len = encode_context_unsigned(&apdu[apdu_len], 5, bcl->Priority);
@@ -153,11 +144,8 @@ int cl_encode_apdu(
return apdu_len;
}
int cl_decode_apdu(
uint8_t * apdu,
unsigned apdu_len,
BACNET_APPLICATION_TAG tag,
BACNET_ACTION_LIST * bcl)
int cl_decode_apdu(uint8_t *apdu, unsigned apdu_len, BACNET_APPLICATION_TAG tag,
BACNET_ACTION_LIST *bcl)
{
int len = 0;
int dec_len = 0;
@@ -167,43 +155,37 @@ int cl_decode_apdu(
if (decode_is_context_tag(&apdu[dec_len], 0)) {
/* Tag 0: Device ID */
dec_len++;
len =
decode_object_id(&apdu[dec_len], &bcl->Device_Id.type,
&bcl->Device_Id.instance);
len = decode_object_id(&apdu[dec_len], &bcl->Device_Id.type,
&bcl->Device_Id.instance);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
}
if (!decode_is_context_tag(&apdu[dec_len++], 1))
return BACNET_STATUS_REJECT;
len =
decode_object_id(&apdu[dec_len], &bcl->Object_Id.type,
&bcl->Object_Id.instance);
len = decode_object_id(&apdu[dec_len], &bcl->Object_Id.type,
&bcl->Object_Id.instance);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
len =
decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
if (tag_number != 2)
return BACNET_STATUS_REJECT;
len =
decode_enumerated(&apdu[dec_len], len_value_type,
&bcl->Property_Identifier);
len = decode_enumerated(&apdu[dec_len], len_value_type,
&bcl->Property_Identifier);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
if (decode_is_context_tag(&apdu[dec_len], 3)) {
len =
decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
dec_len += len;
len =
decode_unsigned(&apdu[dec_len], len_value_type,
&bcl->Property_Array_Index);
len = decode_unsigned(&apdu[dec_len], len_value_type,
&bcl->Property_Array_Index);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
@@ -220,68 +202,55 @@ int cl_decode_apdu(
len = 1;
break;
case BACNET_APPLICATION_TAG_BOOLEAN:
len =
decode_context_boolean2(&apdu[dec_len], 4,
&bcl->Value.type.Boolean);
len = decode_context_boolean2(&apdu[dec_len], 4,
&bcl->Value.type.Boolean);
break;
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
len =
decode_context_unsigned(&apdu[dec_len], 4,
&bcl->Value.type.Unsigned_Int);
len = decode_context_unsigned(&apdu[dec_len], 4,
&bcl->Value.type.Unsigned_Int);
break;
case BACNET_APPLICATION_TAG_SIGNED_INT:
len =
decode_context_signed(&apdu[dec_len], 4,
&bcl->Value.type.Signed_Int);
len = decode_context_signed(&apdu[dec_len], 4,
&bcl->Value.type.Signed_Int);
break;
case BACNET_APPLICATION_TAG_REAL:
len =
decode_context_real(&apdu[dec_len], 4, &bcl->Value.type.Real);
len = decode_context_real(&apdu[dec_len], 4, &bcl->Value.type.Real);
break;
case BACNET_APPLICATION_TAG_DOUBLE:
len =
decode_context_double(&apdu[dec_len], 4,
&bcl->Value.type.Double);
len = decode_context_double(&apdu[dec_len], 4,
&bcl->Value.type.Double);
break;
case BACNET_APPLICATION_TAG_OCTET_STRING:
len =
decode_context_octet_string(&apdu[dec_len], 4,
&bcl->Value.type.Octet_String);
len = decode_context_octet_string(&apdu[dec_len], 4,
&bcl->Value.type.Octet_String);
break;
case BACNET_APPLICATION_TAG_CHARACTER_STRING:
len =
decode_context_character_string(&apdu[dec_len], 4,
&bcl->Value.type.Character_String);
len = decode_context_character_string(
&apdu[dec_len], 4, &bcl->Value.type.Character_String);
break;
case BACNET_APPLICATION_TAG_BIT_STRING:
len =
decode_context_bitstring(&apdu[dec_len], 4,
&bcl->Value.type.Bit_String);
len = decode_context_bitstring(&apdu[dec_len], 4,
&bcl->Value.type.Bit_String);
break;
case BACNET_APPLICATION_TAG_ENUMERATED:
len =
decode_context_enumerated(&apdu[dec_len], 4,
&bcl->Value.type.Enumerated);
len = decode_context_enumerated(&apdu[dec_len], 4,
&bcl->Value.type.Enumerated);
break;
case BACNET_APPLICATION_TAG_DATE:
len =
decode_context_date(&apdu[dec_len], 4, &bcl->Value.type.Date);
len = decode_context_date(&apdu[dec_len], 4, &bcl->Value.type.Date);
break;
case BACNET_APPLICATION_TAG_TIME:
len =
decode_context_bacnet_time(&apdu[dec_len], 4,
&bcl->Value.type.Time);
len = decode_context_bacnet_time(&apdu[dec_len], 4,
&bcl->Value.type.Time);
break;
case BACNET_APPLICATION_TAG_OBJECT_ID:
len =
decode_context_object_id(&apdu[dec_len], 4,
&bcl->Value.type.Object_Id.type,
&bcl->Value.type.Object_Id.instance);
len = decode_context_object_id(&apdu[dec_len], 4,
&bcl->Value.type.Object_Id.type,
&bcl->Value.type.Object_Id.instance);
break;
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
len =
lighting_command_decode(&apdu[dec_len], apdu_len - dec_len,
&bcl->Value.type.Lighting_Command);
len = lighting_command_decode(&apdu[dec_len], apdu_len - dec_len,
&bcl->Value.type.Lighting_Command);
break;
default:
return BACNET_STATUS_REJECT;
@@ -291,25 +260,22 @@ int cl_decode_apdu(
dec_len += len;
if (decode_is_context_tag(&apdu[dec_len], 5)) {
uint32_t priority_dec;
len =
decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
dec_len += len;
len = decode_unsigned(&apdu[dec_len], len_value_type, &priority_dec);
if (len < 0)
return BACNET_STATUS_REJECT;
bcl->Priority = (uint8_t) priority_dec;
bcl->Priority = (uint8_t)priority_dec;
dec_len += len;
} else {
bcl->Priority = BACNET_NO_PRIORITY;
}
if (decode_is_context_tag(&apdu[dec_len], 6)) {
len =
decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
len = decode_tag_number_and_value(&apdu[dec_len], &tag_number,
&len_value_type);
dec_len += len;
len =
decode_unsigned(&apdu[dec_len], len_value_type, &bcl->Post_Delay);
len = decode_unsigned(&apdu[dec_len], len_value_type, &bcl->Post_Delay);
if (len < 0)
return BACNET_STATUS_REJECT;
dec_len += len;
@@ -340,25 +306,18 @@ int cl_decode_apdu(
COMMAND_DESCR Command_Descr[MAX_COMMANDS];
/* These arrays are used by the ReadPropertyMultiple handler */
static const int Command_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_IN_PROCESS,
PROP_ALL_WRITES_SUCCESSFUL,
PROP_ACTION,
-1
};
static const int Command_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_IN_PROCESS,
PROP_ALL_WRITES_SUCCESSFUL,
PROP_ACTION,
-1};
static const int Command_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Command_Properties_Optional[] = {PROP_DESCRIPTION, -1};
static const int Command_Properties_Proprietary[] = {
-1
};
static const int Command_Properties_Proprietary[] = {-1};
/**
* Returns the list of required, optional, and proprietary properties.
@@ -371,10 +330,8 @@ static const int Command_Properties_Proprietary[] = {
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Command_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Command_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Command_Properties_Required;
@@ -386,18 +343,16 @@ void Command_Property_Lists(
return;
}
/**
* Initializes the Command object data
*/
void Command_Init(
void)
void Command_Init(void)
{
unsigned i;
for (i = 0; i < MAX_COMMANDS; i++) {
Command_Descr[i].Present_Value = 0;
Command_Descr[i].In_Process = false;
Command_Descr[i].All_Writes_Successful = true; /* Optimistic default */
Command_Descr[i].All_Writes_Successful = true; /* Optimistic default */
}
}
@@ -408,8 +363,7 @@ void Command_Init(
*
* @return true if the instance is valid, and false if not
*/
bool Command_Valid_Instance(
uint32_t object_instance)
bool Command_Valid_Instance(uint32_t object_instance)
{
unsigned int index;
@@ -425,8 +379,7 @@ bool Command_Valid_Instance(
*
* @return Number of objects
*/
unsigned Command_Count(
void)
unsigned Command_Count(void)
{
return MAX_COMMANDS;
}
@@ -439,8 +392,7 @@ unsigned Command_Count(
*
* @return object instance-number for the given index
*/
uint32_t Command_Index_To_Instance(
unsigned index)
uint32_t Command_Index_To_Instance(unsigned index)
{
return index;
}
@@ -454,8 +406,7 @@ uint32_t Command_Index_To_Instance(
* @return index for the given instance-number, or
* the total number of this object instances if not valid.
*/
unsigned Command_Instance_To_Index(
uint32_t object_instance)
unsigned Command_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_COMMANDS;
@@ -472,8 +423,7 @@ unsigned Command_Instance_To_Index(
*
* @return present-value of the object
*/
uint32_t Command_Present_Value(
uint32_t object_instance)
uint32_t Command_Present_Value(uint32_t object_instance)
{
uint32_t value = 0;
unsigned int index;
@@ -494,9 +444,7 @@ uint32_t Command_Present_Value(
*
* @return true if values are within range and present-value is set.
*/
bool Command_Present_Value_Set(
uint32_t object_instance,
uint32_t value)
bool Command_Present_Value_Set(uint32_t object_instance, uint32_t value)
{
bool status = false;
unsigned int index;
@@ -521,8 +469,7 @@ bool Command_Present_Value_Set(
*
* @return true if this object-instance is in-process.
*/
bool Command_In_Process(
uint32_t object_instance)
bool Command_In_Process(uint32_t object_instance)
{
bool value = false;
unsigned int index;
@@ -543,9 +490,7 @@ bool Command_In_Process(
*
* @return true if values are within range and in-process flag is set.
*/
bool Command_In_Process_Set(
uint32_t object_instance,
bool value)
bool Command_In_Process_Set(uint32_t object_instance, bool value)
{
bool status = false;
unsigned int index;
@@ -568,8 +513,7 @@ bool Command_In_Process_Set(
*
* @return true if all writes were successful for this object-instance
*/
bool Command_All_Writes_Successful(
uint32_t object_instance)
bool Command_All_Writes_Successful(uint32_t object_instance)
{
bool value = false;
unsigned int index;
@@ -590,9 +534,7 @@ bool Command_All_Writes_Successful(
*
* @return true if values are within range and all-writes-succcessful is set.
*/
bool Command_All_Writes_Successful_Set(
uint32_t object_instance,
bool value)
bool Command_All_Writes_Successful_Set(uint32_t object_instance, bool value)
{
bool status = false;
unsigned int index;
@@ -615,17 +557,16 @@ bool Command_All_Writes_Successful_Set(
*
* @return true if object-name was retrieved
*/
bool Command_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Command_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
unsigned int index;
bool status = false;
index = Command_Instance_To_Index(object_instance);
if (index < MAX_COMMANDS) {
sprintf(text_string, "COMMAND %lu", (unsigned long) index);
sprintf(text_string, "COMMAND %lu", (unsigned long)index);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -642,10 +583,9 @@ bool Command_Object_Name(
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Command_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Command_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
int len = 0;
BACNET_CHARACTER_STRING char_string;
unsigned object_index = 0;
@@ -666,11 +606,10 @@ int Command_Read_Property(
}
apdu = rpdata->application_data;
switch ((int) rpdata->object_property) {
switch ((int)rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_COMMAND,
rpdata->object_instance);
apdu_len = encode_application_object_id(&apdu[0], OBJECT_COMMAND,
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
@@ -685,24 +624,23 @@ int Command_Read_Property(
break;
case PROP_PRESENT_VALUE:
apdu_len =
encode_application_unsigned(&apdu[0],
Command_Present_Value(rpdata->object_instance));
apdu_len = encode_application_unsigned(
&apdu[0], Command_Present_Value(rpdata->object_instance));
break;
case PROP_IN_PROCESS:
apdu_len =
encode_application_boolean(&apdu[0],
Command_In_Process(rpdata->object_instance));
apdu_len = encode_application_boolean(
&apdu[0], Command_In_Process(rpdata->object_instance));
break;
case PROP_ALL_WRITES_SUCCESSFUL:
apdu_len =
encode_application_boolean(&apdu[0],
apdu_len = encode_application_boolean(
&apdu[0],
Command_All_Writes_Successful(rpdata->object_instance));
break;
case PROP_ACTION:
/* TODO */
if (rpdata->array_index == 0)
apdu_len = encode_application_unsigned(&apdu[0], MAX_COMMAND_ACTIONS);
apdu_len =
encode_application_unsigned(&apdu[0], MAX_COMMAND_ACTIONS);
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
int i;
for (i = 0; i < MAX_COMMAND_ACTIONS; i++) {
@@ -710,12 +648,12 @@ int Command_Read_Property(
&CurrentCommand->Action[0];
/* another loop, for aditional actions in the list */
for (; Curr_CL_Member != NULL;
Curr_CL_Member = Curr_CL_Member->next) {
len =
cl_encode_apdu(&apdu[apdu_len],
&CurrentCommand->Action[0]);
Curr_CL_Member = Curr_CL_Member->next) {
len = cl_encode_apdu(&apdu[apdu_len],
&CurrentCommand->Action[0]);
apdu_len += len;
/* assume the next one is of the same length, which need not be the case */
/* assume the next one is of the same length, which need
* not be the case */
if ((i != MAX_COMMAND_ACTIONS - 1) &&
(apdu_len + len) >= apdu_max) {
rpdata->error_code =
@@ -731,12 +669,12 @@ int Command_Read_Property(
&CurrentCommand->Action[rpdata->array_index];
/* another loop, for aditional actions in the list */
for (; Curr_CL_Member != NULL;
Curr_CL_Member = Curr_CL_Member->next) {
len =
cl_encode_apdu(&apdu[apdu_len],
&CurrentCommand->Action[0]);
Curr_CL_Member = Curr_CL_Member->next) {
len = cl_encode_apdu(&apdu[apdu_len],
&CurrentCommand->Action[0]);
apdu_len += len;
/* assume the next one is of the same length, which need not be the case */
/* assume the next one is of the same length, which need
* not be the case */
if ((apdu_len + len) >= apdu_max) {
rpdata->error_code =
ERROR_CODE_ABORT_SEGMENTATION_NOT_SUPPORTED;
@@ -758,8 +696,8 @@ int Command_Read_Property(
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) && (rpdata->object_property != PROP_ACTION)
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
if ((apdu_len >= 0) && (rpdata->object_property != PROP_ACTION) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
@@ -777,17 +715,15 @@ int Command_Read_Property(
*
* @return false if an error is loaded, true if no errors
*/
bool Command_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Command_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -807,11 +743,11 @@ bool Command_Write_Property(
return false;
}
switch ((int) wp_data->object_property) {
switch ((int)wp_data->object_property) {
case PROP_PRESENT_VALUE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Unsigned_Int >= MAX_COMMAND_ACTIONS) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -819,7 +755,7 @@ bool Command_Write_Property(
return false;
}
Command_Present_Value_Set(wp_data->object_instance,
value.type.Unsigned_Int);
value.type.Unsigned_Int);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
@@ -846,8 +782,7 @@ bool Command_Write_Property(
return status;
}
void Command_Intrinsic_Reporting(
uint32_t object_instance)
void Command_Intrinsic_Reporting(uint32_t object_instance)
{
}
@@ -856,11 +791,9 @@ void Command_Intrinsic_Reporting(
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
bool bResult;
@@ -878,10 +811,9 @@ bool WPValidateArgType(
return (bResult);
}
void testCommand(
Test * pTest)
void testCommand(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -926,10 +858,9 @@ void testCommand(
ct_test(pTest, clist.Device_Id.instance == clist_test.Device_Id.instance);
ct_test(pTest, clist.Object_Id.type == clist_test.Object_Id.type);
ct_test(pTest, clist.Object_Id.instance == clist_test.Object_Id.instance);
ct_test(pTest, clist.Property_Identifier == clist_test.Property_Identifier);
ct_test(pTest,
clist.Property_Identifier == clist_test.Property_Identifier);
ct_test(pTest,
clist.Property_Array_Index == clist_test.Property_Array_Index);
clist.Property_Array_Index == clist_test.Property_Array_Index);
ct_test(pTest, clist.Value.tag == clist_test.Value.tag);
ct_test(pTest, clist.Value.type.Real == clist_test.Value.type.Real);
ct_test(pTest, clist.Priority == clist_test.Priority);
@@ -940,8 +871,7 @@ void testCommand(
}
#ifdef TEST_COMMAND
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -953,7 +883,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+95 -127
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Credential Data Input Objects - customize for your use */
@@ -33,7 +33,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"
#include "credential_data_input.h"
#include "handlers.h"
@@ -44,30 +44,19 @@ static CREDENTIAL_DATA_INPUT_DESCR cdi_descr[MAX_CREDENTIAL_DATA_INPUTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
PROP_SUPPORTED_FORMATS,
PROP_UPDATE_TIME,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS, PROP_RELIABILITY,
PROP_OUT_OF_SERVICE, PROP_SUPPORTED_FORMATS,
PROP_UPDATE_TIME, -1};
static const int Properties_Optional[] = {
-1
};
static const int Properties_Optional[] = {-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Credential_Data_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Credential_Data_Input_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -79,8 +68,7 @@ void Credential_Data_Input_Property_Lists(
return;
}
void Credential_Data_Input_Init(
void)
void Credential_Data_Input_Init(void)
{
unsigned i;
@@ -107,8 +95,7 @@ void Credential_Data_Input_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Credential_Data_Input_Valid_Instance(
uint32_t object_instance)
bool Credential_Data_Input_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_CREDENTIAL_DATA_INPUTS)
return true;
@@ -118,8 +105,7 @@ bool Credential_Data_Input_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Credential_Data_Input_Count(
void)
unsigned Credential_Data_Input_Count(void)
{
return MAX_CREDENTIAL_DATA_INPUTS;
}
@@ -127,8 +113,7 @@ unsigned Credential_Data_Input_Count(
/* 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 Credential_Data_Input_Index_To_Instance(
unsigned index)
uint32_t Credential_Data_Input_Index_To_Instance(unsigned index)
{
return index;
}
@@ -136,8 +121,7 @@ uint32_t Credential_Data_Input_Index_To_Instance(
/* 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 Credential_Data_Input_Instance_To_Index(
uint32_t object_instance)
unsigned Credential_Data_Input_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_CREDENTIAL_DATA_INPUTS;
@@ -148,24 +132,22 @@ unsigned Credential_Data_Input_Instance_To_Index(
}
/* note: the object name must be unique within this device */
bool Credential_Data_Input_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Credential_Data_Input_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_CREDENTIAL_DATA_INPUTS) {
sprintf(text_string, "CREDENTIAL DATA INPUT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
bool Credential_Data_Input_Out_Of_Service(
uint32_t instance)
bool Credential_Data_Input_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -178,9 +160,7 @@ bool Credential_Data_Input_Out_Of_Service(
return oos_flag;
}
void Credential_Data_Input_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Credential_Data_Input_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -191,11 +171,10 @@ void Credential_Data_Input_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Credential_Data_Input_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Credential_Data_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
unsigned object_index = 0;
@@ -212,25 +191,23 @@ int Credential_Data_Input_Read_Property(
Credential_Data_Input_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_CREDENTIAL_DATA_INPUT, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_CREDENTIAL_DATA_INPUT,
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Credential_Data_Input_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_CREDENTIAL_DATA_INPUT);
apdu_len = encode_application_enumerated(
&apdu[0], OBJECT_CREDENTIAL_DATA_INPUT);
break;
case PROP_PRESENT_VALUE:
apdu_len =
bacapp_encode_authentication_factor(&apdu[apdu_len],
&cdi_descr[object_index].present_value);
apdu_len = bacapp_encode_authentication_factor(
&apdu[apdu_len], &cdi_descr[object_index].present_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -243,9 +220,8 @@ int Credential_Data_Input_Read_Property(
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
cdi_descr[object_index].reliability);
apdu_len = encode_application_enumerated(
&apdu[0], cdi_descr[object_index].reliability);
break;
case PROP_OUT_OF_SERVICE:
state =
@@ -254,14 +230,13 @@ int Credential_Data_Input_Read_Property(
break;
case PROP_SUPPORTED_FORMATS:
if (rpdata->array_index == 0) {
apdu_len =
encode_application_unsigned(&apdu[0],
cdi_descr[object_index].supported_formats_count);
apdu_len = encode_application_unsigned(
&apdu[0], cdi_descr[object_index].supported_formats_count);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 0; i < cdi_descr[object_index].supported_formats_count;
i++) {
len =
bacapp_encode_authentication_factor_format(&apdu[0],
i++) {
len = bacapp_encode_authentication_factor_format(
&apdu[0],
&cdi_descr[object_index].supported_formats[i]);
if (apdu_len + len < MAX_APDU)
apdu_len += len;
@@ -275,10 +250,10 @@ int Credential_Data_Input_Read_Property(
} else {
if (rpdata->array_index <=
cdi_descr[object_index].supported_formats_count) {
apdu_len =
bacapp_encode_authentication_factor_format(&apdu[0],
&cdi_descr[object_index].
supported_formats[rpdata->array_index - 1]);
apdu_len = bacapp_encode_authentication_factor_format(
&apdu[0],
&cdi_descr[object_index]
.supported_formats[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -288,9 +263,8 @@ int Credential_Data_Input_Read_Property(
break;
case PROP_UPDATE_TIME:
apdu_len =
bacapp_encode_timestamp(&apdu[0],
&cdi_descr[object_index].timestamp);
apdu_len = bacapp_encode_timestamp(
&apdu[0], &cdi_descr[object_index].timestamp);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -299,8 +273,9 @@ int Credential_Data_Input_Read_Property(
break;
}
/* only array properties can have array options */
if ((apdu_len >= 0) && (rpdata->object_property != PROP_SUPPORTED_FORMATS)
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
if ((apdu_len >= 0) &&
(rpdata->object_property != PROP_SUPPORTED_FORMATS) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
@@ -310,18 +285,16 @@ int Credential_Data_Input_Read_Property(
}
/* returns true if successful */
bool Credential_Data_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Credential_Data_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
unsigned object_index = 0;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -336,17 +309,18 @@ bool Credential_Data_Input_Write_Property(
wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
return false;
}
object_index = Credential_Data_Input_Instance_To_Index(wp_data->object_instance);
object_index =
Credential_Data_Input_Instance_To_Index(wp_data->object_instance);
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
if (Credential_Data_Input_Out_Of_Service(wp_data->object_instance)) {
if (Credential_Data_Input_Out_Of_Service(
wp_data->object_instance)) {
BACNET_AUTHENTICATION_FACTOR tmp;
len =
bacapp_decode_authentication_factor(wp_data->
application_data, &tmp);
len = bacapp_decode_authentication_factor(
wp_data->application_data, &tmp);
if (len > 0) {
memcpy(&cdi_descr[object_index].present_value, &tmp,
sizeof(BACNET_AUTHENTICATION_FACTOR));
sizeof(BACNET_AUTHENTICATION_FACTOR));
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
@@ -357,14 +331,13 @@ bool Credential_Data_Input_Write_Property(
}
break;
case PROP_RELIABILITY:
if (Credential_Data_Input_Out_Of_Service(wp_data->object_instance)) {
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_ENUMERATED, &wp_data->error_class,
&wp_data->error_code);
if (Credential_Data_Input_Out_Of_Service(
wp_data->object_instance)) {
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
if (status) {
cdi_descr[object_index].reliability =
value.type.Enumerated;
cdi_descr[object_index].reliability = value.type.Enumerated;
}
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -390,17 +363,14 @@ bool Credential_Data_Input_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -410,10 +380,9 @@ bool WPValidateArgType(
return false;
}
void testCredentialDataInput(
Test * pTest)
void testCredentialDataInput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -440,8 +409,7 @@ void testCredentialDataInput(
}
#ifdef TEST_CREDENTIAL_DATA_INPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -453,7 +421,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+91 -128
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* CharacterString Value Objects */
@@ -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 "rp.h"
#include "wp.h"
#include "csv.h"
@@ -52,29 +52,17 @@ static char Object_Description[MAX_CHARACTERSTRING_VALUES][64];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, -1};
static const int Properties_Optional[] = {
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_DESCRIPTION,
-1
};
static const int Properties_Optional[] = {PROP_EVENT_STATE, PROP_OUT_OF_SERVICE,
PROP_DESCRIPTION, -1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void CharacterString_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void CharacterString_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -86,17 +74,16 @@ void CharacterString_Value_Property_Lists(
return;
}
void CharacterString_Value_Init(
void)
void CharacterString_Value_Init(void)
{
unsigned i;
/* initialize all Present Values */
for (i = 0; i < MAX_CHARACTERSTRING_VALUES; i++) {
snprintf(&Object_Name[i][0], sizeof(Object_Name[i]),
"CHARACTER STRING VALUE %u", i+1);
"CHARACTER STRING VALUE %u", i + 1);
snprintf(&Object_Description[i][0], sizeof(Object_Description[i]),
"A Character String Value Example");
"A Character String Value Example");
characterstring_init_ansi(&Present_Value[i], "");
}
@@ -106,8 +93,7 @@ void CharacterString_Value_Init(
/* 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 CharacterString_Value_Instance_To_Index(
uint32_t object_instance)
unsigned CharacterString_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_CHARACTERSTRING_VALUES;
@@ -121,22 +107,19 @@ unsigned CharacterString_Value_Instance_To_Index(
/* 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 CharacterString_Value_Index_To_Instance(
unsigned index)
uint32_t CharacterString_Value_Index_To_Instance(unsigned index)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned CharacterString_Value_Count(
void)
unsigned CharacterString_Value_Count(void)
{
return MAX_CHARACTERSTRING_VALUES;
}
bool CharacterString_Value_Valid_Instance(
uint32_t object_instance)
bool CharacterString_Value_Valid_Instance(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
@@ -148,9 +131,8 @@ bool CharacterString_Value_Valid_Instance(
return false;
}
bool CharacterString_Value_Present_Value(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool CharacterString_Value_Present_Value(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
unsigned index = 0; /* offset from instance lookup */
@@ -164,8 +146,7 @@ bool CharacterString_Value_Present_Value(
}
bool CharacterString_Value_Present_Value_Set(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
unsigned index = 0; /* offset from instance lookup */
@@ -178,8 +159,7 @@ bool CharacterString_Value_Present_Value_Set(
return status;
}
bool CharacterString_Value_Out_Of_Service(
uint32_t object_instance)
bool CharacterString_Value_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -192,9 +172,8 @@ bool CharacterString_Value_Out_Of_Service(
return value;
}
static void CharacterString_Value_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
static void CharacterString_Value_Out_Of_Service_Set(uint32_t object_instance,
bool value)
{
unsigned index = 0;
@@ -206,8 +185,7 @@ static void CharacterString_Value_Out_Of_Service_Set(
return;
}
static char *CharacterString_Value_Description(
uint32_t object_instance)
static char *CharacterString_Value_Description(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
char *pName = NULL; /* return value */
@@ -220,13 +198,12 @@ static char *CharacterString_Value_Description(
return pName;
}
bool CharacterString_Value_Description_Set(
uint32_t object_instance,
char *new_name)
bool CharacterString_Value_Description_Set(uint32_t object_instance,
char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = CharacterString_Value_Instance_To_Index(object_instance);
if (index < MAX_CHARACTERSTRING_VALUES) {
@@ -248,9 +225,8 @@ bool CharacterString_Value_Description_Set(
return status;
}
bool CharacterString_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool CharacterString_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
unsigned index = 0; /* offset from instance lookup */
bool status = false;
@@ -264,13 +240,11 @@ bool CharacterString_Value_Object_Name(
}
/* note: the object name must be unique within this device */
bool CharacterString_Value_Name_Set(
uint32_t object_instance,
char *new_name)
bool CharacterString_Value_Name_Set(uint32_t object_instance, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = CharacterString_Value_Instance_To_Index(object_instance);
if (index < MAX_CHARACTERSTRING_VALUES) {
@@ -294,10 +268,9 @@ bool CharacterString_Value_Name_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int CharacterString_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int CharacterString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index = 0;
@@ -311,32 +284,32 @@ int CharacterString_Value_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_CHARACTERSTRING_VALUE, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_CHARACTERSTRING_VALUE,
rpdata->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:
CharacterString_Value_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
CharacterString_Value_Description(rpdata->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_CHARACTERSTRING_VALUE);
apdu_len = encode_application_enumerated(
&apdu[0], OBJECT_CHARACTERSTRING_VALUE);
break;
case PROP_PRESENT_VALUE:
CharacterString_Value_Present_Value(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -348,10 +321,10 @@ int CharacterString_Value_Read_Property(
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (CharacterString_Value_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
true);
true);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
false);
false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -361,9 +334,8 @@ int CharacterString_Value_Read_Property(
encode_application_enumerated(&apdu[0], EVENT_STATE_NORMAL);
break;
case PROP_OUT_OF_SERVICE:
object_index =
CharacterString_Value_Instance_To_Index
(rpdata->object_instance);
object_index = CharacterString_Value_Instance_To_Index(
rpdata->object_instance);
state = Out_Of_Service[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
@@ -385,17 +357,15 @@ int CharacterString_Value_Read_Property(
}
/* returns true if successful */
bool CharacterString_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool CharacterString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -405,14 +375,12 @@ bool CharacterString_Value_Write_Property(
}
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
status =
WPValidateArgType(&value,
BACNET_APPLICATION_TAG_CHARACTER_STRING, &wp_data->error_class,
&wp_data->error_code);
status = WPValidateArgType(
&value, BACNET_APPLICATION_TAG_CHARACTER_STRING,
&wp_data->error_class, &wp_data->error_code);
if (status) {
status =
CharacterString_Value_Present_Value_Set
(wp_data->object_instance, &value.type.Character_String);
status = CharacterString_Value_Present_Value_Set(
wp_data->object_instance, &value.type.Character_String);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -422,10 +390,10 @@ bool CharacterString_Value_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
CharacterString_Value_Out_Of_Service_Set
(wp_data->object_instance, value.type.Boolean);
CharacterString_Value_Out_Of_Service_Set(
wp_data->object_instance, value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -446,17 +414,14 @@ bool CharacterString_Value_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -466,10 +431,9 @@ bool WPValidateArgType(
return false;
}
void testCharacterStringValue(
Test * pTest)
void testCharacterStringValue(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -496,8 +460,7 @@ void testCharacterStringValue(
}
#ifdef TEST_CHARACTERSTRING_VALUE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -509,7 +472,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+153 -230
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2011 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/** @file device-client.c Lightweight base "class" for handling all
* BACnet objects belonging to a BACnet device, as well as
@@ -30,8 +30,8 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <time.h> /* for timezone, localtime */
#include <string.h> /* for memmove */
#include <time.h> /* for timezone, localtime */
/* OS specific include*/
#include "net.h"
#include "timer.h"
@@ -40,7 +40,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "rp.h" /* ReadProperty handling */
#include "version.h"
@@ -51,7 +51,7 @@
#include "netport.h"
#endif
/* include the device object */
#include "device.h" /* me */
#include "device.h" /* me */
#if defined(__BORLANDC__) || defined(_WIN32)
/* seems to not be defined in time.h as specified by The Open Group */
@@ -82,14 +82,14 @@ static char *Description = "command line client";
/* static uint8_t Max_Segments_Accepted = 0; */
/* VT_Classes_Supported */
/* Active_VT_Sessions */
static BACNET_TIME Local_Time; /* rely on OS, if there is one */
static BACNET_DATE Local_Date; /* rely on OS, if there is one */
static BACNET_TIME Local_Time; /* rely on OS, if there is one */
static BACNET_DATE Local_Date; /* rely on OS, if there is one */
/* NOTE: BACnet UTC Offset is inverse of common practice.
If your UTC offset is -5hours of GMT,
then BACnet UTC offset is +5hours.
BACnet UTC offset is expressed in minutes. */
static int32_t UTC_Offset = 5 * 60;
static bool Daylight_Savings_Status = false; /* rely on OS */
static bool Daylight_Savings_Status = false; /* rely on OS */
#if defined(BACNET_TIME_MASTER)
static bool Align_Intervals;
static uint32_t Interval_Minutes;
@@ -112,68 +112,40 @@ static uint32_t Database_Revision = 0;
/* Profile_Name */
/* local forward (semi-private) and external prototypes */
int Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata);
extern int Routed_Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata);
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
extern int Routed_Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
extern bool Routed_Device_Write_Property_Local(
BACNET_WRITE_PROPERTY_DATA * wp_data);
BACNET_WRITE_PROPERTY_DATA *wp_data);
/* All included BACnet objects */
static object_functions_t Object_Table[] = {
{OBJECT_DEVICE,
NULL /* Init - don't init Device or it will recourse! */ ,
Device_Count,
Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name,
Device_Read_Property_Local,
NULL /* Write_Property */ ,
NULL /* Property_Lists */ ,
NULL /* ReadRangeInfo */ ,
NULL /* Iterator */ ,
NULL /* Value_Lists */ ,
NULL /* COV */ ,
NULL /* COV Clear */ ,
NULL /* Intrinsic Reporting */ },
{OBJECT_DEVICE, NULL /* Init - don't init Device or it will recourse! */,
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number, Device_Object_Name,
Device_Read_Property_Local, NULL /* Write_Property */,
NULL /* Property_Lists */, NULL /* ReadRangeInfo */, NULL /* Iterator */,
NULL /* Value_Lists */, NULL /* COV */, NULL /* COV Clear */,
NULL /* Intrinsic Reporting */},
#if (BACNET_PROTOCOL_REVISION >= 17)
{OBJECT_NETWORK_PORT,
Network_Port_Init,
Network_Port_Count,
Network_Port_Index_To_Instance,
Network_Port_Valid_Instance,
Network_Port_Object_Name,
Network_Port_Read_Property,
Network_Port_Write_Property,
Network_Port_Property_Lists,
NULL /* ReadRangeInfo */ ,
NULL /* Iterator */ ,
NULL /* Value_Lists */ ,
NULL /* COV */ ,
NULL /* COV Clear */ ,
NULL /* Intrinsic Reporting */ },
{OBJECT_NETWORK_PORT, Network_Port_Init, Network_Port_Count,
Network_Port_Index_To_Instance, Network_Port_Valid_Instance,
Network_Port_Object_Name, Network_Port_Read_Property,
Network_Port_Write_Property, Network_Port_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */},
#endif
{MAX_BACNET_OBJECT_TYPE,
NULL /* Init */ ,
NULL /* Count */ ,
NULL /* Index_To_Instance */ ,
NULL /* Valid_Instance */ ,
NULL /* Object_Name */ ,
NULL /* Read_Property */ ,
NULL /* Write_Property */ ,
NULL /* Property_Lists */ ,
NULL /* ReadRangeInfo */ ,
NULL /* Iterator */ ,
NULL /* Value_Lists */ ,
NULL /* COV */ ,
NULL /* COV Clear */ ,
NULL /* Intrinsic Reporting */ }
};
{MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */,
NULL /* Write_Property */, NULL /* Property_Lists */,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */}};
/** Glue function to let the Device object, when called by a handler,
* lookup which Object type needs to be invoked.
* @ingroup ObjHelpers
* @param Object_Type [in] The type of BACnet Object the handler wants to access.
* @param Object_Type [in] The type of BACnet Object the handler wants to
* access.
* @return Pointer to the group of object helper functions that implement this
* type of Object.
*/
@@ -195,14 +167,12 @@ static struct object_functions *Device_Objects_Find_Functions(
return (NULL);
}
unsigned Device_Count(
void)
unsigned Device_Count(void)
{
return 1;
}
uint32_t Device_Index_To_Instance(
unsigned index)
uint32_t Device_Index_To_Instance(unsigned index)
{
index = index;
return Object_Instance_Number;
@@ -216,8 +186,7 @@ uint32_t Device_Index_To_Instance(
* @ingroup ObjIntf
* @return The Instance number used in the BACNET_OBJECT_ID for the Device.
*/
uint32_t Device_Object_Instance_Number(
void)
uint32_t Device_Object_Instance_Number(void)
{
#ifdef BAC_ROUTING
return Routed_Device_Object_Instance_Number();
@@ -226,8 +195,7 @@ uint32_t Device_Object_Instance_Number(
#endif
}
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 */
@@ -241,15 +209,13 @@ bool Device_Set_Object_Instance_Number(
return status;
}
bool Device_Valid_Object_Instance_Number(
uint32_t object_id)
bool Device_Valid_Object_Instance_Number(uint32_t object_id)
{
return (Object_Instance_Number == object_id);
}
bool Device_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Device_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
bool status = false;
@@ -260,10 +226,9 @@ bool Device_Object_Name(
return status;
}
bool Device_Set_Object_Name(
BACNET_CHARACTER_STRING * object_name)
bool Device_Set_Object_Name(BACNET_CHARACTER_STRING *object_name)
{
bool status = false; /*return value */
bool status = false; /*return value */
if (!characterstring_same(&My_Object_Name, object_name)) {
/* Make the change and update the database revision */
@@ -274,17 +239,14 @@ bool Device_Set_Object_Name(
return status;
}
BACNET_DEVICE_STATUS Device_System_Status(
void)
BACNET_DEVICE_STATUS Device_System_Status(void)
{
return System_Status;
}
int Device_Set_System_Status(
BACNET_DEVICE_STATUS status,
bool local)
int Device_Set_System_Status(BACNET_DEVICE_STATUS status, bool local)
{
int result = 0; /*return value - 0 = ok, -1 = bad value, -2 = not allowed */
int result = 0; /*return value - 0 = ok, -1 = bad value, -2 = not allowed */
/* We limit the options available depending on whether the source is
* internal or external. */
@@ -345,39 +307,34 @@ int Device_Set_System_Status(
return (result);
}
const char *Device_Vendor_Name(
void)
const char *Device_Vendor_Name(void)
{
return Vendor_Name;
}
/** Returns the Vendor ID for this Device.
* See the assignments at http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm
* See the assignments at
* http://www.bacnet.org/VendorID/BACnet%20Vendor%20IDs.htm
* @return The Vendor ID of this Device.
*/
uint16_t Device_Vendor_Identifier(
void)
uint16_t Device_Vendor_Identifier(void)
{
return Vendor_Identifier;
}
void Device_Set_Vendor_Identifier(
uint16_t vendor_id)
void Device_Set_Vendor_Identifier(uint16_t vendor_id)
{
Vendor_Identifier = vendor_id;
}
const char *Device_Model_Name(
void)
const char *Device_Model_Name(void)
{
return Model_Name;
}
bool Device_Set_Model_Name(
const char *name,
size_t length)
bool Device_Set_Model_Name(const char *name, size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
if (length < sizeof(Model_Name)) {
memmove(Model_Name, name, length);
@@ -388,23 +345,19 @@ bool Device_Set_Model_Name(
return status;
}
const char *Device_Firmware_Revision(
void)
const char *Device_Firmware_Revision(void)
{
return BACnet_Version;
}
const char *Device_Application_Software_Version(
void)
const char *Device_Application_Software_Version(void)
{
return Application_Software_Version;
}
bool Device_Set_Application_Software_Version(
const char *name,
size_t length)
bool Device_Set_Application_Software_Version(const char *name, size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
if (length < sizeof(Application_Software_Version)) {
memmove(Application_Software_Version, name, length);
@@ -415,17 +368,14 @@ bool Device_Set_Application_Software_Version(
return status;
}
const char *Device_Description(
void)
const char *Device_Description(void)
{
return Description;
}
bool Device_Set_Description(
const char *name,
size_t length)
bool Device_Set_Description(const char *name, size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
if (length < sizeof(Description)) {
memmove(Description, name, length);
@@ -436,17 +386,14 @@ bool Device_Set_Description(
return status;
}
const char *Device_Location(
void)
const char *Device_Location(void)
{
return Location;
}
bool Device_Set_Location(
const char *name,
size_t length)
bool Device_Set_Location(const char *name, size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
if (length < sizeof(Location)) {
memmove(Location, name, length);
@@ -457,32 +404,27 @@ bool Device_Set_Location(
return status;
}
uint8_t Device_Protocol_Version(
void)
uint8_t Device_Protocol_Version(void)
{
return BACNET_PROTOCOL_VERSION;
}
uint8_t Device_Protocol_Revision(
void)
uint8_t Device_Protocol_Revision(void)
{
return BACNET_PROTOCOL_REVISION;
}
BACNET_SEGMENTATION Device_Segmentation_Supported(
void)
BACNET_SEGMENTATION Device_Segmentation_Supported(void)
{
return SEGMENTATION_NONE;
}
uint32_t Device_Database_Revision(
void)
uint32_t Device_Database_Revision(void)
{
return Database_Revision;
}
void Device_Set_Database_Revision(
uint32_t revision)
void Device_Set_Database_Revision(uint32_t revision)
{
Database_Revision = revision;
}
@@ -492,8 +434,7 @@ void Device_Set_Database_Revision(
* the most common operation if changing object names and ids is
* implemented.
*/
void Device_Inc_Database_Revision(
void)
void Device_Inc_Database_Revision(void)
{
Database_Revision++;
}
@@ -503,8 +444,7 @@ void Device_Inc_Database_Revision(
* for discovery, it must be consistent!
* @return The count of objects, for all supported Object types.
*/
unsigned Device_Object_List_Count(
void)
unsigned Device_Object_List_Count(void)
{
unsigned count = 0; /* number of objects */
struct object_functions *pObject = NULL;
@@ -531,10 +471,8 @@ unsigned Device_Object_List_Count(
* @param instance [out] The object's instance number, if found.
* @return True if found, else false.
*/
bool Device_Object_List_Identifier(
uint32_t array_index,
int *object_type,
uint32_t * instance)
bool Device_Object_List_Identifier(uint32_t array_index, int *object_type,
uint32_t *instance)
{
bool status = false;
unsigned count = 0;
@@ -558,19 +496,19 @@ bool Device_Object_List_Identifier(
* look for the index to instance to get the ID */
if (pObject->Object_Iterator) {
/* First find the first object */
temp_index = pObject->Object_Iterator(~(unsigned) 0);
temp_index = pObject->Object_Iterator(~(unsigned)0);
/* Then step through the objects to find the nth */
while (object_index != 0) {
temp_index = pObject->Object_Iterator(temp_index);
object_index--;
}
/* set the object_index up before falling through to next bit */
/* set the object_index up before falling through to next
* bit */
object_index = temp_index;
}
if (pObject->Object_Index_To_Instance) {
*object_type = pObject->Object_Type;
*instance =
pObject->Object_Index_To_Instance(object_index);
*instance = pObject->Object_Index_To_Instance(object_index);
status = true;
break;
}
@@ -587,13 +525,12 @@ bool Device_Object_List_Identifier(
* and the lookup succeeds, they will be given the resulting values.
* @param object_name [in] The desired Object Name to look for.
* @param object_type [out] The BACNET_OBJECT_TYPE of the matching Object.
* @param object_instance [out] The object instance number of the matching Object.
* @param object_instance [out] The object instance number of the matching
* Object.
* @return True on success or else False if not found.
*/
bool Device_Valid_Object_Name(
BACNET_CHARACTER_STRING * object_name1,
int *object_type,
uint32_t * object_instance)
bool Device_Valid_Object_Name(BACNET_CHARACTER_STRING *object_name1,
int *object_type, uint32_t *object_instance)
{
bool found = false;
int type = 0;
@@ -610,7 +547,7 @@ bool Device_Valid_Object_Name(
pObject = Device_Objects_Find_Functions(type);
if ((pObject != NULL) && (pObject->Object_Name != NULL) &&
(pObject->Object_Name(instance, &object_name2) &&
characterstring_same(object_name1, &object_name2))) {
characterstring_same(object_name1, &object_name2))) {
found = true;
if (object_type) {
*object_type = type;
@@ -631,11 +568,9 @@ bool Device_Valid_Object_Name(
* @param object_instance [in] The object instance number to be looked up.
* @return True if found, else False if no such Object in this device.
*/
bool Device_Valid_Object_Id(
int object_type,
uint32_t object_instance)
bool Device_Valid_Object_Id(int object_type, uint32_t object_instance)
{
bool status = false; /* return value */
bool status = false; /* return value */
struct object_functions *pObject = NULL;
pObject = Device_Objects_Find_Functions(object_type);
@@ -652,10 +587,9 @@ bool Device_Valid_Object_Id(
* @param object_name [out] The Object Name found for this child Object.
* @return True on success or else False if not found.
*/
bool Device_Object_Name_Copy(
BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Device_Object_Name_Copy(BACNET_OBJECT_TYPE object_type,
uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
struct object_functions *pObject = NULL;
bool found = false;
@@ -668,8 +602,7 @@ bool Device_Object_Name_Copy(
return found;
}
static void Update_Current_Time(
void)
static void Update_Current_Time(void)
{
struct tm *tblock = NULL;
#if defined(_MSC_VER)
@@ -700,15 +633,16 @@ int tm_isdst Daylight Savings flag.
#endif
if (tblock) {
datetime_set_date(&Local_Date, (uint16_t) tblock->tm_year + 1900,
(uint8_t) tblock->tm_mon + 1, (uint8_t) tblock->tm_mday);
datetime_set_date(&Local_Date, (uint16_t)tblock->tm_year + 1900,
(uint8_t)tblock->tm_mon + 1,
(uint8_t)tblock->tm_mday);
#if !defined(_MSC_VER)
datetime_set_time(&Local_Time, (uint8_t) tblock->tm_hour,
(uint8_t) tblock->tm_min, (uint8_t) tblock->tm_sec,
(uint8_t) (tv.tv_usec / 10000));
datetime_set_time(&Local_Time, (uint8_t)tblock->tm_hour,
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec,
(uint8_t)(tv.tv_usec / 10000));
#else
datetime_set_time(&Local_Time, (uint8_t) tblock->tm_hour,
(uint8_t) tblock->tm_min, (uint8_t) tblock->tm_sec, 0);
datetime_set_time(&Local_Time, (uint8_t)tblock->tm_hour,
(uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec, 0);
#endif
if (tblock->tm_isdst) {
Daylight_Savings_Status = true;
@@ -724,8 +658,7 @@ int tm_isdst Daylight Savings flag.
}
}
void Device_getCurrentDateTime(
BACNET_DATE_TIME * DateTime)
void Device_getCurrentDateTime(BACNET_DATE_TIME *DateTime)
{
Update_Current_Time();
@@ -821,11 +754,10 @@ uint32_t Device_Interval_Offset(void)
/* return the length of the apdu encoded or BACNET_STATUS_ERROR for error or
BACNET_STATUS_ABORT for abort message */
int Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata)
int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
uint32_t i = 0;
@@ -843,9 +775,8 @@ int Device_Read_Property_Local(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
apdu_len = encode_application_object_id(&apdu[0], OBJECT_DEVICE,
Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
apdu_len =
@@ -868,8 +799,7 @@ int Device_Read_Property_Local(
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_VENDOR_IDENTIFIER:
apdu_len =
encode_application_unsigned(&apdu[0], Vendor_Identifier);
apdu_len = encode_application_unsigned(&apdu[0], Vendor_Identifier);
break;
case PROP_MODEL_NAME:
characterstring_init_ansi(&char_string, Model_Name);
@@ -883,7 +813,7 @@ int Device_Read_Property_Local(
break;
case PROP_APPLICATION_SOFTWARE_VERSION:
characterstring_init_ansi(&char_string,
Application_Software_Version);
Application_Software_Version);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
@@ -893,22 +823,21 @@ int Device_Read_Property_Local(
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_PROTOCOL_VERSION:
apdu_len =
encode_application_unsigned(&apdu[0],
Device_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());
apdu_len = encode_application_unsigned(&apdu[0],
Device_Protocol_Revision());
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((BACNET_SERVICES_SUPPORTED) i));
bitstring_set_bit(
&bit_string, (uint8_t)i,
apdu_service_supported((BACNET_SERVICES_SUPPORTED)i));
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -918,7 +847,7 @@ int Device_Read_Property_Local(
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);
bitstring_set_bit(&bit_string, (uint8_t)i, false);
}
/* set the object types with objects to supported */
@@ -942,16 +871,15 @@ int Device_Read_Property_Local(
/* your maximum APDU size. */
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= count; i++) {
found =
Device_Object_List_Identifier(i, &object_type,
&instance);
found = Device_Object_List_Identifier(i, &object_type,
&instance);
if (found) {
len =
encode_application_object_id(&apdu[apdu_len],
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? Don't check for last entry */
/* can we all fit into the APDU? Don't check for last
* entry */
if ((i != count) && (apdu_len + len) >= MAX_APDU) {
/* Abort response */
rpdata->error_code =
@@ -968,13 +896,11 @@ int Device_Read_Property_Local(
}
}
} else {
found =
Device_Object_List_Identifier(rpdata->array_index,
&object_type, &instance);
found = Device_Object_List_Identifier(rpdata->array_index,
&object_type, &instance);
if (found) {
apdu_len =
encode_application_object_id(&apdu[0], object_type,
instance);
apdu_len = encode_application_object_id(
&apdu[0], object_type, instance);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -986,9 +912,8 @@ int Device_Read_Property_Local(
apdu_len = encode_application_unsigned(&apdu[0], MAX_APDU);
break;
case PROP_SEGMENTATION_SUPPORTED:
apdu_len =
encode_application_enumerated(&apdu[0],
Device_Segmentation_Supported());
apdu_len = encode_application_enumerated(
&apdu[0], Device_Segmentation_Supported());
break;
case PROP_APDU_TIMEOUT:
apdu_len = encode_application_unsigned(&apdu[0], apdu_timeout());
@@ -997,18 +922,17 @@ int Device_Read_Property_Local(
apdu_len = encode_application_unsigned(&apdu[0], apdu_retries());
break;
case PROP_DEVICE_ADDRESS_BINDING:
/* FIXME: the real max apdu remaining should be passed into function */
/* FIXME: the real max apdu remaining should be passed into function
*/
apdu_len = address_list_encode(&apdu[0], MAX_APDU);
break;
case PROP_DATABASE_REVISION:
apdu_len =
encode_application_unsigned(&apdu[0], Database_Revision);
apdu_len = encode_application_unsigned(&apdu[0], Database_Revision);
break;
#if defined(BACDL_MSTP)
case PROP_MAX_INFO_FRAMES:
apdu_len =
encode_application_unsigned(&apdu[0],
dlmstp_max_info_frames());
encode_application_unsigned(&apdu[0], dlmstp_max_info_frames());
break;
case PROP_MAX_MASTER:
apdu_len =
@@ -1034,7 +958,8 @@ int Device_Read_Property_Local(
return apdu_len;
}
/** Looks up the requested Object and Property, and encodes its Value in an APDU.
/** Looks up the requested Object and Property, and encodes its Value in an
* APDU.
* @ingroup ObjIntf
* If the Object or Property can't be found, sets the error class and code.
*
@@ -1042,8 +967,7 @@ int Device_Read_Property_Local(
* on entry, and APDU message on return.
* @return The length of the APDU on success, else BACNET_STATUS_ERROR
*/
int Device_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Device_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = BACNET_STATUS_ERROR;
struct object_functions *pObject = NULL;
@@ -1078,14 +1002,13 @@ int Device_Read_Property(
* Each Child Object must provide some implementation of each of these
* functions in order to properly support the default handlers.
*/
void Device_Init(
object_functions_t * object_table)
void Device_Init(object_functions_t *object_table)
{
struct object_functions *pObject = NULL;
characterstring_init_ansi(&My_Object_Name, "SimpleClient");
/* we don't use the object table passed in */
(void) object_table;
(void)object_table;
pObject = &Object_Table[0];
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
if (pObject->Object_Init) {
+393 -700
View File
File diff suppressed because it is too large Load Diff
+115 -154
View File
@@ -1,44 +1,45 @@
/**************************************************************************
*
* Copyright (C) 2005,2010 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2005,2010 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/** @file gw_device.c Functions that extend the Device object to support routing. */
/** @file gw_device.c Functions that extend the Device object to support
* routing. */
#include <stdbool.h>
#include <stdint.h>
#include <string.h> /* for memmove */
#include <time.h> /* for timezone, localtime */
#include <string.h> /* for memmove */
#include <time.h> /* for timezone, localtime */
#include "bacdef.h"
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "apdu.h"
#include "wp.h" /* write property handling */
#include "rp.h" /* read property handling */
#include "version.h"
#include "device.h" /* me */
#include "device.h" /* me */
#include "handlers.h"
#include "datalink.h"
#include "address.h"
@@ -56,7 +57,7 @@
#include "ms-input.h"
#include "trendlog.h"
#if defined(BACFILE)
#include "bacfile.h" /* object list dependency */
#include "bacfile.h" /* object list dependency */
#endif
/* os specfic includes */
#include "timer.h"
@@ -68,19 +69,15 @@ long int timezone;
#endif
/* local forward and external prototypes */
extern int Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata);
extern bool Device_Write_Property_Local(
BACNET_WRITE_PROPERTY_DATA * wp_data);
int Routed_Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata);
bool Routed_Device_Write_Property_Local(
BACNET_WRITE_PROPERTY_DATA * wp_data);
extern int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
extern bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
int Routed_Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
bool Routed_Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data);
#if !defined(BAC_ROUTING)
#ifdef _MSC_VER
#pragma message This file should not be included in the build unless BAC_ROUTING is enabled.
#pragma message This file should not be included in the build unless \
BAC_ROUTING is enabled.
#else
#warning This file should not be included in the build unless BAC_ROUTING is enabled.
#endif
@@ -118,10 +115,9 @@ uint16_t iCurrent_Device_Idx = 0;
* @return The index of this instance in the Devices[] array,
* or -1 if there isn't enough room to add this Device.
*/
uint16_t Add_Routed_Device(
uint32_t Object_Instance,
BACNET_CHARACTER_STRING * sObject_Name,
const char *sDescription)
uint16_t Add_Routed_Device(uint32_t Object_Instance,
BACNET_CHARACTER_STRING *sObject_Name,
const char *sDescription)
{
int i = Num_Managed_Devices;
if (i < MAX_NUM_DEVICES) {
@@ -132,21 +128,21 @@ uint16_t Add_Routed_Device(
pDev->bacObj.Object_Instance_Number = Object_Instance;
if (sObject_Name != NULL)
Routed_Device_Set_Object_Name(sObject_Name->encoding,
sObject_Name->value, sObject_Name->length);
sObject_Name->value,
sObject_Name->length);
else
Routed_Device_Set_Object_Name(CHARACTER_UTF8, "No Name",
strlen("No Name"));
strlen("No Name"));
if (sDescription != NULL)
Routed_Device_Set_Description(sDescription, strlen(sDescription));
else
Routed_Device_Set_Description("No Descr", strlen("No Descr"));
pDev->Database_Revision = 0; /* Reset/Initialize now */
pDev->Database_Revision = 0; /* Reset/Initialize now */
return i;
} else
return -1;
}
/** Return the Device Object descriptive data for the indicated entry.
* @param idx [in] Index into Devices[] array being requested.
* 0 is for the main, gateway Device entry.
@@ -156,8 +152,7 @@ uint16_t Add_Routed_Device(
* @return Pointer to the requested Device Object data, or NULL if the idx
* is for an invalid row entry (eg, after the last good Device).
*/
DEVICE_OBJECT_DATA *Get_Routed_Device_Object(
int idx)
DEVICE_OBJECT_DATA *Get_Routed_Device_Object(int idx)
{
if (idx == -1)
return &Devices[iCurrent_Device_Idx];
@@ -174,11 +169,10 @@ DEVICE_OBJECT_DATA *Get_Routed_Device_Object(
* -1 is a special case meaning "whichever iCurrent_Device_Idx
* is currently set to"
* If valid idx, will set iCurrent_Device_Idx with the idx
* @return Pointer to the requested Device Object BACnet address, or NULL if the idx
* is for an invalid row entry (eg, after the last good Device).
* @return Pointer to the requested Device Object BACnet address, or NULL if the
* idx is for an invalid row entry (eg, after the last good Device).
*/
BACNET_ADDRESS *Get_Routed_Device_Address(
int idx)
BACNET_ADDRESS *Get_Routed_Device_Address(int idx)
{
if (idx == -1)
return &Devices[iCurrent_Device_Idx].bacDevAddr;
@@ -189,8 +183,6 @@ BACNET_ADDRESS *Get_Routed_Device_Address(
return NULL;
}
/** Get the currently active BACnet address.
* This is an implementation of the datalink_get_my_address() template for
* devices with routing.
@@ -198,16 +190,14 @@ BACNET_ADDRESS *Get_Routed_Device_Address(
* @param my_address [out] Points to the currently active Device Object's
* BACnet address.
*/
void routed_get_my_address(
BACNET_ADDRESS * my_address)
void routed_get_my_address(BACNET_ADDRESS *my_address)
{
if (my_address) {
memcpy(my_address, &Devices[iCurrent_Device_Idx].bacDevAddr,
sizeof(BACNET_ADDRESS));
sizeof(BACNET_ADDRESS));
}
}
/** See if the Gateway or Routed Device at the given idx matches
* the given MAC address.
* Has the desirable side-effect of setting iCurrent_Device_Idx to the
@@ -225,10 +215,8 @@ void routed_get_my_address(
* meaning MAC broadcast, so it's an automatic match).
* Else False if no match or invalid idx is given.
*/
bool Routed_Device_Address_Lookup(
int idx,
uint8_t address_len,
uint8_t * mac_adress)
bool Routed_Device_Address_Lookup(int idx, uint8_t address_len,
uint8_t *mac_adress)
{
bool result = false;
DEVICE_OBJECT_DATA *pDev = &Devices[idx];
@@ -244,7 +232,7 @@ bool Routed_Device_Address_Lookup(
if (pDev->bacDevAddr.mac[i] != mac_adress[i])
break;
}
if (i == address_len) { /* Success! */
if (i == address_len) { /* Success! */
iCurrent_Device_Idx = idx;
result = true;
}
@@ -253,7 +241,6 @@ bool Routed_Device_Address_Lookup(
return result;
}
/** Find the next Gateway or Routed Device at the given MAC address,
* starting the search at the "cursor".
* Has the desirable side-effect of setting internal iCurrent_Device_Idx
@@ -261,31 +248,27 @@ bool Routed_Device_Address_Lookup(
* functions.
*
* @param dest [in] The BACNET_ADDRESS of the message's destination.
* If the Length of the mac_adress[] field is 0, then this is a MAC
* broadcast. Otherwise, size is determined
* by the DLL type (eg, 6 for BIP and 2 for MSTP).
* @param DNET_list [in] List of our reachable downstream BACnet Network numbers.
* Normally just one valid entry; terminated with a -1 value.
* If the Length of the mac_adress[] field is 0, then this is a
* MAC broadcast. Otherwise, size is determined by the DLL type (eg, 6 for BIP
* and 2 for MSTP).
* @param DNET_list [in] List of our reachable downstream BACnet Network
* numbers. Normally just one valid entry; terminated with a -1 value.
* @param cursor [in,out] The concept of the cursor is that it is a starting
* "hint" for the search; on return, it is updated to provide the
* cursor value to use with a subsequent GetNext call, or it
* equals -1 if there are no further matches.
* Set it to 0 on entry to access the main, gateway Device entry, or
* to start looping through the routed devices.
* "hint" for the search; on return, it is updated to provide
* the cursor value to use with a subsequent GetNext call, or it equals -1 if
* there are no further matches. Set it to 0 on entry to access the main,
* gateway Device entry, or to start looping through the routed devices.
* Otherwise, its returned value is implementation-dependent and the
* calling function should not alter or interpret it.
*
* @return True if the MAC addresses match (or if BACNET_BROADCAST_NETWORK and
* the dest->len is 0, meaning MAC bcast, so it's an automatic match).
* Else False if no match or invalid idx is given; the cursor will
* be returned as -1 in these cases.
* the dest->len is 0, meaning MAC bcast, so it's an automatic
* match). Else False if no match or invalid idx is given; the cursor will be
* returned as -1 in these cases.
*/
bool Routed_Device_GetNext(
BACNET_ADDRESS * dest,
int *DNET_list,
int *cursor)
bool Routed_Device_GetNext(BACNET_ADDRESS *dest, int *DNET_list, int *cursor)
{
int dnet = DNET_list[0]; /* Get the DNET of our virtual network */
int dnet = DNET_list[0]; /* Get the DNET of our virtual network */
int idx = *cursor;
bool bSuccess = false;
@@ -319,44 +302,40 @@ bool Routed_Device_GetNext(
* For broadcasts, all Devices get a chance at it.
*/
else if (dest->net == dnet) {
if (idx == 0) /* Step over this case (starting point) */
if (idx == 0) /* Step over this case (starting point) */
idx = 1;
while (idx < MAX_NUM_DEVICES) {
bSuccess =
Routed_Device_Address_Lookup(idx++, dest->len, dest->adr);
if (bSuccess)
break; /* We don't need to keep looking */
break; /* We don't need to keep looking */
}
}
if (!bSuccess)
*cursor = -1;
else if (idx == MAX_NUM_DEVICES) /* No more to GetNext */
else if (idx == MAX_NUM_DEVICES) /* No more to GetNext */
*cursor = -1;
else
*cursor = idx;
return bSuccess;
}
/** Check if the destination network is reachable - is it our virtual network,
* or local or else broadcast.
*
* @param dest_net [in] The BACnet network number of a message's destination.
* Success if it is our virtual network number, or 0 (local for the
* gateway, or 0xFFFF for a broadcast network number.
* @param DNET_list [in] List of our reachable downstream BACnet Network numbers.
* Normally just one valid entry; terminated with a -1 value.
* Success if it is our virtual network number, or 0 (local for
* the gateway, or 0xFFFF for a broadcast network number.
* @param DNET_list [in] List of our reachable downstream BACnet Network
* numbers. Normally just one valid entry; terminated with a -1 value.
* @return True if matches our virtual network, or is for the local network
* Device (the gateway), or is BACNET_BROADCAST_NETWORK, which is
* an automatic match.
* Else False if not a reachable network.
* Device (the gateway), or is BACNET_BROADCAST_NETWORK,
* which is an automatic match. Else False if not a reachable network.
*/
bool Routed_Device_Is_Valid_Network(
uint16_t dest_net,
int *DNET_list)
bool Routed_Device_Is_Valid_Network(uint16_t dest_net, int *DNET_list)
{
int dnet = DNET_list[0]; /* Get the DNET of our virtual network */
int dnet = DNET_list[0]; /* Get the DNET of our virtual network */
bool bSuccess = false;
/* First, see if it's a BACnet broadcast (automatic pass). */
@@ -374,11 +353,9 @@ bool Routed_Device_Is_Valid_Network(
return bSuccess;
}
/* methods to override the normal Device objection functions */
uint32_t Routed_Device_Index_To_Instance(
unsigned index)
uint32_t Routed_Device_Index_To_Instance(unsigned index)
{
index = index;
return Devices[iCurrent_Device_Idx].bacObj.Object_Instance_Number;
@@ -389,11 +366,11 @@ uint32_t Routed_Device_Index_To_Instance(
* iCurrent_Device_Idx must have been set to point to this Device Object
* before this function is called.
* @param object_id [in] Object ID of the desired Device object.
* If the wildcard value (BACNET_MAX_INSTANCE), always matches.
* If the wildcard value (BACNET_MAX_INSTANCE), always
* matches.
* @return True if Object ID matches the present Device, else False.
*/
bool Routed_Device_Valid_Object_Instance_Number(
uint32_t object_id)
bool Routed_Device_Valid_Object_Instance_Number(uint32_t object_id)
{
bool bResult = false;
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
@@ -404,14 +381,12 @@ bool Routed_Device_Valid_Object_Instance_Number(
return bResult;
}
bool Routed_Device_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Routed_Device_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
if (object_instance == pDev->bacObj.Object_Instance_Number) {
return characterstring_init_ansi(object_name,
pDev->bacObj.Object_Name);
return characterstring_init_ansi(object_name, pDev->bacObj.Object_Name);
}
return false;
@@ -423,10 +398,9 @@ bool Routed_Device_Name(
* @return The length of the apdu encoded, or BACNET_STATUS_ERROR for error or
* BACNET_STATUS_ABORT for abort message.
*/
int Routed_Device_Read_Property_Local(
BACNET_READ_PROPERTY_DATA * rpdata)
int Routed_Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
@@ -438,9 +412,8 @@ int Routed_Device_Read_Property_Local(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_DEVICE,
pDev->bacObj.Object_Instance_Number);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_DEVICE, pDev->bacObj.Object_Instance_Number);
break;
case PROP_OBJECT_NAME:
characterstring_init_ansi(&char_string, pDev->bacObj.Object_Name);
@@ -464,17 +437,15 @@ int Routed_Device_Read_Property_Local(
return (apdu_len);
}
bool Routed_Device_Write_Property_Local(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Routed_Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -493,12 +464,13 @@ bool Routed_Device_Write_Property_Local(
case PROP_OBJECT_IDENTIFIER:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_OBJECT_ID,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if ((value.type.Object_Id.type == OBJECT_DEVICE) &&
(Routed_Device_Set_Object_Instance_Number(value.type.
Object_Id.instance))) {
/* FIXME: we could send an I-Am broadcast to let the world know */
(Routed_Device_Set_Object_Instance_Number(
value.type.Object_Id.instance))) {
/* FIXME: we could send an I-Am broadcast to let the world
* know */
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -509,10 +481,10 @@ bool Routed_Device_Write_Property_Local(
case PROP_OBJECT_NAME:
status =
WPValidateString(&value, MAX_DEV_NAME_LEN, false,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Routed_Device_Set_Object_Name(characterstring_encoding(&value.
type.Character_String),
Routed_Device_Set_Object_Name(
characterstring_encoding(&value.type.Character_String),
characterstring_value(&value.type.Character_String),
characterstring_length(&value.type.Character_String));
}
@@ -532,14 +504,12 @@ bool Routed_Device_Write_Property_Local(
*
* @return The Instance number of the currently active Device.
*/
uint32_t Routed_Device_Object_Instance_Number(
void)
uint32_t Routed_Device_Object_Instance_Number(void)
{
return Devices[iCurrent_Device_Idx].bacObj.Object_Instance_Number;
}
bool Routed_Device_Set_Object_Instance_Number(
uint32_t object_id)
bool Routed_Device_Set_Object_Instance_Number(uint32_t object_id)
{
bool status = true; /* return value */
@@ -559,12 +529,10 @@ bool Routed_Device_Set_Object_Instance_Number(
* @param object_name [in] Character String for the new Object Name.
* @return True if succeed in updating Object Name, else False.
*/
bool Routed_Device_Set_Object_Name(
uint8_t encoding,
const char *value,
size_t length)
bool Routed_Device_Set_Object_Name(uint8_t encoding, const char *value,
size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
if ((encoding == CHARACTER_UTF8) && (length < MAX_DEV_NAME_LEN)) {
@@ -578,11 +546,9 @@ bool Routed_Device_Set_Object_Name(
return status;
}
bool Routed_Device_Set_Description(
const char *name,
size_t length)
bool Routed_Device_Set_Description(const char *name, size_t length)
{
bool status = false; /*return value */
bool status = false; /*return value */
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
if (length < MAX_DEV_DESC_LEN) {
@@ -594,20 +560,17 @@ bool Routed_Device_Set_Description(
return status;
}
/*
* Shortcut for incrementing database revision as this is potentially
* the most common operation if changing object names and ids is
* implemented.
*/
void Routed_Device_Inc_Database_Revision(
void)
void Routed_Device_Inc_Database_Revision(void)
{
DEVICE_OBJECT_DATA *pDev = &Devices[iCurrent_Device_Idx];
pDev->Database_Revision++;
}
/** Check to see if the current Device supports this service.
* Presently checks for RD and DCC and only allows them if the current
* device is the gateway device.
@@ -621,11 +584,9 @@ void Routed_Device_Inc_Database_Revision(
* just 1 if no apdu_buff was supplied and service is not supported,
* else 0 if service is approved for the current device.
*/
int Routed_Device_Service_Approval(
BACNET_CONFIRMED_SERVICE service,
int service_argument,
uint8_t * apdu_buff,
uint8_t invoke_id)
int Routed_Device_Service_Approval(BACNET_CONFIRMED_SERVICE service,
int service_argument, uint8_t *apdu_buff,
uint8_t invoke_id)
{
int len = 0;
switch (service) {
@@ -635,9 +596,9 @@ int Routed_Device_Service_Approval(
if (apdu_buff != NULL)
len =
reject_encode_apdu(apdu_buff, invoke_id,
REJECT_REASON_UNRECOGNIZED_SERVICE);
REJECT_REASON_UNRECOGNIZED_SERVICE);
else
len = 1; /* Non-zero return */
len = 1; /* Non-zero return */
}
break;
case SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL:
@@ -646,9 +607,9 @@ int Routed_Device_Service_Approval(
if (apdu_buff != NULL)
len =
reject_encode_apdu(apdu_buff, invoke_id,
REJECT_REASON_UNRECOGNIZED_SERVICE);
REJECT_REASON_UNRECOGNIZED_SERVICE);
else
len = 1; /* Non-zero return */
len = 1; /* Non-zero return */
}
break;
default:
+49 -74
View File
@@ -41,7 +41,7 @@
#include "bacenum.h"
#include "bacapp.h"
#include "bactext.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "device.h"
#include "handlers.h"
/* me! */
@@ -52,31 +52,25 @@
#endif
struct integer_object {
bool Out_Of_Service:1;
bool Out_Of_Service : 1;
int32_t Present_Value;
uint16_t Units;
};
struct integer_object Integer_Value[MAX_INTEGER_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Integer_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_UNITS,
-1
};
static const int Integer_Value_Properties_Required[] = {PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_UNITS,
-1};
static const int Integer_Value_Properties_Optional[] = {
PROP_OUT_OF_SERVICE,
-1
};
static const int Integer_Value_Properties_Optional[] = {PROP_OUT_OF_SERVICE,
-1};
static const int Integer_Value_Properties_Proprietary[] = {
-1
};
static const int Integer_Value_Properties_Proprietary[] = {-1};
/**
* Returns the list of required, optional, and proprietary properties.
@@ -89,10 +83,8 @@ static const int Integer_Value_Properties_Proprietary[] = {
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Integer_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Integer_Value_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Integer_Value_Properties_Required;
@@ -111,8 +103,7 @@ void Integer_Value_Property_Lists(
*
* @return true if the instance is valid, and false if not
*/
bool Integer_Value_Valid_Instance(
uint32_t object_instance)
bool Integer_Value_Valid_Instance(uint32_t object_instance)
{
unsigned int index;
@@ -129,8 +120,7 @@ bool Integer_Value_Valid_Instance(
*
* @return Number of Analog Value objects
*/
unsigned Integer_Value_Count(
void)
unsigned Integer_Value_Count(void)
{
return MAX_INTEGER_VALUES;
}
@@ -143,8 +133,7 @@ unsigned Integer_Value_Count(
*
* @return object instance-number for the given index
*/
uint32_t Integer_Value_Index_To_Instance(
unsigned index)
uint32_t Integer_Value_Index_To_Instance(unsigned index)
{
uint32_t instance = 1;
@@ -162,8 +151,7 @@ uint32_t Integer_Value_Index_To_Instance(
* @return index for the given instance-number, or MAX_INTEGER_VALUES
* if not valid.
*/
unsigned Integer_Value_Instance_To_Index(
uint32_t object_instance)
unsigned Integer_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_INTEGER_VALUES;
@@ -184,8 +172,7 @@ unsigned Integer_Value_Instance_To_Index(
*
* @return present-value of the object
*/
int32_t Integer_Value_Present_Value(
uint32_t object_instance)
int32_t Integer_Value_Present_Value(uint32_t object_instance)
{
int32_t value = 0;
unsigned int index;
@@ -206,10 +193,8 @@ int32_t Integer_Value_Present_Value(
*
* @return true if values are within range and present-value is set.
*/
bool Integer_Value_Present_Value_Set(
uint32_t object_instance,
int32_t value,
uint8_t priority)
bool Integer_Value_Present_Value_Set(uint32_t object_instance, int32_t value,
uint8_t priority)
{
bool status = false;
unsigned int index;
@@ -234,9 +219,8 @@ bool Integer_Value_Present_Value_Set(
*
* @return true if object-name was retrieved
*/
bool Integer_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Integer_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
char text_string[32] = "";
unsigned int index;
@@ -244,7 +228,8 @@ bool Integer_Value_Object_Name(
index = Integer_Value_Instance_To_Index(object_instance);
if (index < MAX_INTEGER_VALUES) {
sprintf(text_string, "ANALOG VALUE %lu", (unsigned long) object_instance);
sprintf(text_string, "ANALOG VALUE %lu",
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -258,8 +243,7 @@ bool Integer_Value_Object_Name(
*
* @return units property value
*/
uint16_t Integer_Value_Units(
uint32_t instance)
uint16_t Integer_Value_Units(uint32_t instance)
{
unsigned int index;
uint16_t units = UNITS_NO_UNITS;
@@ -280,9 +264,7 @@ uint16_t Integer_Value_Units(
*
* @return true if the units property value was set
*/
bool Integer_Value_Units_Set(
uint32_t instance,
uint16_t units)
bool Integer_Value_Units_Set(uint32_t instance, uint16_t units)
{
unsigned int index = 0;
bool status = false;
@@ -304,15 +286,14 @@ bool Integer_Value_Units_Set(
*
* @return out-of-service property value
*/
bool Integer_Value_Out_Of_Service(
uint32_t instance)
bool Integer_Value_Out_Of_Service(uint32_t instance)
{
unsigned int index = 0;
bool value = false;
index = Integer_Value_Instance_To_Index(instance);
if (index < MAX_INTEGER_VALUES) {
value= Integer_Value[index].Out_Of_Service;
value = Integer_Value[index].Out_Of_Service;
}
return value;
@@ -326,9 +307,7 @@ bool Integer_Value_Out_Of_Service(
*
* @return true if the out-of-service property value was set
*/
void Integer_Value_Out_Of_Service_Set(
uint32_t instance,
bool value)
void Integer_Value_Out_Of_Service_Set(uint32_t instance, bool value)
{
unsigned int index = 0;
@@ -348,10 +327,9 @@ void Integer_Value_Out_Of_Service_Set(
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Integer_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Integer_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
uint8_t *apdu = NULL;
@@ -367,9 +345,8 @@ int Integer_Value_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_INTEGER_VALUE,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_INTEGER_VALUE, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Integer_Value_Object_Name(rpdata->object_instance, &char_string);
@@ -381,7 +358,8 @@ int Integer_Value_Read_Property(
encode_application_enumerated(&apdu[0], OBJECT_INTEGER_VALUE);
break;
case PROP_PRESENT_VALUE:
integer_value = Integer_Value_Present_Value(rpdata->object_instance);
integer_value =
Integer_Value_Present_Value(rpdata->object_instance);
apdu_len = encode_application_signed(&apdu[0], integer_value);
break;
case PROP_STATUS_FLAGS:
@@ -428,17 +406,15 @@ int Integer_Value_Read_Property(
*
* @return false if an error is loaded, true if no errors
*/
bool Integer_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Integer_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -456,22 +432,22 @@ bool Integer_Value_Write_Property(
}
switch (wp_data->object_property) {
case PROP_PRESENT_VALUE:
status =
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_SIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
if (status) {
&wp_data->error_class, &wp_data->error_code);
if (status) {
Integer_Value_Present_Value_Set(wp_data->object_instance,
value.type.Signed_Int, wp_data->priority);
value.type.Signed_Int,
wp_data->priority);
}
break;
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Integer_Value_Out_Of_Service_Set(
wp_data->object_instance,
value.type.Boolean);
Integer_Value_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -494,8 +470,7 @@ bool Integer_Value_Write_Property(
/**
* Initializes the Integer Value object data
*/
void Integer_Value_Init(
void)
void Integer_Value_Init(void)
{
unsigned index = 0;
+202 -260
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2007 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Load Control Objects - customize for your use */
/* from 135-2004-Addendum e */
@@ -29,13 +29,13 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h> /* for memcpy */
#include <string.h> /* for memcpy */
#include <time.h>
#include "bacdef.h"
#include "bacdcode.h"
#include "datetime.h"
#include "bacenum.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "lc.h"
#include "ao.h"
#include "wp.h"
@@ -51,9 +51,9 @@ static BACNET_SHED_STATE Present_Value[MAX_LOAD_CONTROLS];
/* load control objects are required to support LEVEL */
typedef enum BACnetShedLevelType {
BACNET_SHED_TYPE_PERCENT, /* Unsigned */
BACNET_SHED_TYPE_LEVEL, /* Unsigned */
BACNET_SHED_TYPE_AMOUNT /* REAL */
BACNET_SHED_TYPE_PERCENT, /* Unsigned */
BACNET_SHED_TYPE_LEVEL, /* Unsigned */
BACNET_SHED_TYPE_AMOUNT /* REAL */
} BACNET_SHED_LEVEL_TYPE;
#define DEFAULT_VALUE_PERCENT 100
@@ -126,17 +126,9 @@ static unsigned Shed_Levels[MAX_LOAD_CONTROLS][MAX_SHED_LEVELS];
Load Control object can take on. It is the same for
all the load control objects in this example device. */
static char *Shed_Level_Descriptions[MAX_SHED_LEVELS] = {
"dim lights 10%",
"dim lights 20%",
"dim lights 30%"
};
static float Shed_Level_Values[MAX_SHED_LEVELS] = {
90.0,
80.0,
70.0
};
"dim lights 10%", "dim lights 20%", "dim lights 30%"};
static float Shed_Level_Values[MAX_SHED_LEVELS] = {90.0, 80.0, 70.0};
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Load_Control_Properties_Required[] = {
@@ -155,23 +147,15 @@ static const int Load_Control_Properties_Required[] = {
PROP_ACTUAL_SHED_LEVEL,
PROP_SHED_LEVELS,
PROP_SHED_LEVEL_DESCRIPTIONS,
-1
};
-1};
static const int Load_Control_Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_FULL_DUTY_BASELINE,
-1
};
PROP_DESCRIPTION, PROP_FULL_DUTY_BASELINE, -1};
static const int Load_Control_Properties_Proprietary[] = {
-1
};
static const int Load_Control_Properties_Proprietary[] = {-1};
void Load_Control_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Load_Control_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Load_Control_Properties_Required;
@@ -183,8 +167,7 @@ void Load_Control_Property_Lists(
return;
}
void Load_Control_Init(
void)
void Load_Control_Init(void)
{
unsigned i, j;
@@ -199,7 +182,7 @@ void Load_Control_Init(
Shed_Duration[i] = 0;
Duty_Window[i] = 0;
Load_Control_Enable[i] = true;
Full_Duty_Baseline[i] = 1.500; /* kilowatts */
Full_Duty_Baseline[i] = 1.500; /* kilowatts */
Expected_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
Expected_Shed_Level[i].value.level = 0;
Actual_Shed_Level[i].type = BACNET_SHED_TYPE_LEVEL;
@@ -217,8 +200,7 @@ void Load_Control_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Load_Control_Valid_Instance(
uint32_t object_instance)
bool Load_Control_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_LOAD_CONTROLS)
return true;
@@ -228,8 +210,7 @@ bool Load_Control_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Load_Control_Count(
void)
unsigned Load_Control_Count(void)
{
return MAX_LOAD_CONTROLS;
}
@@ -237,8 +218,7 @@ unsigned Load_Control_Count(
/* 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 Load_Control_Index_To_Instance(
unsigned index)
uint32_t Load_Control_Index_To_Instance(unsigned index)
{
return index;
}
@@ -246,8 +226,7 @@ uint32_t Load_Control_Index_To_Instance(
/* 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 Load_Control_Instance_To_Index(
uint32_t object_instance)
unsigned Load_Control_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_LOAD_CONTROLS;
@@ -257,8 +236,7 @@ unsigned Load_Control_Instance_To_Index(
return index;
}
static BACNET_SHED_STATE Load_Control_Present_Value(
uint32_t object_instance)
static BACNET_SHED_STATE Load_Control_Present_Value(uint32_t object_instance)
{
BACNET_SHED_STATE value = BACNET_SHED_INACTIVE;
unsigned index = 0;
@@ -272,11 +250,10 @@ static BACNET_SHED_STATE Load_Control_Present_Value(
}
/* note: the object name must be unique within this device */
bool Load_Control_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Load_Control_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_LOAD_CONTROLS) {
@@ -287,37 +264,35 @@ bool Load_Control_Object_Name(
return status;
}
static void Update_Current_Time(
BACNET_DATE_TIME * bdatetime)
static void Update_Current_Time(BACNET_DATE_TIME *bdatetime)
{
time_t timer;
struct tm *tblock;
/*
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
*/
/*
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
*/
timer = time(NULL);
tblock = localtime(&timer);
datetime_set_values(bdatetime, (uint16_t) tblock->tm_year,
(uint8_t) tblock->tm_mon, (uint8_t) tblock->tm_mday,
(uint8_t) tblock->tm_hour, (uint8_t) tblock->tm_min,
(uint8_t) tblock->tm_sec, 0);
datetime_set_values(bdatetime, (uint16_t)tblock->tm_year,
(uint8_t)tblock->tm_mon, (uint8_t)tblock->tm_mday,
(uint8_t)tblock->tm_hour, (uint8_t)tblock->tm_min,
(uint8_t)tblock->tm_sec, 0);
}
/* convert the shed level request into an Analog Output Present_Value */
static float Requested_Shed_Level_Value(
int object_index)
static float Requested_Shed_Level_Value(int object_index)
{
unsigned shed_level_index = 0;
unsigned i = 0;
@@ -326,13 +301,12 @@ static float Requested_Shed_Level_Value(
switch (Requested_Shed_Level[object_index].type) {
case BACNET_SHED_TYPE_PERCENT:
requested_level =
(float) Requested_Shed_Level[object_index].value.percent;
(float)Requested_Shed_Level[object_index].value.percent;
break;
case BACNET_SHED_TYPE_AMOUNT:
/* Assumptions: wattage is linear with analog output level */
requested_level =
Full_Duty_Baseline[object_index] -
Requested_Shed_Level[object_index].value.amount;
requested_level = Full_Duty_Baseline[object_index] -
Requested_Shed_Level[object_index].value.amount;
requested_level /= Full_Duty_Baseline[object_index];
requested_level *= 100.0;
break;
@@ -350,9 +324,7 @@ static float Requested_Shed_Level_Value(
return requested_level;
}
static void Shed_Level_Copy(
BACNET_SHED_LEVEL * dest,
BACNET_SHED_LEVEL * src)
static void Shed_Level_Copy(BACNET_SHED_LEVEL *dest, BACNET_SHED_LEVEL *src)
{
if (dest && src) {
dest->type = src->type;
@@ -371,9 +343,8 @@ static void Shed_Level_Copy(
}
}
static void Shed_Level_Default_Set(
BACNET_SHED_LEVEL * dest,
BACNET_SHED_LEVEL_TYPE type)
static void Shed_Level_Default_Set(BACNET_SHED_LEVEL *dest,
BACNET_SHED_LEVEL_TYPE type)
{
if (dest) {
dest->type = type;
@@ -392,8 +363,7 @@ static void Shed_Level_Default_Set(
}
}
static bool Able_To_Meet_Shed_Request(
int object_index)
static bool Able_To_Meet_Shed_Request(int object_index)
{
float level = 0.0;
float requested_level = 0.0;
@@ -428,30 +398,25 @@ static LOAD_CONTROL_STATE Load_Control_State[MAX_LOAD_CONTROLS];
static LOAD_CONTROL_STATE Load_Control_State_Previously[MAX_LOAD_CONTROLS];
#if PRINT_ENABLED_DEBUG
static void Print_Load_Control_State(
int object_index)
static void Print_Load_Control_State(int object_index)
{
char *Load_Control_State_Text[MAX_LOAD_CONTROLS] = {
"SHED_INACTIVE",
"SHED_REQUEST_PENDING",
"SHED_NON_COMPLIANT",
"SHED_COMPLIANT"
};
"SHED_INACTIVE", "SHED_REQUEST_PENDING", "SHED_NON_COMPLIANT",
"SHED_COMPLIANT"};
if (object_index < MAX_LOAD_CONTROLS) {
if (Load_Control_State[object_index] < MAX_LOAD_CONTROL_STATE) {
printf("Load Control[%d]=%s\n", object_index,
Load_Control_State_Text[Load_Control_State[object_index]]);
Load_Control_State_Text[Load_Control_State[object_index]]);
}
}
}
#endif
void Load_Control_State_Machine(
int object_index)
void Load_Control_State_Machine(int object_index)
{
unsigned i = 0; /* loop counter */
int diff = 0; /* used for datetime comparison */
unsigned i = 0; /* loop counter */
int diff = 0; /* used for datetime comparison */
/* is the state machine enabled? */
if (!Load_Control_Enable[object_index]) {
@@ -485,7 +450,7 @@ void Load_Control_State_Machine(
if (Load_Control_State[object_index] == SHED_INACTIVE) {
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Requested Shed Level=Default\n",
object_index);
object_index);
#endif
break;
}
@@ -498,7 +463,7 @@ void Load_Control_State_Machine(
Load_Control_State[object_index] = SHED_INACTIVE;
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Start Time=Wildcard\n",
object_index);
object_index);
#endif
break;
}
@@ -506,14 +471,16 @@ void Load_Control_State_Machine(
/* cancel because current time is after start time + duration? */
datetime_copy(&End_Time[object_index], &Start_Time[object_index]);
datetime_add_minutes(&End_Time[object_index],
Shed_Duration[object_index]);
Shed_Duration[object_index]);
diff = datetime_compare(&End_Time[object_index], &Current_Time);
if (diff < 0) {
/* CancelShed */
/* FIXME: stop shedding! i.e. relinquish */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Current Time"
" is after Start Time + Duration\n", object_index);
printf(
"Load Control[%d]:Current Time"
" is after Start Time + Duration\n",
object_index);
#endif
Load_Control_State[object_index] = SHED_INACTIVE;
break;
@@ -523,29 +490,34 @@ void Load_Control_State_Machine(
/* current time prior to start time */
/* ReconfigurePending */
Shed_Level_Copy(&Expected_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
&Requested_Shed_Level[object_index]);
Shed_Level_Default_Set(&Actual_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Requested_Shed_Level[object_index].type);
} else if (diff > 0) {
/* current time after to start time */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Current Time"
" is after Start Time\n", object_index);
printf(
"Load Control[%d]:Current Time"
" is after Start Time\n",
object_index);
#endif
/* AbleToMeetShed */
if (Able_To_Meet_Shed_Request(object_index)) {
Shed_Level_Copy(&Expected_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
Analog_Output_Present_Value_Set(object_index,
Requested_Shed_Level_Value(object_index), 4);
&Requested_Shed_Level[object_index]);
Analog_Output_Present_Value_Set(
object_index, Requested_Shed_Level_Value(object_index),
4);
Shed_Level_Copy(&Actual_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
&Requested_Shed_Level[object_index]);
Load_Control_State[object_index] = SHED_COMPLIANT;
} else {
/* CannotMeetShed */
Shed_Level_Default_Set(&Expected_Shed_Level[object_index],
Shed_Level_Default_Set(
&Expected_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Shed_Level_Default_Set(&Actual_Shed_Level[object_index],
Shed_Level_Default_Set(
&Actual_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Load_Control_State[object_index] = SHED_NON_COMPLIANT;
}
@@ -554,13 +526,14 @@ void Load_Control_State_Machine(
case SHED_NON_COMPLIANT:
datetime_copy(&End_Time[object_index], &Start_Time[object_index]);
datetime_add_minutes(&End_Time[object_index],
Shed_Duration[object_index]);
Shed_Duration[object_index]);
diff = datetime_compare(&End_Time[object_index], &Current_Time);
if (diff < 0) {
/* FinishedUnsuccessfulShed */
#if PRINT_ENABLED_DEBUG
printf
("Load Control[%d]:Current Time is after Start Time + Duration\n",
printf(
"Load Control[%d]:Current Time is after Start Time + "
"Duration\n",
object_index);
#endif
Load_Control_State[object_index] = SHED_INACTIVE;
@@ -571,7 +544,7 @@ void Load_Control_State_Machine(
/* UnsuccessfulShedReconfigured */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Control Property written\n",
object_index);
object_index);
#endif
/* The Written flags will cleared in the next state */
Load_Control_State[object_index] = SHED_REQUEST_PENDING;
@@ -581,27 +554,28 @@ void Load_Control_State_Machine(
/* CanNowComplyWithShed */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Able to meet Shed Request\n",
object_index);
object_index);
#endif
Shed_Level_Copy(&Expected_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
Analog_Output_Present_Value_Set(object_index,
Requested_Shed_Level_Value(object_index), 4);
&Requested_Shed_Level[object_index]);
Analog_Output_Present_Value_Set(
object_index, Requested_Shed_Level_Value(object_index), 4);
Shed_Level_Copy(&Actual_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
&Requested_Shed_Level[object_index]);
Load_Control_State[object_index] = SHED_COMPLIANT;
}
break;
case SHED_COMPLIANT:
datetime_copy(&End_Time[object_index], &Start_Time[object_index]);
datetime_add_minutes(&End_Time[object_index],
Shed_Duration[object_index]);
Shed_Duration[object_index]);
diff = datetime_compare(&End_Time[object_index], &Current_Time);
if (diff < 0) {
/* FinishedSuccessfulShed */
#if PRINT_ENABLED_DEBUG
printf
("Load Control[%d]:Current Time is after Start Time + Duration\n",
printf(
"Load Control[%d]:Current Time is after Start Time + "
"Duration\n",
object_index);
#endif
datetime_wildcard_set(&Start_Time[i]);
@@ -614,7 +588,7 @@ void Load_Control_State_Machine(
/* UnsuccessfulShedReconfigured */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Control Property written\n",
object_index);
object_index);
#endif
/* The Written flags will cleared in the next state */
Load_Control_State[object_index] = SHED_REQUEST_PENDING;
@@ -624,12 +598,12 @@ void Load_Control_State_Machine(
/* CanNoLongerComplyWithShed */
#if PRINT_ENABLED_DEBUG
printf("Load Control[%d]:Not able to meet Shed Request\n",
object_index);
object_index);
#endif
Shed_Level_Default_Set(&Expected_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Requested_Shed_Level[object_index].type);
Shed_Level_Default_Set(&Actual_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Requested_Shed_Level[object_index].type);
Load_Control_State[object_index] = SHED_NON_COMPLIANT;
}
break;
@@ -641,9 +615,9 @@ void Load_Control_State_Machine(
#endif
/* The Written flag will cleared in the next state */
Shed_Level_Copy(&Expected_Shed_Level[object_index],
&Requested_Shed_Level[object_index]);
&Requested_Shed_Level[object_index]);
Shed_Level_Default_Set(&Actual_Shed_Level[object_index],
Requested_Shed_Level[object_index].type);
Requested_Shed_Level[object_index].type);
Load_Control_State[object_index] = SHED_REQUEST_PENDING;
}
break;
@@ -653,8 +627,7 @@ void Load_Control_State_Machine(
}
/* call every second or so */
void Load_Control_State_Machine_Handler(
void)
void Load_Control_State_Machine_Handler(void)
{
unsigned i = 0;
static bool initialized = false;
@@ -675,17 +648,14 @@ void Load_Control_State_Machine_Handler(
#endif
Load_Control_State_Previously[i] = Load_Control_State[i];
}
}
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Load_Control_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Load_Control_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
int enumeration = 0;
@@ -702,9 +672,8 @@ int Load_Control_Read_Property(
object_index = Load_Control_Instance_To_Index(rpdata->object_instance);
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_LOAD_CONTROL,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_LOAD_CONTROL, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
@@ -744,68 +713,63 @@ int Load_Control_Read_Property(
case PROP_REQUESTED_SHED_LEVEL:
switch (Requested_Shed_Level[object_index].type) {
case BACNET_SHED_TYPE_PERCENT:
apdu_len =
encode_context_unsigned(&apdu[0], 0,
apdu_len = encode_context_unsigned(
&apdu[0], 0,
Requested_Shed_Level[object_index].value.percent);
break;
case BACNET_SHED_TYPE_AMOUNT:
apdu_len =
encode_context_real(&apdu[0], 2,
apdu_len = encode_context_real(
&apdu[0], 2,
Requested_Shed_Level[object_index].value.amount);
break;
case BACNET_SHED_TYPE_LEVEL:
default:
apdu_len =
encode_context_unsigned(&apdu[0], 1,
apdu_len = encode_context_unsigned(
&apdu[0], 1,
Requested_Shed_Level[object_index].value.level);
break;
}
break;
case PROP_START_TIME:
len =
encode_application_date(&apdu[0],
&Start_Time[object_index].date);
len = encode_application_date(&apdu[0],
&Start_Time[object_index].date);
apdu_len = len;
len =
encode_application_time(&apdu[apdu_len],
&Start_Time[object_index].time);
len = encode_application_time(&apdu[apdu_len],
&Start_Time[object_index].time);
apdu_len += len;
break;
case PROP_SHED_DURATION:
apdu_len =
encode_application_unsigned(&apdu[0],
Shed_Duration[object_index]);
apdu_len = encode_application_unsigned(&apdu[0],
Shed_Duration[object_index]);
break;
case PROP_DUTY_WINDOW:
apdu_len =
encode_application_unsigned(&apdu[0],
Duty_Window[object_index]);
apdu_len = encode_application_unsigned(&apdu[0],
Duty_Window[object_index]);
break;
case PROP_ENABLE:
state = Load_Control_Enable[object_index];
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_FULL_DUTY_BASELINE: /* optional */
apdu_len =
encode_application_real(&apdu[0],
Full_Duty_Baseline[object_index]);
case PROP_FULL_DUTY_BASELINE: /* optional */
apdu_len = encode_application_real(
&apdu[0], Full_Duty_Baseline[object_index]);
break;
case PROP_EXPECTED_SHED_LEVEL:
switch (Expected_Shed_Level[object_index].type) {
case BACNET_SHED_TYPE_PERCENT:
apdu_len =
encode_context_unsigned(&apdu[0], 0,
apdu_len = encode_context_unsigned(
&apdu[0], 0,
Expected_Shed_Level[object_index].value.percent);
break;
case BACNET_SHED_TYPE_AMOUNT:
apdu_len =
encode_context_real(&apdu[0], 2,
apdu_len = encode_context_real(
&apdu[0], 2,
Expected_Shed_Level[object_index].value.amount);
break;
case BACNET_SHED_TYPE_LEVEL:
default:
apdu_len =
encode_context_unsigned(&apdu[0], 1,
apdu_len = encode_context_unsigned(
&apdu[0], 1,
Expected_Shed_Level[object_index].value.level);
break;
}
@@ -813,19 +777,19 @@ int Load_Control_Read_Property(
case PROP_ACTUAL_SHED_LEVEL:
switch (Actual_Shed_Level[object_index].type) {
case BACNET_SHED_TYPE_PERCENT:
apdu_len =
encode_context_unsigned(&apdu[0], 0,
apdu_len = encode_context_unsigned(
&apdu[0], 0,
Actual_Shed_Level[object_index].value.percent);
break;
case BACNET_SHED_TYPE_AMOUNT:
apdu_len =
encode_context_real(&apdu[0], 2,
apdu_len = encode_context_real(
&apdu[0], 2,
Actual_Shed_Level[object_index].value.amount);
break;
case BACNET_SHED_TYPE_LEVEL:
default:
apdu_len =
encode_context_unsigned(&apdu[0], 1,
apdu_len = encode_context_unsigned(
&apdu[0], 1,
Actual_Shed_Level[object_index].value.level);
break;
}
@@ -841,9 +805,8 @@ int Load_Control_Read_Property(
apdu_len = 0;
for (i = 0; i < MAX_SHED_LEVELS; i++) {
/* FIXME: check if we have room before adding it to APDU */
len =
encode_application_unsigned(&apdu[apdu_len],
Shed_Levels[object_index][i]);
len = encode_application_unsigned(
&apdu[apdu_len], Shed_Levels[object_index][i]);
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
@@ -856,8 +819,8 @@ int Load_Control_Read_Property(
}
} else {
if (rpdata->array_index <= MAX_SHED_LEVELS) {
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
Shed_Levels[object_index][rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -878,10 +841,9 @@ int Load_Control_Read_Property(
for (i = 0; i < MAX_SHED_LEVELS; i++) {
/* FIXME: check if we have room before adding it to APDU */
characterstring_init_ansi(&char_string,
Shed_Level_Descriptions[i]);
len =
encode_application_character_string(&apdu[apdu_len],
&char_string);
Shed_Level_Descriptions[i]);
len = encode_application_character_string(&apdu[apdu_len],
&char_string);
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
apdu_len += len;
@@ -894,11 +856,11 @@ int Load_Control_Read_Property(
}
} else {
if (rpdata->array_index <= MAX_SHED_LEVELS) {
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
Shed_Level_Descriptions[rpdata->array_index - 1]);
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
apdu_len = encode_application_character_string(
&apdu[0], &char_string);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -926,19 +888,18 @@ int Load_Control_Read_Property(
}
/* returns true if successful */
bool Load_Control_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Load_Control_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
BACNET_DATE TempDate; /* build here in case of error in time half of datetime */
BACNET_DATE
TempDate; /* build here in case of error in time half of datetime */
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -956,10 +917,9 @@ bool Load_Control_Write_Property(
object_index = Load_Control_Instance_To_Index(wp_data->object_instance);
switch (wp_data->object_property) {
case PROP_REQUESTED_SHED_LEVEL:
len =
bacapp_decode_context_data(wp_data->application_data,
wp_data->application_data_len, &value,
PROP_REQUESTED_SHED_LEVEL);
len = bacapp_decode_context_data(wp_data->application_data,
wp_data->application_data_len,
&value, PROP_REQUESTED_SHED_LEVEL);
if (value.context_tag == 0) {
/* percent - Unsigned */
Requested_Shed_Level[object_index].type =
@@ -994,20 +954,20 @@ bool Load_Control_Write_Property(
case PROP_START_TIME:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_DATE,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (!status) {
/* don't continue if we don't have a valid date */
break;
}
/* Hold the date until we are sure the time is also there */
TempDate = value.type.Date;
len =
bacapp_decode_application_data(wp_data->application_data + len,
len = bacapp_decode_application_data(
wp_data->application_data + len,
wp_data->application_data_len - len, &value);
if (len) {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_TIME,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_TIME,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
/* Write time and date and set written flag */
Start_Time[object_index].date = TempDate;
@@ -1024,7 +984,7 @@ bool Load_Control_Write_Property(
case PROP_SHED_DURATION:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Shed_Duration[object_index] = value.type.Unsigned_Int;
Load_Control_Request_Written[object_index] = true;
@@ -1034,7 +994,7 @@ bool Load_Control_Write_Property(
case PROP_DUTY_WINDOW:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Duty_Window[object_index] = value.type.Unsigned_Int;
Load_Control_Request_Written[object_index] = true;
@@ -1044,7 +1004,7 @@ bool Load_Control_Write_Property(
case PROP_SHED_LEVELS:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
/* re-write the size of the array? */
if (wp_data->array_index == 0) {
@@ -1069,7 +1029,7 @@ bool Load_Control_Write_Property(
case PROP_ENABLE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Load_Control_Enable[object_index] = value.type.Boolean;
}
@@ -1117,10 +1077,9 @@ static void Load_Control_WriteProperty_Request_Shed_Percent(
}
#endif
static void Load_Control_WriteProperty_Request_Shed_Level(
Test * pTest,
int instance,
unsigned level)
static void Load_Control_WriteProperty_Request_Shed_Level(Test *pTest,
int instance,
unsigned level)
{
bool status = false;
BACNET_APPLICATION_DATA_VALUE value;
@@ -1169,10 +1128,8 @@ static void Load_Control_WriteProperty_Request_Shed_Amount(
}
#endif
static void Load_Control_WriteProperty_Enable(
Test * pTest,
int instance,
bool enable)
static void Load_Control_WriteProperty_Enable(Test *pTest, int instance,
bool enable)
{
bool status = false;
BACNET_APPLICATION_DATA_VALUE value;
@@ -1195,10 +1152,8 @@ static void Load_Control_WriteProperty_Enable(
ct_test(pTest, status == true);
}
static void Load_Control_WriteProperty_Shed_Duration(
Test * pTest,
int instance,
unsigned duration)
static void Load_Control_WriteProperty_Shed_Duration(Test *pTest, int instance,
unsigned duration)
{
bool status = false;
BACNET_APPLICATION_DATA_VALUE value;
@@ -1220,10 +1175,8 @@ static void Load_Control_WriteProperty_Shed_Duration(
ct_test(pTest, status == true);
}
static void Load_Control_WriteProperty_Duty_Window(
Test * pTest,
int instance,
unsigned duration)
static void Load_Control_WriteProperty_Duty_Window(Test *pTest, int instance,
unsigned duration)
{
bool status = false;
BACNET_APPLICATION_DATA_VALUE value;
@@ -1245,9 +1198,8 @@ static void Load_Control_WriteProperty_Duty_Window(
ct_test(pTest, status == true);
}
static void Load_Control_WriteProperty_Start_Time_Wildcards(
Test * pTest,
int instance)
static void Load_Control_WriteProperty_Start_Time_Wildcards(Test *pTest,
int instance)
{
int len = 0;
bool status = false;
@@ -1278,15 +1230,8 @@ static void Load_Control_WriteProperty_Start_Time_Wildcards(
}
static void Load_Control_WriteProperty_Start_Time(
Test * pTest,
int instance,
uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t minute,
uint8_t seconds,
uint8_t hundredths)
Test *pTest, int instance, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t seconds, uint8_t hundredths)
{
int len = 0;
bool status = false;
@@ -1316,8 +1261,7 @@ static void Load_Control_WriteProperty_Start_Time(
ct_test(pTest, status == true);
}
void testLoadControlStateMachine(
Test * pTest)
void testLoadControlStateMachine(Test *pTest)
{
unsigned i = 0, j = 0;
uint8_t level = 0;
@@ -1456,10 +1400,9 @@ void testLoadControlStateMachine(
ct_test(pTest, level == 100);
}
void testLoadControl(
Test * pTest)
void testLoadControl(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -1487,8 +1430,7 @@ void testLoadControl(
}
#ifdef TEST_LOAD_CONTROL
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -1502,7 +1444,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+168 -242
View File
@@ -1,31 +1,31 @@
/**
* @file
* @author Steve Karg
* @date 2013
* @brief Lighting Output object
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
* @file
* @author Steve Karg
* @date 2013
* @brief Lighting Output object
*
* @section LICENSE
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#include <stdbool.h>
#include <stdint.h>
@@ -34,7 +34,7 @@
#include "bacdcode.h"
#include "bacenum.h"
#include "bacapp.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "rp.h"
#include "wp.h"
#include "lighting.h"
@@ -53,9 +53,9 @@ struct lighting_output_object {
float Physical_Value;
BACNET_LIGHTING_COMMAND Lighting_Command;
BACNET_LIGHTING_IN_PROGRESS In_Progress;
bool Out_Of_Service:1;
bool Blink_Warn_Enable:1;
bool Egress_Active:1;
bool Out_Of_Service : 1;
bool Blink_Warn_Enable : 1;
bool Egress_Active : 1;
uint32_t Egress_Time;
uint32_t Default_Fade_Time;
float Default_Ramp_Rate;
@@ -94,15 +94,10 @@ static const int Lighting_Output_Properties_Required[] = {
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
PROP_LIGHTING_COMMAND_DEFAULT_PRIORITY,
-1
};
static const int Lighting_Output_Properties_Optional[] = {
-1
};
-1};
static const int Lighting_Output_Properties_Optional[] = {-1};
static const int Lighting_Output_Properties_Proprietary[] = {
-1
};
static const int Lighting_Output_Properties_Proprietary[] = {-1};
/**
* Returns the list of required, optional, and proprietary properties.
@@ -115,10 +110,9 @@ static const int Lighting_Output_Properties_Proprietary[] = {
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Lighting_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Lighting_Output_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Lighting_Output_Properties_Required;
@@ -137,8 +131,7 @@ void Lighting_Output_Property_Lists(
*
* @return true if the instance is valid, and false if not
*/
bool Lighting_Output_Valid_Instance(
uint32_t object_instance)
bool Lighting_Output_Valid_Instance(uint32_t object_instance)
{
unsigned int index;
@@ -155,8 +148,7 @@ bool Lighting_Output_Valid_Instance(
*
* @return Number of Lighting Output objects
*/
unsigned Lighting_Output_Count(
void)
unsigned Lighting_Output_Count(void)
{
return MAX_LIGHTING_OUTPUTS;
}
@@ -169,8 +161,7 @@ unsigned Lighting_Output_Count(
*
* @return object instance-number for the given index
*/
uint32_t Lighting_Output_Index_To_Instance(
unsigned index)
uint32_t Lighting_Output_Index_To_Instance(unsigned index)
{
uint32_t instance = 1;
@@ -188,8 +179,7 @@ uint32_t Lighting_Output_Index_To_Instance(
* @return index for the given instance-number, or MAX_LIGHTING_OUTPUTS
* if not valid.
*/
unsigned Lighting_Output_Instance_To_Index(
uint32_t object_instance)
unsigned Lighting_Output_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_LIGHTING_OUTPUTS;
@@ -210,8 +200,7 @@ unsigned Lighting_Output_Instance_To_Index(
*
* @return present-value of the object
*/
float Lighting_Output_Present_Value(
uint32_t object_instance)
float Lighting_Output_Present_Value(uint32_t object_instance)
{
float value = 0.0;
unsigned index = 0;
@@ -240,9 +229,8 @@ float Lighting_Output_Present_Value(
*
* @return priority-value of the object
*/
static float Lighting_Output_Priority_Value(
uint32_t object_instance,
unsigned priority)
static float Lighting_Output_Priority_Value(uint32_t object_instance,
unsigned priority)
{
float value = 0.0;
unsigned index = 0;
@@ -267,9 +255,8 @@ static float Lighting_Output_Priority_Value(
*
* @return true if the priority slot is active
*/
static bool Lighting_Output_Priority_Active(
uint32_t object_instance,
unsigned priority)
static bool Lighting_Output_Priority_Active(uint32_t object_instance,
unsigned priority)
{
bool status = false;
unsigned index = 0;
@@ -278,7 +265,8 @@ static bool Lighting_Output_Priority_Active(
if (index < MAX_LIGHTING_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
if (BIT_CHECK(Lighting_Output[index].Priority_Active_Bits, priority)) {
if (BIT_CHECK(Lighting_Output[index].Priority_Active_Bits,
priority)) {
status = true;
}
}
@@ -294,12 +282,11 @@ static bool Lighting_Output_Priority_Active(
*
* @return active priority 1..16, or 0 if no priority is active
*/
unsigned Lighting_Output_Present_Value_Priority(
uint32_t object_instance)
unsigned Lighting_Output_Present_Value_Priority(uint32_t object_instance)
{
unsigned index = 0; /* instance to index conversion */
unsigned p = 0; /* loop counter */
unsigned priority = 0; /* return value */
unsigned index = 0; /* instance to index conversion */
unsigned p = 0; /* loop counter */
unsigned priority = 0; /* return value */
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
@@ -324,10 +311,8 @@ unsigned Lighting_Output_Present_Value_Priority(
*
* @return true if values are within range and present-value is set.
*/
bool Lighting_Output_Present_Value_Set(
uint32_t object_instance,
float value,
unsigned priority)
bool Lighting_Output_Present_Value_Set(uint32_t object_instance, float value,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -335,7 +320,7 @@ bool Lighting_Output_Present_Value_Set(
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
(priority != 6 /* reserved */)) {
priority--;
BIT_SET(Lighting_Output[index].Priority_Active_Bits, priority);
Lighting_Output[index].Priority_Array[priority] = value;
@@ -355,9 +340,8 @@ bool Lighting_Output_Present_Value_Set(
*
* @return true if values are within range and present-value is set.
*/
bool Lighting_Output_Present_Value_Relinquish(
uint32_t object_instance,
unsigned priority)
bool Lighting_Output_Present_Value_Relinquish(uint32_t object_instance,
unsigned priority)
{
unsigned index = 0;
bool status = false;
@@ -365,7 +349,7 @@ bool Lighting_Output_Present_Value_Relinquish(
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ )) {
(priority != 6 /* reserved */)) {
priority--;
BIT_CLEAR(Lighting_Output[index].Priority_Active_Bits, priority);
Lighting_Output[index].Priority_Array[priority] = 0.0;
@@ -386,9 +370,8 @@ bool Lighting_Output_Present_Value_Relinquish(
*
* @return true if object-name was retrieved
*/
bool Lighting_Output_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Lighting_Output_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
char text_string[32] = "";
bool status = false;
@@ -397,7 +380,7 @@ bool Lighting_Output_Object_Name(
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
sprintf(text_string, "LIGHTING OUTPUT %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -412,9 +395,8 @@ bool Lighting_Output_Object_Name(
*
* @return true if lighting command was set
*/
bool Lighting_Output_Lighting_Command_Set(
uint32_t object_instance,
BACNET_LIGHTING_COMMAND *value)
bool Lighting_Output_Lighting_Command_Set(uint32_t object_instance,
BACNET_LIGHTING_COMMAND *value)
{
bool status = false;
unsigned index = 0;
@@ -422,9 +404,8 @@ bool Lighting_Output_Lighting_Command_Set(
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
// FIXME: check lighting command member values
status = lighting_command_copy(
&Lighting_Output[index].Lighting_Command,
value);
status = lighting_command_copy(&Lighting_Output[index].Lighting_Command,
value);
// FIXME: set all the other values, and get the light levels moving
}
@@ -439,17 +420,16 @@ bool Lighting_Output_Lighting_Command_Set(
*
* @return true if lighting command was retrieved
*/
bool Lighting_Output_Lighting_Command(
uint32_t object_instance,
BACNET_LIGHTING_COMMAND *value)
bool Lighting_Output_Lighting_Command(uint32_t object_instance,
BACNET_LIGHTING_COMMAND *value)
{
bool status = false;
unsigned index = 0;
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
status = lighting_command_copy(value,
&Lighting_Output[index].Lighting_Command);
status = lighting_command_copy(
value, &Lighting_Output[index].Lighting_Command);
}
return status;
@@ -485,9 +465,8 @@ BACNET_LIGHTING_IN_PROGRESS Lighting_Output_In_Progress(
*
* @return true if value was set
*/
bool Lighting_Output_In_Progress_Set(
uint32_t object_instance,
BACNET_LIGHTING_IN_PROGRESS in_progress)
bool Lighting_Output_In_Progress_Set(uint32_t object_instance,
BACNET_LIGHTING_IN_PROGRESS in_progress)
{
bool status = false;
unsigned index = 0;
@@ -495,7 +474,6 @@ bool Lighting_Output_In_Progress_Set(
index = Lighting_Output_Instance_To_Index(object_instance);
if (index < MAX_LIGHTING_OUTPUTS) {
Lighting_Output[index].In_Progress = in_progress;
}
return status;
@@ -508,8 +486,7 @@ bool Lighting_Output_In_Progress_Set(
*
* @return the tracking-value of this object instance.
*/
float Lighting_Output_Tracking_Value(
uint32_t object_instance)
float Lighting_Output_Tracking_Value(uint32_t object_instance)
{
float value = 0.0;
unsigned index = 0;
@@ -531,9 +508,7 @@ float Lighting_Output_Tracking_Value(
*
* @return true if value was set
*/
bool Lighting_Output_Tracking_Value_Set(
uint32_t object_instance,
float value)
bool Lighting_Output_Tracking_Value_Set(uint32_t object_instance, float value)
{
bool status = false;
unsigned int index = 0;
@@ -555,8 +530,7 @@ bool Lighting_Output_Tracking_Value_Set(
*
* @return the blink-warn-enable property value of this object
*/
bool Lighting_Output_Blink_Warn_Enable(
uint32_t object_instance)
bool Lighting_Output_Blink_Warn_Enable(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -578,9 +552,8 @@ bool Lighting_Output_Blink_Warn_Enable(
*
* @return true if value was set
*/
bool Lighting_Output_Blink_Warn_Enable_Set(
uint32_t object_instance,
bool enable)
bool Lighting_Output_Blink_Warn_Enable_Set(uint32_t object_instance,
bool enable)
{
bool status = false;
unsigned int index = 0;
@@ -602,8 +575,7 @@ bool Lighting_Output_Blink_Warn_Enable_Set(
*
* @return the egress-time property value of this object
*/
uint32_t Lighting_Output_Egress_Time(
uint32_t object_instance)
uint32_t Lighting_Output_Egress_Time(uint32_t object_instance)
{
uint32_t value = 0;
unsigned int index = 0;
@@ -625,9 +597,7 @@ uint32_t Lighting_Output_Egress_Time(
*
* @return true if value was set
*/
bool Lighting_Output_Egress_Time_Set(
uint32_t object_instance,
uint32_t seconds)
bool Lighting_Output_Egress_Time_Set(uint32_t object_instance, uint32_t seconds)
{
bool status = false;
unsigned int index = 0;
@@ -649,8 +619,7 @@ bool Lighting_Output_Egress_Time_Set(
*
* @return the egress-active property value of this object
*/
bool Lighting_Output_Egress_Active(
uint32_t object_instance)
bool Lighting_Output_Egress_Active(uint32_t object_instance)
{
bool value = false;
unsigned int index = 0;
@@ -671,8 +640,7 @@ bool Lighting_Output_Egress_Active(
*
* @return the fade-time property value of this object
*/
uint32_t Lighting_Output_Default_Fade_Time(
uint32_t object_instance)
uint32_t Lighting_Output_Default_Fade_Time(uint32_t object_instance)
{
uint32_t value = 0;
unsigned int index = 0;
@@ -694,16 +662,14 @@ uint32_t Lighting_Output_Default_Fade_Time(
*
* @return true if value was set
*/
bool Lighting_Output_Default_Fade_Time_Set(
uint32_t object_instance,
uint32_t milliseconds)
bool Lighting_Output_Default_Fade_Time_Set(uint32_t object_instance,
uint32_t milliseconds)
{
bool status = false;
unsigned int index = 0;
index = Lighting_Output_Instance_To_Index(object_instance);
if ((index < MAX_LIGHTING_OUTPUTS) &&
(milliseconds >= 100) &&
if ((index < MAX_LIGHTING_OUTPUTS) && (milliseconds >= 100) &&
(milliseconds <= 86400000)) {
Lighting_Output[index].Default_Fade_Time = milliseconds;
status = true;
@@ -720,8 +686,7 @@ bool Lighting_Output_Default_Fade_Time_Set(
*
* @return the ramp-rate property value of this object
*/
float Lighting_Output_Default_Ramp_Rate(
uint32_t object_instance)
float Lighting_Output_Default_Ramp_Rate(uint32_t object_instance)
{
float value = 0.0;
unsigned int index = 0;
@@ -743,16 +708,14 @@ float Lighting_Output_Default_Ramp_Rate(
*
* @return true if value was set
*/
bool Lighting_Output_Default_Ramp_Rate_Set(
uint32_t object_instance,
float percent_per_second)
bool Lighting_Output_Default_Ramp_Rate_Set(uint32_t object_instance,
float percent_per_second)
{
bool status = false;
unsigned int index = 0;
index = Lighting_Output_Instance_To_Index(object_instance);
if ((index < MAX_LIGHTING_OUTPUTS) &&
(percent_per_second >= 0.1) &&
if ((index < MAX_LIGHTING_OUTPUTS) && (percent_per_second >= 0.1) &&
(percent_per_second <= 100.0)) {
Lighting_Output[index].Default_Ramp_Rate = percent_per_second;
status = true;
@@ -769,8 +732,7 @@ bool Lighting_Output_Default_Ramp_Rate_Set(
*
* @return the default-step-increment property value of this object
*/
float Lighting_Output_Default_Step_Increment(
uint32_t object_instance)
float Lighting_Output_Default_Step_Increment(uint32_t object_instance)
{
float value = 0.0;
unsigned int index = 0;
@@ -792,16 +754,14 @@ float Lighting_Output_Default_Step_Increment(
*
* @return true if value was set
*/
bool Lighting_Output_Default_Step_Increment_Set(
uint32_t object_instance,
float step_increment)
bool Lighting_Output_Default_Step_Increment_Set(uint32_t object_instance,
float step_increment)
{
bool status = false;
unsigned int index = 0;
index = Lighting_Output_Instance_To_Index(object_instance);
if ((index < MAX_LIGHTING_OUTPUTS) &&
(step_increment >= 0.1) &&
if ((index < MAX_LIGHTING_OUTPUTS) && (step_increment >= 0.1) &&
(step_increment <= 100.0)) {
Lighting_Output[index].Default_Step_Increment = step_increment;
status = true;
@@ -820,8 +780,7 @@ bool Lighting_Output_Default_Step_Increment_Set(
* @return the lighting-command-default-priority property value of
* this object
*/
unsigned Lighting_Output_Default_Priority(
uint32_t object_instance)
unsigned Lighting_Output_Default_Priority(uint32_t object_instance)
{
unsigned value = 0;
unsigned int index = 0;
@@ -843,16 +802,14 @@ unsigned Lighting_Output_Default_Priority(
*
* @return true if value was set
*/
bool Lighting_Output_Default_Priority_Set(
uint32_t object_instance,
unsigned priority)
bool Lighting_Output_Default_Priority_Set(uint32_t object_instance,
unsigned priority)
{
bool status = false;
unsigned int index = 0;
index = Lighting_Output_Instance_To_Index(object_instance);
if ((index < MAX_LIGHTING_OUTPUTS) &&
(priority >= BACNET_MIN_PRIORITY) &&
if ((index < MAX_LIGHTING_OUTPUTS) && (priority >= BACNET_MIN_PRIORITY) &&
(priority <= BACNET_MAX_PRIORITY)) {
Lighting_Output[index].Lighting_Command_Default_Priority = priority;
status = true;
@@ -869,8 +826,7 @@ bool Lighting_Output_Default_Priority_Set(
*
* @return out-of-service property value
*/
bool Lighting_Output_Out_Of_Service(
uint32_t object_instance)
bool Lighting_Output_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned int index = 0;
@@ -891,9 +847,7 @@ bool Lighting_Output_Out_Of_Service(
*
* @return true if the out-of-service property value was set
*/
void Lighting_Output_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
void Lighting_Output_Out_Of_Service_Set(uint32_t object_instance, bool value)
{
unsigned int index = 0;
@@ -911,8 +865,7 @@ void Lighting_Output_Out_Of_Service_Set(
*
* @return relinquish-default property value
*/
float Lighting_Output_Relinquish_Default(
uint32_t object_instance)
float Lighting_Output_Relinquish_Default(uint32_t object_instance)
{
float value = 0.0;
unsigned int index = 0;
@@ -934,9 +887,8 @@ float Lighting_Output_Relinquish_Default(
*
* @return true if the relinquish-default property value was set
*/
bool Lighting_Output_Relinquish_Default_Set(
uint32_t object_instance,
float value)
bool Lighting_Output_Relinquish_Default_Set(uint32_t object_instance,
float value)
{
bool status = false;
unsigned int index = 0;
@@ -959,15 +911,14 @@ bool Lighting_Output_Relinquish_Default_Set(
* @return number of APDU bytes in the response, or
* BACNET_STATUS_ERROR on error.
*/
int Lighting_Output_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Lighting_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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_LIGHTING_COMMAND lighting_command;
float real_value = (float) 1.414;
float real_value = (float)1.414;
uint32_t unsigned_value = 0;
unsigned i = 0;
bool state = false;
@@ -980,9 +931,8 @@ int Lighting_Output_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_LIGHTING_OUTPUT,
rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_LIGHTING_OUTPUT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Lighting_Output_Object_Name(rpdata->object_instance, &char_string);
@@ -1003,17 +953,14 @@ int Lighting_Output_Read_Property(
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_LIGHTING_COMMAND:
Lighting_Output_Lighting_Command(
rpdata->object_instance,
&lighting_command);
apdu_len = lighting_command_encode(&apdu[0],
&lighting_command);
Lighting_Output_Lighting_Command(rpdata->object_instance,
&lighting_command);
apdu_len = lighting_command_encode(&apdu[0], &lighting_command);
break;
case PROP_IN_PROGRESS:
unsigned_value = Lighting_Output_In_Progress(
rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0],
unsigned_value);
unsigned_value =
Lighting_Output_In_Progress(rpdata->object_instance);
apdu_len = encode_application_enumerated(&apdu[0], unsigned_value);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -1033,20 +980,18 @@ int Lighting_Output_Read_Property(
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_EGRESS_TIME:
unsigned_value = Lighting_Output_Egress_Time(
rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0],
unsigned_value);
unsigned_value =
Lighting_Output_Egress_Time(rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0], unsigned_value);
break;
case PROP_EGRESS_ACTIVE:
state = Lighting_Output_Egress_Active(rpdata->object_instance);
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_DEFAULT_FADE_TIME:
unsigned_value = Lighting_Output_Default_Fade_Time(
rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0],
unsigned_value);
unsigned_value =
Lighting_Output_Default_Fade_Time(rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0], unsigned_value);
break;
case PROP_DEFAULT_RAMP_RATE:
real_value =
@@ -1063,17 +1008,17 @@ int Lighting_Output_Read_Property(
if (rpdata->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. */
/* if no index was specified, then try to encode the entire list
*/
/* into one packet. */
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
for (i = 1; i <= BACNET_MAX_PRIORITY; i++) {
if (Lighting_Output_Priority_Active(
rpdata->object_instance, i)) {
if (Lighting_Output_Priority_Active(rpdata->object_instance,
i)) {
real_value = Lighting_Output_Priority_Value(
rpdata->object_instance, i);
len =
encode_application_real(&apdu[apdu_len],
real_value);
len = encode_application_real(&apdu[apdu_len],
real_value);
} else {
len = encode_application_null(&apdu[apdu_len]);
}
@@ -1089,15 +1034,12 @@ int Lighting_Output_Read_Property(
}
} else {
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Lighting_Output_Priority_Active(
rpdata->object_instance,
rpdata->array_index)) {
if (Lighting_Output_Priority_Active(rpdata->object_instance,
rpdata->array_index)) {
real_value = Lighting_Output_Priority_Value(
rpdata->object_instance,
rpdata->array_index);
len =
encode_application_real(&apdu[apdu_len],
real_value);
rpdata->object_instance, rpdata->array_index);
len = encode_application_real(&apdu[apdu_len],
real_value);
} else {
len = encode_application_null(&apdu[apdu_len]);
}
@@ -1109,15 +1051,14 @@ int Lighting_Output_Read_Property(
}
break;
case PROP_RELINQUISH_DEFAULT:
real_value = Lighting_Output_Relinquish_Default(
rpdata->object_instance);
real_value =
Lighting_Output_Relinquish_Default(rpdata->object_instance);
apdu_len = encode_application_real(&apdu[0], real_value);
break;
case PROP_LIGHTING_COMMAND_DEFAULT_PRIORITY:
unsigned_value = Lighting_Output_Default_Priority(
rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0],
unsigned_value);
unsigned_value =
Lighting_Output_Default_Priority(rpdata->object_instance);
apdu_len = encode_application_unsigned(&apdu[0], unsigned_value);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -1145,17 +1086,15 @@ int Lighting_Output_Read_Property(
*
* @return false if an error is loaded, true if no errors
*/
bool Lighting_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -1176,9 +1115,9 @@ bool Lighting_Output_Write_Property(
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
status =
Lighting_Output_Present_Value_Set(wp_data->object_instance,
value.type.Real, wp_data->priority);
status = Lighting_Output_Present_Value_Set(
wp_data->object_instance, value.type.Real,
wp_data->priority);
if (wp_data->priority == 6) {
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
@@ -1190,14 +1129,15 @@ bool Lighting_Output_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
if (wp_data->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. - Note Lighting_Output_Present_Value_Relinquish()
/* Command priority 6 is reserved for use by Minimum
On/Off algorithm and may not be used for other
purposes in any object. - Note
Lighting_Output_Present_Value_Relinquish()
will have returned false because of this */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
@@ -1215,8 +1155,7 @@ bool Lighting_Output_Write_Property(
case PROP_LIGHTING_COMMAND:
if (value.tag == BACNET_APPLICATION_TAG_LIGHTING_COMMAND) {
status = Lighting_Output_Lighting_Command_Set(
wp_data->object_instance,
&value.type.Lighting_Command);
wp_data->object_instance, &value.type.Lighting_Command);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -1229,11 +1168,10 @@ bool Lighting_Output_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Lighting_Output_Out_Of_Service_Set(
wp_data->object_instance,
value.type.Boolean);
Lighting_Output_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -1270,13 +1208,11 @@ bool Lighting_Output_Write_Property(
* @param milliseconds - number of milliseconds elapsed since previously
* called. Works best when called about every 10 milliseconds.
*/
static void Lighting_Output_Ramp_Handler(
struct lighting_output_object *pLight,
BACNET_LIGHTING_COMMAND *pCommand,
uint16_t milliseconds)
static void Lighting_Output_Ramp_Handler(struct lighting_output_object *pLight,
BACNET_LIGHTING_COMMAND *pCommand,
uint16_t milliseconds)
{
if (pLight && pCommand) {
}
}
@@ -1288,13 +1224,11 @@ static void Lighting_Output_Ramp_Handler(
* @param milliseconds - number of milliseconds elapsed since previously
* called. Works best when called about every 10 milliseconds.
*/
static void Lighting_Output_Fade_Handler(
struct lighting_output_object *pLight,
BACNET_LIGHTING_COMMAND *pCommand,
uint16_t milliseconds)
static void Lighting_Output_Fade_Handler(struct lighting_output_object *pLight,
BACNET_LIGHTING_COMMAND *pCommand,
uint16_t milliseconds)
{
if (pLight && pCommand) {
}
}
@@ -1305,9 +1239,7 @@ static void Lighting_Output_Fade_Handler(
* @param milliseconds - number of milliseconds elapsed since previously
* called. Works best when called about every 10 milliseconds.
*/
static void Lighting_Output_Timer_Handler(
unsigned index,
uint16_t milliseconds)
static void Lighting_Output_Timer_Handler(unsigned index, uint16_t milliseconds)
{
struct lighting_output_object *pLight = NULL;
BACNET_LIGHTING_COMMAND *pCommand = NULL;
@@ -1352,8 +1284,7 @@ static void Lighting_Output_Timer_Handler(
* @param milliseconds - number of milliseconds elapsed since previously
* called. Works best when called about every 10 milliseconds.
*/
void Lighting_Output_Timer(
uint16_t milliseconds)
void Lighting_Output_Timer(uint16_t milliseconds)
{
unsigned i = 0;
@@ -1365,8 +1296,7 @@ void Lighting_Output_Timer(
/**
* Initializes the Lighting Output object data
*/
void Lighting_Output_Init(
void)
void Lighting_Output_Init(void)
{
unsigned i, p;
@@ -1410,11 +1340,9 @@ void Lighting_Output_Init(
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -1424,10 +1352,9 @@ bool WPValidateArgType(
return false;
}
void testLightingOutput(
Test * pTest)
void testLightingOutput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -1454,8 +1381,7 @@ void testLightingOutput(
}
#ifdef TEST_LIGHTING_OUTPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -1467,7 +1393,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+71 -105
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2005 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Life Safety Point Objects - customize for your use */
@@ -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 "rp.h"
#include "wp.h"
#include "lsp.h"
@@ -45,8 +45,7 @@
/* Here are our stored levels.*/
static BACNET_LIFE_SAFETY_MODE Life_Safety_Point_Mode[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_STATE
Life_Safety_Point_State[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_State[MAX_LIFE_SAFETY_POINTS];
static BACNET_SILENCED_STATE
Life_Safety_Point_Silenced_State[MAX_LIFE_SAFETY_POINTS];
static BACNET_LIFE_SAFETY_OPERATION
@@ -57,30 +56,18 @@ static bool Life_Safety_Point_Out_Of_Service[MAX_LIFE_SAFETY_POINTS];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Life_Safety_Point_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_TRACKING_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_RELIABILITY,
PROP_MODE,
PROP_ACCEPTED_MODES,
PROP_SILENCED,
PROP_OPERATION_EXPECTED,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_PRESENT_VALUE,
PROP_TRACKING_VALUE, PROP_STATUS_FLAGS,
PROP_EVENT_STATE, PROP_OUT_OF_SERVICE,
PROP_RELIABILITY, PROP_MODE,
PROP_ACCEPTED_MODES, PROP_SILENCED,
PROP_OPERATION_EXPECTED, -1};
static const int Life_Safety_Point_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Life_Safety_Point_Properties_Optional[] = {PROP_DESCRIPTION,
-1};
static const int Life_Safety_Point_Properties_Proprietary[] = {
-1
};
static const int Life_Safety_Point_Properties_Proprietary[] = {-1};
/**
* Returns the list of required, optional, and proprietary properties.
@@ -93,10 +80,9 @@ static const int Life_Safety_Point_Properties_Proprietary[] = {
* @param pProprietary - pointer to list of int terminated by -1, of
* BACnet proprietary properties for this object.
*/
void Life_Safety_Point_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Life_Safety_Point_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired) {
*pRequired = Life_Safety_Point_Properties_Required;
@@ -111,8 +97,7 @@ void Life_Safety_Point_Property_Lists(
return;
}
void Life_Safety_Point_Init(
void)
void Life_Safety_Point_Init(void)
{
static bool initialized = false;
unsigned i;
@@ -135,8 +120,7 @@ void Life_Safety_Point_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Life_Safety_Point_Valid_Instance(
uint32_t object_instance)
bool Life_Safety_Point_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_LIFE_SAFETY_POINTS)
return true;
@@ -146,8 +130,7 @@ bool Life_Safety_Point_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Life_Safety_Point_Count(
void)
unsigned Life_Safety_Point_Count(void)
{
return MAX_LIFE_SAFETY_POINTS;
}
@@ -155,8 +138,7 @@ unsigned Life_Safety_Point_Count(
/* 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 Life_Safety_Point_Index_To_Instance(
unsigned index)
uint32_t Life_Safety_Point_Index_To_Instance(unsigned index)
{
return index;
}
@@ -164,8 +146,7 @@ uint32_t Life_Safety_Point_Index_To_Instance(
/* 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 Life_Safety_Point_Instance_To_Index(
uint32_t object_instance)
unsigned Life_Safety_Point_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_LIFE_SAFETY_POINTS;
@@ -189,11 +170,10 @@ static BACNET_LIFE_SAFETY_STATE Life_Safety_Point_Present_Value(
}
/* note: the object name must be unique within this device */
bool Life_Safety_Point_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Life_Safety_Point_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_LIFE_SAFETY_POINTS) {
@@ -205,11 +185,10 @@ bool Life_Safety_Point_Object_Name(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Life_Safety_Point_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Life_Safety_Point_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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_LIFE_SAFETY_STATE present_value = LIFE_SAFETY_STATE_QUIET;
@@ -228,21 +207,19 @@ int Life_Safety_Point_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_LIFE_SAFETY_POINT, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_LIFE_SAFETY_POINT, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
Life_Safety_Point_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_LIFE_SAFETY_POINT);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_LIFE_SAFETY_POINT);
break;
case PROP_PRESENT_VALUE:
present_value =
@@ -286,7 +263,7 @@ int Life_Safety_Point_Read_Property(
break;
case PROP_ACCEPTED_MODES:
for (mode = MIN_LIFE_SAFETY_MODE; mode < MAX_LIFE_SAFETY_MODE;
mode++) {
mode++) {
len = encode_application_enumerated(&apdu[apdu_len], mode);
apdu_len += len;
}
@@ -320,18 +297,16 @@ int Life_Safety_Point_Read_Property(
}
/* returns true if successful */
bool Life_Safety_Point_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Life_Safety_Point_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -349,12 +324,11 @@ bool Life_Safety_Point_Write_Property(
case PROP_MODE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_ENUMERATED,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Enumerated <= MAX_LIFE_SAFETY_MODE) {
object_index =
Life_Safety_Point_Instance_To_Index
(wp_data->object_instance);
object_index = Life_Safety_Point_Instance_To_Index(
wp_data->object_instance);
Life_Safety_Point_Mode[object_index] =
value.type.Enumerated;
} else {
@@ -367,18 +341,15 @@ bool Life_Safety_Point_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
object_index =
Life_Safety_Point_Instance_To_Index
(wp_data->object_instance);
object_index = Life_Safety_Point_Instance_To_Index(
wp_data->object_instance);
Life_Safety_Point_Out_Of_Service[object_index] =
value.type.Boolean;
}
break;
case PROP_OBJECT_IDENTIFIER:
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
@@ -403,17 +374,14 @@ bool Life_Safety_Point_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -423,10 +391,9 @@ bool WPValidateArgType(
return false;
}
void testLifeSafetyPoint(
Test * pTest)
void testLifeSafetyPoint(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -453,8 +420,7 @@ void testLifeSafetyPoint(
}
#ifdef TEST_LIFE_SAFETY_POINT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -466,7 +432,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+139 -197
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2009 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Multi-state Input Objects */
@@ -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 "rp.h"
#include "wp.h"
#include "device.h"
@@ -59,31 +59,18 @@ static char State_Text[MAX_MULTISTATE_INPUTS][MULTISTATE_NUMBER_OF_STATES][64];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_NUMBER_OF_STATES,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_NUMBER_OF_STATES, -1};
static const int Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_STATE_TEXT,
-1
};
static const int Properties_Optional[] = {PROP_DESCRIPTION, PROP_STATE_TEXT,
-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Multistate_Input_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Multistate_Input_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -95,8 +82,7 @@ void Multistate_Input_Property_Lists(
return;
}
void Multistate_Input_Init(
void)
void Multistate_Input_Init(void)
{
unsigned i;
@@ -113,8 +99,7 @@ void Multistate_Input_Init(
/* 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 Multistate_Input_Instance_To_Index(
uint32_t object_instance)
unsigned Multistate_Input_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_MULTISTATE_INPUTS;
@@ -127,22 +112,19 @@ unsigned Multistate_Input_Instance_To_Index(
/* 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 Multistate_Input_Index_To_Instance(
unsigned index)
uint32_t Multistate_Input_Index_To_Instance(unsigned index)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Multistate_Input_Count(
void)
unsigned Multistate_Input_Count(void)
{
return MAX_MULTISTATE_INPUTS;
}
bool Multistate_Input_Valid_Instance(
uint32_t object_instance)
bool Multistate_Input_Valid_Instance(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
@@ -154,14 +136,12 @@ bool Multistate_Input_Valid_Instance(
return false;
}
static uint32_t Multistate_Input_Max_States(
uint32_t instance)
static uint32_t Multistate_Input_Max_States(uint32_t instance)
{
return MULTISTATE_NUMBER_OF_STATES;
}
uint32_t Multistate_Input_Present_Value(
uint32_t object_instance)
uint32_t Multistate_Input_Present_Value(uint32_t object_instance)
{
uint32_t value = 1;
unsigned index = 0; /* offset from instance lookup */
@@ -174,9 +154,8 @@ uint32_t Multistate_Input_Present_Value(
return value;
}
bool Multistate_Input_Present_Value_Set(
uint32_t object_instance,
uint32_t value)
bool Multistate_Input_Present_Value_Set(uint32_t object_instance,
uint32_t value)
{
bool status = false;
unsigned index = 0; /* offset from instance lookup */
@@ -184,7 +163,7 @@ bool Multistate_Input_Present_Value_Set(
index = Multistate_Input_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_INPUTS) {
if ((value > 0) && (value <= MULTISTATE_NUMBER_OF_STATES)) {
Present_Value[index] = (uint8_t) value;
Present_Value[index] = (uint8_t)value;
status = true;
}
}
@@ -192,8 +171,7 @@ bool Multistate_Input_Present_Value_Set(
return status;
}
bool Multistate_Input_Out_Of_Service(
uint32_t object_instance)
bool Multistate_Input_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -206,9 +184,7 @@ bool Multistate_Input_Out_Of_Service(
return value;
}
void Multistate_Input_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
void Multistate_Input_Out_Of_Service_Set(uint32_t object_instance, bool value)
{
unsigned index = 0;
@@ -220,8 +196,7 @@ void Multistate_Input_Out_Of_Service_Set(
return;
}
char *Multistate_Input_Description(
uint32_t object_instance)
char *Multistate_Input_Description(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
char *pName = NULL; /* return value */
@@ -234,13 +209,11 @@ char *Multistate_Input_Description(
return pName;
}
bool Multistate_Input_Description_Set(
uint32_t object_instance,
char *new_name)
bool Multistate_Input_Description_Set(uint32_t object_instance, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_INPUTS) {
@@ -263,15 +236,13 @@ bool Multistate_Input_Description_Set(
}
static bool Multistate_Input_Description_Write(
uint32_t object_instance,
BACNET_CHARACTER_STRING * char_string,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
uint32_t object_instance, BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CODE *error_code)
{
unsigned index = 0; /* offset from instance lookup */
size_t length = 0;
uint8_t encoding = 0;
bool status = false; /* return value */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_INPUTS) {
@@ -279,8 +250,8 @@ static bool Multistate_Input_Description_Write(
if (length <= sizeof(Object_Description[index])) {
encoding = characterstring_encoding(char_string);
if (encoding == CHARACTER_UTF8) {
status =
characterstring_ansi_copy(Object_Description[index],
status = characterstring_ansi_copy(
Object_Description[index],
sizeof(Object_Description[index]), char_string);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
@@ -299,10 +270,8 @@ static bool Multistate_Input_Description_Write(
return status;
}
bool Multistate_Input_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Multistate_Input_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
unsigned index = 0; /* offset from instance lookup */
bool status = false;
@@ -316,13 +285,11 @@ bool Multistate_Input_Object_Name(
}
/* note: the object name must be unique within this device */
bool Multistate_Input_Name_Set(
uint32_t object_instance,
char *new_name)
bool Multistate_Input_Name_Set(uint32_t object_instance, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_INPUTS) {
@@ -346,15 +313,13 @@ bool Multistate_Input_Name_Set(
}
static bool Multistate_Input_Object_Name_Write(
uint32_t object_instance,
BACNET_CHARACTER_STRING * char_string,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
uint32_t object_instance, BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class, BACNET_ERROR_CODE *error_code)
{
unsigned index = 0; /* offset from instance lookup */
size_t length = 0;
uint8_t encoding = 0;
bool status = false; /* return value */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_INPUTS) {
@@ -362,9 +327,9 @@ static bool Multistate_Input_Object_Name_Write(
if (length <= sizeof(Object_Name[index])) {
encoding = characterstring_encoding(char_string);
if (encoding == CHARACTER_UTF8) {
status =
characterstring_ansi_copy(Object_Name[index],
sizeof(Object_Name[index]), char_string);
status = characterstring_ansi_copy(Object_Name[index],
sizeof(Object_Name[index]),
char_string);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -382,9 +347,8 @@ static bool Multistate_Input_Object_Name_Write(
return status;
}
char *Multistate_Input_State_Text(
uint32_t object_instance,
uint32_t state_index)
char *Multistate_Input_State_Text(uint32_t object_instance,
uint32_t state_index)
{
unsigned index = 0; /* offset from instance lookup */
char *pName = NULL; /* return value */
@@ -400,14 +364,12 @@ char *Multistate_Input_State_Text(
}
/* note: the object name must be unique within this device */
bool Multistate_Input_State_Text_Set(
uint32_t object_instance,
uint32_t state_index,
char *new_name)
bool Multistate_Input_State_Text_Set(uint32_t object_instance,
uint32_t state_index, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if ((index < MAX_MULTISTATE_INPUTS) && (state_index > 0) &&
@@ -428,20 +390,19 @@ bool Multistate_Input_State_Text_Set(
}
}
return status;;
return status;
;
}
static bool Multistate_Input_State_Text_Write(
uint32_t object_instance,
uint32_t state_index,
BACNET_CHARACTER_STRING * char_string,
BACNET_ERROR_CLASS * error_class,
BACNET_ERROR_CODE * error_code)
uint32_t object_instance, uint32_t state_index,
BACNET_CHARACTER_STRING *char_string, BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
unsigned index = 0; /* offset from instance lookup */
size_t length = 0;
uint8_t encoding = 0;
bool status = false; /* return value */
bool status = false; /* return value */
index = Multistate_Input_Instance_To_Index(object_instance);
if ((index < MAX_MULTISTATE_INPUTS) && (state_index > 0) &&
@@ -451,8 +412,8 @@ static bool Multistate_Input_State_Text_Write(
if (length <= sizeof(State_Text[index][state_index])) {
encoding = characterstring_encoding(char_string);
if (encoding == CHARACTER_UTF8) {
status =
characterstring_ansi_copy(State_Text[index][state_index],
status = characterstring_ansi_copy(
State_Text[index][state_index],
sizeof(State_Text[index][state_index]), char_string);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
@@ -475,11 +436,10 @@ static bool Multistate_Input_State_Text_Write(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Multistate_Input_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Multistate_Input_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
uint32_t present_value = 0;
@@ -495,28 +455,26 @@ int Multistate_Input_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_INPUT, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_MULTI_STATE_INPUT, rpdata->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:
Multistate_Input_Object_Name(rpdata->object_instance,
&char_string);
Multistate_Input_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
Multistate_Input_Description(rpdata->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_MULTI_STATE_INPUT);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_MULTI_STATE_INPUT);
break;
case PROP_PRESENT_VALUE:
present_value =
@@ -531,10 +489,10 @@ int Multistate_Input_Read_Property(
bitstring_set_bit(&bit_string, STATUS_FLAG_OVERRIDDEN, false);
if (Multistate_Input_Out_Of_Service(rpdata->object_instance)) {
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
true);
true);
} else {
bitstring_set_bit(&bit_string, STATUS_FLAG_OUT_OF_SERVICE,
false);
false);
}
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -548,29 +506,29 @@ int Multistate_Input_Read_Property(
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_NUMBER_OF_STATES:
apdu_len =
encode_application_unsigned(&apdu[apdu_len],
apdu_len = encode_application_unsigned(
&apdu[apdu_len],
Multistate_Input_Max_States(rpdata->object_instance));
break;
case PROP_STATE_TEXT:
if (rpdata->array_index == 0) {
/* Array element zero is the number of elements in the array */
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
Multistate_Input_Max_States(rpdata->object_instance));
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
/* if no index was specified, then try to encode the entire list */
/* if no index was specified, then try to encode the entire list
*/
/* into one packet. */
max_states =
Multistate_Input_Max_States(rpdata->object_instance);
for (i = 1; i <= max_states; i++) {
characterstring_init_ansi(&char_string,
Multistate_Input_State_Text(rpdata->object_instance,
i));
Multistate_Input_State_Text(
rpdata->object_instance, i));
/* FIXME: this might go beyond MAX_APDU length! */
len =
encode_application_character_string(&apdu[apdu_len],
&char_string);
len = encode_application_character_string(&apdu[apdu_len],
&char_string);
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU) {
apdu_len += len;
@@ -585,12 +543,12 @@ int Multistate_Input_Read_Property(
max_states =
Multistate_Input_Max_States(rpdata->object_instance);
if (rpdata->array_index <= max_states) {
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
Multistate_Input_State_Text(rpdata->object_instance,
rpdata->array_index));
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
rpdata->array_index));
apdu_len = encode_application_character_string(
&apdu[0], &char_string);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -616,10 +574,9 @@ int Multistate_Input_Read_Property(
}
/* returns true if successful */
bool Multistate_Input_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Multistate_Input_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
int element_len = 0;
BACNET_APPLICATION_DATA_VALUE value;
@@ -629,9 +586,8 @@ bool Multistate_Input_Write_Property(
uint32_t object_instance = 0;
/* decode the first chunk of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* len < application_data_len: extra data for arrays only */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -651,7 +607,7 @@ bool Multistate_Input_Write_Property(
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
/* All the object names in a device must be unique */
if (Device_Valid_Object_Name(&value.type.Character_String,
&object_type, &object_instance)) {
&object_type, &object_instance)) {
if ((object_type == wp_data->object_type) &&
(object_instance == wp_data->object_instance)) {
/* writing same name to same object */
@@ -662,9 +618,8 @@ bool Multistate_Input_Write_Property(
wp_data->error_code = ERROR_CODE_DUPLICATE_NAME;
}
} else {
status =
Multistate_Input_Object_Name_Write(wp_data->
object_instance, &value.type.Character_String,
status = Multistate_Input_Object_Name_Write(
wp_data->object_instance, &value.type.Character_String,
&wp_data->error_class, &wp_data->error_code);
}
} else {
@@ -674,9 +629,8 @@ bool Multistate_Input_Write_Property(
break;
case PROP_DESCRIPTION:
if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) {
status =
Multistate_Input_Description_Write(wp_data->
object_instance, &value.type.Character_String,
status = Multistate_Input_Description_Write(
wp_data->object_instance, &value.type.Character_String,
&wp_data->error_class, &wp_data->error_code);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -686,11 +640,10 @@ bool Multistate_Input_Write_Property(
case PROP_PRESENT_VALUE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
status =
Multistate_Input_Present_Value_Set
(wp_data->object_instance, value.type.Unsigned_Int);
status = Multistate_Input_Present_Value_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -700,10 +653,10 @@ bool Multistate_Input_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Multistate_Input_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_STATE_TEXT:
@@ -721,18 +674,16 @@ bool Multistate_Input_Write_Property(
element_len = len;
do {
if (element_len) {
status =
Multistate_Input_State_Text_Write(wp_data->
object_instance, array_index,
status = Multistate_Input_State_Text_Write(
wp_data->object_instance, array_index,
&value.type.Character_String,
&wp_data->error_class, &wp_data->error_code);
}
max_states--;
array_index++;
if (max_states) {
element_len =
bacapp_decode_application_data(&wp_data->
application_data[len],
element_len = bacapp_decode_application_data(
&wp_data->application_data[len],
wp_data->application_data_len - len, &value);
if (element_len < 0) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -747,11 +698,10 @@ bool Multistate_Input_Write_Property(
max_states =
Multistate_Input_Max_States(wp_data->object_instance);
if (wp_data->array_index <= max_states) {
status =
Multistate_Input_State_Text_Write(wp_data->
object_instance, wp_data->array_index,
&value.type.Character_String,
&wp_data->error_class, &wp_data->error_code);
status = Multistate_Input_State_Text_Write(
wp_data->object_instance, wp_data->array_index,
&value.type.Character_String, &wp_data->error_class,
&wp_data->error_code);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
@@ -779,26 +729,20 @@ bool Multistate_Input_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool Device_Valid_Object_Name(
BACNET_CHARACTER_STRING * object_name,
int *object_type,
uint32_t * object_instance)
bool Device_Valid_Object_Name(BACNET_CHARACTER_STRING *object_name,
int *object_type, uint32_t *object_instance)
{
return true;
}
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -808,10 +752,9 @@ bool WPValidateArgType(
return false;
}
void testMultistateInput(
Test * pTest)
void testMultistateInput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -838,8 +781,7 @@ void testMultistateInput(
}
#ifdef TEST_MULTISTATE_INPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -851,7 +793,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+98 -127
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Multi-state Output Objects - customize for your use */
@@ -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 "rp.h"
#include "wp.h"
#include "mso.h"
@@ -51,8 +51,8 @@
/* how many states? 1 to 254 states, 0 is not allowed */
#define MULTISTATE_NUMBER_OF_STATES (254)
/* Here is our Priority Array.*/
static uint8_t
Multistate_Output_Level[MAX_MULTISTATE_OUTPUTS][BACNET_MAX_PRIORITY];
static uint8_t Multistate_Output_Level[MAX_MULTISTATE_OUTPUTS]
[BACNET_MAX_PRIORITY];
/* Writable out-of-service allows others to play with our Present Value */
/* without changing the physical output */
static bool Out_Of_Service[MAX_MULTISTATE_OUTPUTS];
@@ -69,22 +69,16 @@ static const int Multistate_Output_Properties_Required[] = {
PROP_NUMBER_OF_STATES,
PROP_PRIORITY_ARRAY,
PROP_RELINQUISH_DEFAULT,
-1
};
-1};
static const int Multistate_Output_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Multistate_Output_Properties_Optional[] = {PROP_DESCRIPTION,
-1};
static const int Multistate_Output_Properties_Proprietary[] = {
-1
};
static const int Multistate_Output_Properties_Proprietary[] = {-1};
void Multistate_Output_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Multistate_Output_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Multistate_Output_Properties_Required;
@@ -96,8 +90,7 @@ void Multistate_Output_Property_Lists(
return;
}
void Multistate_Output_Init(
void)
void Multistate_Output_Init(void)
{
unsigned i, j;
static bool initialized = false;
@@ -119,8 +112,7 @@ void Multistate_Output_Init(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Multistate_Output_Valid_Instance(
uint32_t object_instance)
bool Multistate_Output_Valid_Instance(uint32_t object_instance)
{
if (object_instance < MAX_MULTISTATE_OUTPUTS)
return true;
@@ -130,8 +122,7 @@ bool Multistate_Output_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Multistate_Output_Count(
void)
unsigned Multistate_Output_Count(void)
{
return MAX_MULTISTATE_OUTPUTS;
}
@@ -139,8 +130,7 @@ unsigned Multistate_Output_Count(
/* 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 Multistate_Output_Index_To_Instance(
unsigned index)
uint32_t Multistate_Output_Index_To_Instance(unsigned index)
{
return index;
}
@@ -148,8 +138,7 @@ uint32_t Multistate_Output_Index_To_Instance(
/* 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 Multistate_Output_Instance_To_Index(
uint32_t object_instance)
unsigned Multistate_Output_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_MULTISTATE_OUTPUTS;
@@ -159,8 +148,7 @@ unsigned Multistate_Output_Instance_To_Index(
return index;
}
uint32_t Multistate_Output_Present_Value(
uint32_t object_instance)
uint32_t Multistate_Output_Present_Value(uint32_t object_instance)
{
uint32_t value = MULTISTATE_RELINQUISH_DEFAULT;
unsigned index = 0;
@@ -180,11 +168,10 @@ uint32_t Multistate_Output_Present_Value(
}
/* note: the object name must be unique within this device */
bool Multistate_Output_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Multistate_Output_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_MULTISTATE_OUTPUTS) {
@@ -195,8 +182,7 @@ bool Multistate_Output_Object_Name(
return status;
}
bool Multistate_Output_Out_Of_Service(
uint32_t instance)
bool Multistate_Output_Out_Of_Service(uint32_t instance)
{
unsigned index = 0;
bool oos_flag = false;
@@ -209,9 +195,7 @@ bool Multistate_Output_Out_Of_Service(
return oos_flag;
}
void Multistate_Output_Out_Of_Service_Set(
uint32_t instance,
bool oos_flag)
void Multistate_Output_Out_Of_Service_Set(uint32_t instance, bool oos_flag)
{
unsigned index = 0;
@@ -222,11 +206,10 @@ void Multistate_Output_Out_Of_Service_Set(
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Multistate_Output_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Multistate_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
uint32_t present_value = 0;
@@ -242,23 +225,21 @@ int Multistate_Output_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_OUTPUT, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_MULTI_STATE_OUTPUT, rpdata->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:
Multistate_Output_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_MULTI_STATE_OUTPUT);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_MULTI_STATE_OUTPUT);
break;
case PROP_PRESENT_VALUE:
present_value =
@@ -292,9 +273,8 @@ int Multistate_Output_Read_Property(
/* if no index was specified, then try to encode the entire list */
/* into one packet. */
else if (rpdata->array_index == BACNET_ARRAY_ALL) {
object_index =
Multistate_Output_Instance_To_Index
(rpdata->object_instance);
object_index = Multistate_Output_Instance_To_Index(
rpdata->object_instance);
for (i = 0; i < BACNET_MAX_PRIORITY; i++) {
/* FIXME: check if we have room before adding it to APDU */
if (Multistate_Output_Level[object_index][i] ==
@@ -303,9 +283,8 @@ int Multistate_Output_Read_Property(
else {
present_value =
Multistate_Output_Level[object_index][i];
len =
encode_application_unsigned(&apdu[apdu_len],
present_value);
len = encode_application_unsigned(&apdu[apdu_len],
present_value);
}
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU)
@@ -318,19 +297,19 @@ int Multistate_Output_Read_Property(
}
}
} else {
object_index =
Multistate_Output_Instance_To_Index
(rpdata->object_instance);
object_index = Multistate_Output_Instance_To_Index(
rpdata->object_instance);
if (rpdata->array_index <= BACNET_MAX_PRIORITY) {
if (Multistate_Output_Level[object_index]
[rpdata->array_index - 1] == MULTISTATE_NULL)
[rpdata->array_index - 1] ==
MULTISTATE_NULL)
apdu_len = encode_application_null(&apdu[0]);
else {
present_value = Multistate_Output_Level[object_index]
[rpdata->array_index - 1];
apdu_len =
encode_application_unsigned(&apdu[0],
present_value);
present_value =
Multistate_Output_Level[object_index]
[rpdata->array_index - 1];
apdu_len = encode_application_unsigned(&apdu[0],
present_value);
}
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -345,9 +324,8 @@ int Multistate_Output_Read_Property(
apdu_len = encode_application_unsigned(&apdu[0], present_value);
break;
case PROP_NUMBER_OF_STATES:
apdu_len =
encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
apdu_len = encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
break;
default:
@@ -369,10 +347,9 @@ int Multistate_Output_Read_Property(
}
/* returns true if successful */
bool Multistate_Output_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Multistate_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
unsigned int priority = 0;
uint32_t level = 0;
@@ -380,9 +357,8 @@ bool Multistate_Output_Write_Property(
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -406,21 +382,21 @@ bool Multistate_Output_Write_Property(
algorithm and may not be used for other purposes in any
object. */
if (priority && (priority <= BACNET_MAX_PRIORITY) &&
(priority != 6 /* reserved */ ) &&
(priority != 6 /* reserved */) &&
(value.type.Unsigned_Int > 0) &&
(value.type.Unsigned_Int <= MULTISTATE_NUMBER_OF_STATES)) {
level = value.type.Unsigned_Int;
object_index =
Multistate_Output_Instance_To_Index
(wp_data->object_instance);
object_index = Multistate_Output_Instance_To_Index(
wp_data->object_instance);
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) level;
(uint8_t)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) */
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
@@ -433,25 +409,25 @@ bool Multistate_Output_Write_Property(
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class, &wp_data->error_code);
status = WPValidateArgType(&value, BACNET_APPLICATION_TAG_NULL,
&wp_data->error_class,
&wp_data->error_code);
if (status) {
level = MULTISTATE_NULL;
object_index =
Multistate_Output_Instance_To_Index
(wp_data->object_instance);
object_index = Multistate_Output_Instance_To_Index(
wp_data->object_instance);
priority = wp_data->priority;
if (priority && (priority <= BACNET_MAX_PRIORITY)) {
priority--;
Multistate_Output_Level[object_index][priority] =
(uint8_t) 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) */
(uint8_t)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) */
} else {
status = false;
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -463,10 +439,10 @@ bool Multistate_Output_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Multistate_Output_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -490,17 +466,14 @@ bool Multistate_Output_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -510,10 +483,9 @@ bool WPValidateArgType(
return false;
}
void testMultistateOutput(
Test * pTest)
void testMultistateOutput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -540,8 +512,7 @@ void testMultistateOutput(
}
#ifdef TEST_MULTISTATE_OUTPUT
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -553,7 +524,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+114 -163
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Multi-state Value Objects */
@@ -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 "rp.h"
#include "wp.h"
#include "msv.h"
@@ -63,31 +63,18 @@ static char State_Text[MAX_MULTISTATE_VALUES][MULTISTATE_NUMBER_OF_STATES][64];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_NUMBER_OF_STATES,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE, PROP_NUMBER_OF_STATES, -1};
static const int Properties_Optional[] = {
PROP_DESCRIPTION,
PROP_STATE_TEXT,
-1
};
static const int Properties_Optional[] = {PROP_DESCRIPTION, PROP_STATE_TEXT,
-1};
static const int Properties_Proprietary[] = {
-1
};
static const int Properties_Proprietary[] = {-1};
void Multistate_Value_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Multistate_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Properties_Required;
@@ -99,8 +86,7 @@ void Multistate_Value_Property_Lists(
return;
}
void Multistate_Value_Init(
void)
void Multistate_Value_Init(void)
{
unsigned int i;
@@ -117,8 +103,7 @@ void Multistate_Value_Init(
/* 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 Multistate_Value_Instance_To_Index(
uint32_t object_instance)
unsigned Multistate_Value_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_MULTISTATE_VALUES;
@@ -131,22 +116,19 @@ unsigned Multistate_Value_Instance_To_Index(
/* 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 Multistate_Value_Index_To_Instance(
unsigned index)
uint32_t Multistate_Value_Index_To_Instance(unsigned index)
{
return index;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Multistate_Value_Count(
void)
unsigned Multistate_Value_Count(void)
{
return MAX_MULTISTATE_VALUES;
}
bool Multistate_Value_Valid_Instance(
uint32_t object_instance)
bool Multistate_Value_Valid_Instance(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
@@ -158,8 +140,7 @@ bool Multistate_Value_Valid_Instance(
return false;
}
uint32_t Multistate_Value_Present_Value(
uint32_t object_instance)
uint32_t Multistate_Value_Present_Value(uint32_t object_instance)
{
uint32_t value = 1;
unsigned index = 0; /* offset from instance lookup */
@@ -172,9 +153,8 @@ uint32_t Multistate_Value_Present_Value(
return value;
}
bool Multistate_Value_Present_Value_Set(
uint32_t object_instance,
uint32_t value)
bool Multistate_Value_Present_Value_Set(uint32_t object_instance,
uint32_t value)
{
bool status = false;
unsigned index = 0; /* offset from instance lookup */
@@ -185,7 +165,7 @@ bool Multistate_Value_Present_Value_Set(
if (Present_Value[index] != (uint8_t)value) {
Change_Of_Value[index] = true;
}
Present_Value[index] = (uint8_t) value;
Present_Value[index] = (uint8_t)value;
status = true;
}
}
@@ -193,8 +173,7 @@ bool Multistate_Value_Present_Value_Set(
return status;
}
bool Multistate_Value_Out_Of_Service(
uint32_t object_instance)
bool Multistate_Value_Out_Of_Service(uint32_t object_instance)
{
bool value = false;
unsigned index = 0;
@@ -207,9 +186,7 @@ bool Multistate_Value_Out_Of_Service(
return value;
}
void Multistate_Value_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
void Multistate_Value_Out_Of_Service_Set(uint32_t object_instance, bool value)
{
unsigned index = 0;
@@ -224,8 +201,7 @@ void Multistate_Value_Out_Of_Service_Set(
return;
}
char *Multistate_Value_Description(
uint32_t object_instance)
char *Multistate_Value_Description(uint32_t object_instance)
{
unsigned index = 0; /* offset from instance lookup */
char *pName = NULL; /* return value */
@@ -238,13 +214,11 @@ char *Multistate_Value_Description(
return pName;
}
bool Multistate_Value_Description_Set(
uint32_t object_instance,
char *new_name)
bool Multistate_Value_Description_Set(uint32_t object_instance, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Value_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_VALUES) {
@@ -266,9 +240,8 @@ bool Multistate_Value_Description_Set(
return status;
}
bool Multistate_Value_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Multistate_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
unsigned index = 0; /* offset from instance lookup */
bool status = false;
@@ -282,13 +255,11 @@ bool Multistate_Value_Object_Name(
}
/* note: the object name must be unique within this device */
bool Multistate_Value_Name_Set(
uint32_t object_instance,
char *new_name)
bool Multistate_Value_Name_Set(uint32_t object_instance, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Value_Instance_To_Index(object_instance);
if (index < MAX_MULTISTATE_VALUES) {
@@ -311,9 +282,8 @@ bool Multistate_Value_Name_Set(
return status;
}
char *Multistate_Value_State_Text(
uint32_t object_instance,
uint32_t state_index)
char *Multistate_Value_State_Text(uint32_t object_instance,
uint32_t state_index)
{
unsigned index = 0; /* offset from instance lookup */
char *pName = NULL; /* return value */
@@ -329,14 +299,12 @@ char *Multistate_Value_State_Text(
}
/* note: the object name must be unique within this device */
bool Multistate_Value_State_Text_Set(
uint32_t object_instance,
uint32_t state_index,
char *new_name)
bool Multistate_Value_State_Text_Set(uint32_t object_instance,
uint32_t state_index, char *new_name)
{
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
unsigned index = 0; /* offset from instance lookup */
size_t i = 0; /* loop counter */
bool status = false; /* return value */
index = Multistate_Value_Instance_To_Index(object_instance);
if ((index < MAX_MULTISTATE_VALUES) && (state_index > 0) &&
@@ -357,11 +325,11 @@ bool Multistate_Value_State_Text_Set(
}
}
return status;;
return status;
;
}
bool Multistate_Value_Change_Of_Value(
uint32_t object_instance)
bool Multistate_Value_Change_Of_Value(uint32_t object_instance)
{
bool status = false;
unsigned index;
@@ -374,8 +342,7 @@ bool Multistate_Value_Change_Of_Value(
return status;
}
void Multistate_Value_Change_Of_Value_Clear(
uint32_t object_instance)
void Multistate_Value_Change_Of_Value_Clear(uint32_t object_instance)
{
unsigned index;
@@ -395,9 +362,8 @@ void Multistate_Value_Change_Of_Value_Clear(
*
* @return true if the value list is encoded
*/
bool Multistate_Value_Encode_Value_List(
uint32_t object_instance,
BACNET_PROPERTY_VALUE * value_list)
bool Multistate_Value_Encode_Value_List(uint32_t object_instance,
BACNET_PROPERTY_VALUE *value_list)
{
bool status = false;
@@ -420,17 +386,17 @@ bool Multistate_Value_Encode_Value_List(
value_list->value.next = NULL;
bitstring_init(&value_list->value.type.Bit_String);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_IN_ALARM, false);
STATUS_FLAG_IN_ALARM, false);
bitstring_set_bit(&value_list->value.type.Bit_String, STATUS_FLAG_FAULT,
false);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_FAULT, false);
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OVERRIDDEN, false);
STATUS_FLAG_OVERRIDDEN, false);
if (Multistate_Value_Out_Of_Service(object_instance)) {
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OUT_OF_SERVICE, true);
STATUS_FLAG_OUT_OF_SERVICE, true);
} else {
bitstring_set_bit(&value_list->value.type.Bit_String,
STATUS_FLAG_OUT_OF_SERVICE, false);
STATUS_FLAG_OUT_OF_SERVICE, false);
}
value_list->priority = BACNET_NO_PRIORITY;
value_list->next = NULL;
@@ -440,14 +406,11 @@ bool Multistate_Value_Encode_Value_List(
return status;
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int Multistate_Value_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Multistate_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
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;
uint32_t present_value = 0;
@@ -462,28 +425,26 @@ int Multistate_Value_Read_Property(
apdu = rpdata->application_data;
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_MULTI_STATE_VALUE, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_MULTI_STATE_VALUE, rpdata->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:
Multistate_Value_Object_Name(rpdata->object_instance,
&char_string);
Multistate_Value_Object_Name(rpdata->object_instance, &char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_DESCRIPTION:
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
Multistate_Value_Description(rpdata->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_MULTI_STATE_VALUE);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_MULTI_STATE_VALUE);
break;
case PROP_PRESENT_VALUE:
present_value =
@@ -510,27 +471,25 @@ int Multistate_Value_Read_Property(
apdu_len = encode_application_boolean(&apdu[0], state);
break;
case PROP_NUMBER_OF_STATES:
apdu_len =
encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
apdu_len = encode_application_unsigned(&apdu[apdu_len],
MULTISTATE_NUMBER_OF_STATES);
break;
case PROP_STATE_TEXT:
if (rpdata->array_index == 0) {
/* Array element zero is the number of elements in the array */
apdu_len =
encode_application_unsigned(&apdu[0],
MULTISTATE_NUMBER_OF_STATES);
apdu_len = encode_application_unsigned(
&apdu[0], MULTISTATE_NUMBER_OF_STATES);
} else if (rpdata->array_index == BACNET_ARRAY_ALL) {
/* if no index was specified, then try to encode the entire list */
/* if no index was specified, then try to encode the entire list
*/
/* into one packet. */
for (i = 1; i <= MULTISTATE_NUMBER_OF_STATES; i++) {
characterstring_init_ansi(&char_string,
Multistate_Value_State_Text(rpdata->object_instance,
i));
Multistate_Value_State_Text(
rpdata->object_instance, i));
/* FIXME: this might go beyond MAX_APDU length! */
len =
encode_application_character_string(&apdu[apdu_len],
&char_string);
len = encode_application_character_string(&apdu[apdu_len],
&char_string);
/* add it if we have room */
if ((apdu_len + len) < MAX_APDU) {
apdu_len += len;
@@ -543,12 +502,12 @@ int Multistate_Value_Read_Property(
}
} else {
if (rpdata->array_index <= MULTISTATE_NUMBER_OF_STATES) {
characterstring_init_ansi(&char_string,
characterstring_init_ansi(
&char_string,
Multistate_Value_State_Text(rpdata->object_instance,
rpdata->array_index));
apdu_len =
encode_application_character_string(&apdu[0],
&char_string);
rpdata->array_index));
apdu_len = encode_application_character_string(
&apdu[0], &char_string);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -575,17 +534,15 @@ int Multistate_Value_Read_Property(
}
/* returns true if successful */
bool Multistate_Value_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Multistate_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -605,11 +562,10 @@ bool Multistate_Value_Write_Property(
case PROP_PRESENT_VALUE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
status =
Multistate_Value_Present_Value_Set
(wp_data->object_instance, value.type.Unsigned_Int);
status = Multistate_Value_Present_Value_Set(
wp_data->object_instance, value.type.Unsigned_Int);
if (!status) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
@@ -619,10 +575,10 @@ bool Multistate_Value_Write_Property(
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Multistate_Value_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
value.type.Boolean);
}
break;
case PROP_OBJECT_IDENTIFIER:
@@ -645,17 +601,14 @@ bool Multistate_Value_Write_Property(
return status;
}
#ifdef TEST
#include <assert.h>
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(
BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -665,10 +618,9 @@ bool WPValidateArgType(
return false;
}
void testMultistateInput(
Test * pTest)
void testMultistateInput(Test *pTest)
{
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -695,8 +647,7 @@ void testMultistateInput(
}
#ifdef TEST_MULTISTATE_VALUE
int main(
void)
int main(void)
{
Test *pTest;
bool rc;
@@ -708,7 +659,7 @@ int main(
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+243 -272
View File
@@ -1,32 +1,32 @@
/**************************************************************************
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Additional changes, Copyright (c) 2018 Ed Hague <edward@bac-test.com>
*
* 2018.06.17 - Attempting to write to Object_Name returned UNKNOWN_PROPERTY.
* Now returns WRITE_ACCESS_DENIED
*
*********************************************************************/
*
* Copyright (C) 2011 Krzysztof Malorny <malornykrzysztof@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Additional changes, Copyright (c) 2018 Ed Hague <edward@bac-test.com>
*
* 2018.06.17 - Attempting to write to Object_Name returned
*UNKNOWN_PROPERTY. Now returns WRITE_ACCESS_DENIED
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
@@ -47,40 +47,27 @@
#include "wp.h"
#include "nc.h"
#ifndef MAX_NOTIFICATION_CLASSES
#define MAX_NOTIFICATION_CLASSES 2
#endif
#if defined(INTRINSIC_REPORTING)
static NOTIFICATION_CLASS_INFO NC_Info[MAX_NOTIFICATION_CLASSES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Notification_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_NOTIFICATION_CLASS,
PROP_PRIORITY,
PROP_ACK_REQUIRED,
PROP_RECIPIENT_LIST,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME,
PROP_OBJECT_TYPE, PROP_NOTIFICATION_CLASS,
PROP_PRIORITY, PROP_ACK_REQUIRED,
PROP_RECIPIENT_LIST, -1};
static const int Notification_Properties_Optional[] = {
PROP_DESCRIPTION,
-1
};
static const int Notification_Properties_Optional[] = {PROP_DESCRIPTION, -1};
static const int Notification_Properties_Proprietary[] = {
-1
};
static const int Notification_Properties_Proprietary[] = {-1};
void Notification_Class_Property_Lists(
const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Notification_Class_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Notification_Properties_Required;
@@ -91,8 +78,7 @@ void Notification_Class_Property_Lists(
return;
}
void Notification_Class_Init(
void)
void Notification_Class_Init(void)
{
uint8_t NotifyIdx = 0;
@@ -101,20 +87,21 @@ void Notification_Class_Init(
memset(&NC_Info[NotifyIdx], 0x00, sizeof(NOTIFICATION_CLASS_INFO));
/* set the basic parameters */
NC_Info[NotifyIdx].Ack_Required = 0;
NC_Info[NotifyIdx].Priority[TRANSITION_TO_OFFNORMAL] = 255; /* The lowest priority for Normal message. */
NC_Info[NotifyIdx].Priority[TRANSITION_TO_FAULT] = 255; /* The lowest priority for Normal message. */
NC_Info[NotifyIdx].Priority[TRANSITION_TO_NORMAL] = 255; /* The lowest priority for Normal message. */
NC_Info[NotifyIdx].Priority[TRANSITION_TO_OFFNORMAL] =
255; /* The lowest priority for Normal message. */
NC_Info[NotifyIdx].Priority[TRANSITION_TO_FAULT] =
255; /* The lowest priority for Normal message. */
NC_Info[NotifyIdx].Priority[TRANSITION_TO_NORMAL] =
255; /* The lowest priority for Normal message. */
}
return;
}
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then you need validate that the */
/* given instance exists */
bool Notification_Class_Valid_Instance(
uint32_t object_instance)
bool Notification_Class_Valid_Instance(uint32_t object_instance)
{
unsigned int index;
@@ -127,8 +114,7 @@ bool Notification_Class_Valid_Instance(
/* we simply have 0-n object instances. Yours might be */
/* more complex, and then count how many you have */
unsigned Notification_Class_Count(
void)
unsigned Notification_Class_Count(void)
{
return MAX_NOTIFICATION_CLASSES;
}
@@ -136,8 +122,7 @@ unsigned Notification_Class_Count(
/* 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 Notification_Class_Index_To_Instance(
unsigned index)
uint32_t Notification_Class_Index_To_Instance(unsigned index)
{
return index;
}
@@ -145,8 +130,7 @@ uint32_t Notification_Class_Index_To_Instance(
/* 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 Notification_Class_Instance_To_Index(
uint32_t object_instance)
unsigned Notification_Class_Instance_To_Index(uint32_t object_instance)
{
unsigned index = MAX_NOTIFICATION_CLASSES;
@@ -156,27 +140,23 @@ unsigned Notification_Class_Instance_To_Index(
return index;
}
bool Notification_Class_Object_Name(
uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
bool Notification_Class_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
unsigned int index;
bool status = false;
index = Notification_Class_Instance_To_Index(object_instance);
if (index < MAX_NOTIFICATION_CLASSES) {
sprintf(text_string, "NOTIFICATION CLASS %lu", (unsigned long) index);
sprintf(text_string, "NOTIFICATION CLASS %lu", (unsigned long)index);
status = characterstring_init_ansi(object_name, text_string);
}
return status;
}
int Notification_Class_Read_Property(
BACNET_READ_PROPERTY_DATA * rpdata)
int Notification_Class_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
NOTIFICATION_CLASS_INFO *CurrentNotify;
BACNET_CHARACTER_STRING char_string;
@@ -185,8 +165,7 @@ int Notification_Class_Read_Property(
uint8_t *apdu = NULL;
uint8_t u8Val;
int idx;
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
if ((rpdata == NULL) || (rpdata->application_data == NULL) ||
(rpdata->application_data_len == 0)) {
@@ -195,28 +174,25 @@ int Notification_Class_Read_Property(
apdu = rpdata->application_data;
CurrentNotify =
&NC_Info[Notification_Class_Instance_To_Index(rpdata->
object_instance)];
&NC_Info[Notification_Class_Instance_To_Index(rpdata->object_instance)];
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_NOTIFICATION_CLASS, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_NOTIFICATION_CLASS, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
Notification_Class_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_NOTIFICATION_CLASS);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_NOTIFICATION_CLASS);
break;
case PROP_NOTIFICATION_CLASS:
@@ -229,18 +205,18 @@ int Notification_Class_Read_Property(
apdu_len += encode_application_unsigned(&apdu[0], 3);
else {
if (rpdata->array_index == BACNET_ARRAY_ALL) {
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
apdu_len += encode_application_unsigned(
&apdu[apdu_len],
CurrentNotify->Priority[TRANSITION_TO_OFFNORMAL]);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
apdu_len += encode_application_unsigned(
&apdu[apdu_len],
CurrentNotify->Priority[TRANSITION_TO_FAULT]);
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
apdu_len += encode_application_unsigned(
&apdu[apdu_len],
CurrentNotify->Priority[TRANSITION_TO_NORMAL]);
} else if (rpdata->array_index <= MAX_BACNET_EVENT_TRANSITION) {
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
apdu_len += encode_application_unsigned(
&apdu[apdu_len],
CurrentNotify->Priority[rpdata->array_index - 1]);
} else {
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -254,11 +230,14 @@ int Notification_Class_Read_Property(
u8Val = CurrentNotify->Ack_Required;
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
bitstring_set_bit(
&bit_string, TRANSITION_TO_OFFNORMAL,
(u8Val & TRANSITION_TO_OFFNORMAL_MASKED) ? true : false);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
bitstring_set_bit(
&bit_string, TRANSITION_TO_FAULT,
(u8Val & TRANSITION_TO_FAULT_MASKED) ? true : false);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
bitstring_set_bit(
&bit_string, TRANSITION_TO_NORMAL,
(u8Val & TRANSITION_TO_NORMAL_MASKED) ? true : false);
/* encode bitstring */
apdu_len +=
@@ -271,11 +250,13 @@ int Notification_Class_Read_Property(
BACNET_DESTINATION *RecipientEntry;
int i = 0;
/* get pointer of current element for Recipient_List - easier for use */
/* get pointer of current element for Recipient_List - easier
* for use */
RecipientEntry = &CurrentNotify->Recipient_List[idx];
if (RecipientEntry->Recipient.RecipientType !=
RECIPIENT_TYPE_NOTINITIALIZED) {
/* Valid Days - BACnetDaysOfWeek - [bitstring] monday-sunday */
/* Valid Days - BACnetDaysOfWeek - [bitstring] monday-sunday
*/
u8Val = 0x01;
bitstring_init(&bit_string);
@@ -284,21 +265,18 @@ int Notification_Class_Read_Property(
bitstring_set_bit(&bit_string, i, true);
else
bitstring_set_bit(&bit_string, i, false);
u8Val <<= 1; /* next day */
u8Val <<= 1; /* next day */
}
apdu_len +=
encode_application_bitstring(&apdu[apdu_len],
&bit_string);
apdu_len += encode_application_bitstring(&apdu[apdu_len],
&bit_string);
/* From Time */
apdu_len +=
encode_application_time(&apdu[apdu_len],
&RecipientEntry->FromTime);
apdu_len += encode_application_time(
&apdu[apdu_len], &RecipientEntry->FromTime);
/* To Time */
apdu_len +=
encode_application_time(&apdu[apdu_len],
&RecipientEntry->ToTime);
apdu_len += encode_application_time(
&apdu[apdu_len], &RecipientEntry->ToTime);
/*
BACnetRecipient ::= CHOICE {
@@ -309,66 +287,67 @@ int Notification_Class_Read_Property(
/* CHOICE - device [0] BACnetObjectIdentifier */
if (RecipientEntry->Recipient.RecipientType ==
RECIPIENT_TYPE_DEVICE) {
apdu_len +=
encode_context_object_id(&apdu[apdu_len], 0,
OBJECT_DEVICE,
apdu_len += encode_context_object_id(
&apdu[apdu_len], 0, OBJECT_DEVICE,
RecipientEntry->Recipient._.DeviceIdentifier);
}
/* CHOICE - address [1] BACnetAddress */
else if (RecipientEntry->Recipient.RecipientType ==
RECIPIENT_TYPE_ADDRESS) {
RECIPIENT_TYPE_ADDRESS) {
/* opening tag 1 */
apdu_len += encode_opening_tag(&apdu[apdu_len], 1);
/* network-number Unsigned16, */
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
apdu_len += encode_application_unsigned(
&apdu[apdu_len],
RecipientEntry->Recipient._.Address.net);
/* mac-address OCTET STRING */
if (RecipientEntry->Recipient._.Address.net) {
octetstring_init(&octet_string,
octetstring_init(
&octet_string,
RecipientEntry->Recipient._.Address.adr,
RecipientEntry->Recipient._.Address.len);
} else {
octetstring_init(&octet_string,
octetstring_init(
&octet_string,
RecipientEntry->Recipient._.Address.mac,
RecipientEntry->Recipient._.Address.mac_len);
}
apdu_len +=
encode_application_octet_string(&apdu[apdu_len],
&octet_string);
apdu_len += encode_application_octet_string(
&apdu[apdu_len], &octet_string);
/* closing tag 1 */
apdu_len += encode_closing_tag(&apdu[apdu_len], 1);
} else {;
} /* shouldn't happen */
} else {
;
} /* shouldn't happen */
/* Process Identifier - Unsigned32 */
apdu_len +=
encode_application_unsigned(&apdu[apdu_len],
RecipientEntry->ProcessIdentifier);
apdu_len += encode_application_unsigned(
&apdu[apdu_len], RecipientEntry->ProcessIdentifier);
/* Issue Confirmed Notifications - boolean */
apdu_len +=
encode_application_boolean(&apdu[apdu_len],
RecipientEntry->ConfirmedNotify);
apdu_len += encode_application_boolean(
&apdu[apdu_len], RecipientEntry->ConfirmedNotify);
/* Transitions - BACnet Event Transition Bits [bitstring] */
u8Val = RecipientEntry->Transitions;
bitstring_init(&bit_string);
bitstring_set_bit(&bit_string, TRANSITION_TO_OFFNORMAL,
(u8Val & TRANSITION_TO_OFFNORMAL_MASKED) ? true :
false);
bitstring_set_bit(&bit_string, TRANSITION_TO_FAULT,
(u8Val & TRANSITION_TO_OFFNORMAL_MASKED)
? true
: false);
bitstring_set_bit(
&bit_string, TRANSITION_TO_FAULT,
(u8Val & TRANSITION_TO_FAULT_MASKED) ? true : false);
bitstring_set_bit(&bit_string, TRANSITION_TO_NORMAL,
bitstring_set_bit(
&bit_string, TRANSITION_TO_NORMAL,
(u8Val & TRANSITION_TO_NORMAL_MASKED) ? true : false);
apdu_len +=
encode_application_bitstring(&apdu[apdu_len],
&bit_string);
apdu_len += encode_application_bitstring(&apdu[apdu_len],
&bit_string);
}
}
break;
@@ -391,29 +370,24 @@ int Notification_Class_Read_Property(
return apdu_len;
}
bool Notification_Class_Write_Property(
BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Notification_Class_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
NOTIFICATION_CLASS_INFO *CurrentNotify;
NOTIFICATION_CLASS_INFO TmpNotify;
BACNET_APPLICATION_DATA_VALUE value;
uint8_t TmpPriority[MAX_BACNET_EVENT_TRANSITION]; /* BACnetARRAY[3] of Unsigned */
uint8_t TmpPriority[MAX_BACNET_EVENT_TRANSITION]; /* BACnetARRAY[3] of
Unsigned */
bool status = false;
int iOffset;
uint8_t idx;
int len = 0;
CurrentNotify =
&NC_Info[Notification_Class_Instance_To_Index(wp_data->
object_instance)];
CurrentNotify = &NC_Info[Notification_Class_Instance_To_Index(
wp_data->object_instance)];
/* decode some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
if (len < 0) {
/* error while decoding - a value larger than we can handle */
wp_data->error_class = ERROR_CLASS_PROPERTY;
@@ -431,7 +405,7 @@ bool Notification_Class_Write_Property(
case PROP_PRIORITY:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_UNSIGNED_INT,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (wp_data->array_index == 0) {
@@ -440,16 +414,15 @@ bool Notification_Class_Write_Property(
status = false;
} else if (wp_data->array_index == BACNET_ARRAY_ALL) {
iOffset = 0;
for (idx = 0; idx < MAX_BACNET_EVENT_TRANSITION; idx++)
{
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
for (idx = 0; idx < MAX_BACNET_EVENT_TRANSITION; idx++) {
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT))
{
/* Bad decode, wrong tag or following required parameter missing */
(value.tag !=
BACNET_APPLICATION_TAG_UNSIGNED_INT)) {
/* Bad decode, wrong tag or following required
* parameter missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
status = false;
@@ -461,22 +434,21 @@ bool Notification_Class_Write_Property(
status = false;
break;
}
TmpPriority[idx] = (uint8_t) value.type.Unsigned_Int;
TmpPriority[idx] = (uint8_t)value.type.Unsigned_Int;
iOffset += len;
}
if (status == true) {
for (idx = 0; idx < MAX_BACNET_EVENT_TRANSITION; idx++)
CurrentNotify->Priority[idx] = TmpPriority[idx];
CurrentNotify->Priority[idx] = TmpPriority[idx];
}
} else if (wp_data->array_index <= 3) {
if (value.type.Unsigned_Int > 255) {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
status = false;
}
else
CurrentNotify->Priority[wp_data->array_index - 1] =
value.type.Unsigned_Int;
} else
CurrentNotify->Priority[wp_data->array_index - 1] =
value.type.Unsigned_Int;
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
@@ -488,7 +460,7 @@ bool Notification_Class_Write_Property(
case PROP_ACK_REQUIRED:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BIT_STRING,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
if (value.type.Bit_String.bits_used == 3) {
@@ -509,14 +481,14 @@ bool Notification_Class_Write_Property(
/* decode all packed */
while (iOffset < wp_data->application_data_len) {
/* Decode Valid Days */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -534,13 +506,13 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* Decode From Time */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -550,13 +522,13 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* Decode To Time */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) || (value.tag != BACNET_APPLICATION_TAG_TIME)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -567,44 +539,44 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* context tag [0] - Device */
if (decode_is_context_tag(&wp_data->application_data[iOffset],
0)) {
0)) {
TmpNotify.Recipient_List[idx].Recipient.RecipientType =
RECIPIENT_TYPE_DEVICE;
/* Decode Network Number */
len =
bacapp_decode_context_data(&wp_data->
application_data[iOffset],
len = bacapp_decode_context_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value,
PROP_RECIPIENT_LIST);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_OBJECT_ID)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
}
/* store value */
TmpNotify.Recipient_List[idx].Recipient._.
DeviceIdentifier = value.type.Object_Id.instance;
TmpNotify.Recipient_List[idx].Recipient._.DeviceIdentifier =
value.type.Object_Id.instance;
iOffset += len;
}
/* opening tag [1] - Recipient */
else if (decode_is_opening_tag_number(&wp_data->
application_data[iOffset], 1)) {
else if (decode_is_opening_tag_number(
&wp_data->application_data[iOffset], 1)) {
iOffset++;
TmpNotify.Recipient_List[idx].Recipient.RecipientType =
RECIPIENT_TYPE_ADDRESS;
/* Decode Network Number */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset],
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -615,61 +587,66 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* Decode Address */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset],
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_OCTET_STRING)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
}
/* store value */
if (TmpNotify.Recipient_List[idx].Recipient._.Address.
net == 0) {
memcpy(TmpNotify.Recipient_List[idx].Recipient._.
Address.mac, value.type.Octet_String.value,
value.type.Octet_String.length);
TmpNotify.Recipient_List[idx].Recipient._.Address.
mac_len = value.type.Octet_String.length;
if (TmpNotify.Recipient_List[idx].Recipient._.Address.net ==
0) {
memcpy(TmpNotify.Recipient_List[idx]
.Recipient._.Address.mac,
value.type.Octet_String.value,
value.type.Octet_String.length);
TmpNotify.Recipient_List[idx]
.Recipient._.Address.mac_len =
value.type.Octet_String.length;
} else {
memcpy(TmpNotify.Recipient_List[idx].Recipient._.
Address.adr, value.type.Octet_String.value,
value.type.Octet_String.length);
memcpy(TmpNotify.Recipient_List[idx]
.Recipient._.Address.adr,
value.type.Octet_String.value,
value.type.Octet_String.length);
TmpNotify.Recipient_List[idx].Recipient._.Address.len =
value.type.Octet_String.length;
}
iOffset += len;
/* closing tag [1] - Recipient */
if (decode_is_closing_tag_number(&wp_data->
application_data[iOffset], 1))
if (decode_is_closing_tag_number(
&wp_data->application_data[iOffset], 1))
iOffset++;
else {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
}
} else {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
}
/* Process Identifier */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_UNSIGNED_INT)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -680,14 +657,14 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* Issue Confirmed Notifications */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_BOOLEAN)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -698,14 +675,14 @@ bool Notification_Class_Write_Property(
iOffset += len;
/* Transitions */
len =
bacapp_decode_application_data(&wp_data->
application_data[iOffset], wp_data->application_data_len,
&value);
len = bacapp_decode_application_data(
&wp_data->application_data[iOffset],
wp_data->application_data_len, &value);
if ((len == 0) ||
(value.tag != BACNET_APPLICATION_TAG_BIT_STRING)) {
/* Bad decode, wrong tag or following required parameter missing */
/* Bad decode, wrong tag or following required parameter
* missing */
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
return false;
@@ -726,8 +703,7 @@ bool Notification_Class_Write_Property(
/* Increasing element of list */
if (++idx >= NC_MAX_RECIPIENTS) {
wp_data->error_class = ERROR_CLASS_RESOURCES;
wp_data->error_code =
ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
return false;
}
}
@@ -735,26 +711,29 @@ bool Notification_Class_Write_Property(
/* Decoded all recipient list */
/* copy elements from temporary object */
for (idx = 0; idx < NC_MAX_RECIPIENTS; idx++) {
BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS src = {0};
unsigned max_apdu = 0;
int32_t DeviceID;
CurrentNotify->Recipient_List[idx] =
TmpNotify.Recipient_List[idx];
if (CurrentNotify->Recipient_List[idx].Recipient.
RecipientType == RECIPIENT_TYPE_DEVICE) {
if (CurrentNotify->Recipient_List[idx]
.Recipient.RecipientType == RECIPIENT_TYPE_DEVICE) {
/* copy Device_ID */
DeviceID =
CurrentNotify->Recipient_List[idx].Recipient._.
DeviceIdentifier;
DeviceID = CurrentNotify->Recipient_List[idx]
.Recipient._.DeviceIdentifier;
address_bind_request(DeviceID, &max_apdu, &src);
} else if (CurrentNotify->Recipient_List[idx].Recipient.
RecipientType == RECIPIENT_TYPE_ADDRESS) {
} else if (CurrentNotify->Recipient_List[idx]
.Recipient.RecipientType ==
RECIPIENT_TYPE_ADDRESS) {
/* copy Address */
/* src = CurrentNotify->Recipient_List[idx].Recipient._.Address; */
/* address_bind_request(BACNET_MAX_INSTANCE, &max_apdu, &src); */
/* src =
* CurrentNotify->Recipient_List[idx].Recipient._.Address;
*/
/* address_bind_request(BACNET_MAX_INSTANCE, &max_apdu,
* &src); */
}
}
@@ -774,10 +753,8 @@ bool Notification_Class_Write_Property(
return status;
}
void Notification_Class_Get_Priorities(
uint32_t Object_Instance,
uint32_t * pPriorityArray)
void Notification_Class_Get_Priorities(uint32_t Object_Instance,
uint32_t *pPriorityArray)
{
NOTIFICATION_CLASS_INFO *CurrentNotify;
uint32_t object_index;
@@ -797,10 +774,8 @@ void Notification_Class_Get_Priorities(
pPriorityArray[i] = CurrentNotify->Priority[i];
}
static bool IsRecipientActive(
BACNET_DESTINATION * pBacDest,
uint8_t EventToState)
static bool IsRecipientActive(BACNET_DESTINATION *pBacDest,
uint8_t EventToState)
{
BACNET_DATE_TIME DateTime;
@@ -824,7 +799,7 @@ static bool IsRecipientActive(
break;
default:
return false; /* shouldn't happen */
return false; /* shouldn't happen */
}
/* get actual date and time */
@@ -845,9 +820,8 @@ static bool IsRecipientActive(
return true;
}
void Notification_Class_common_reporting_function(
BACNET_EVENT_NOTIFICATION_DATA * event_data)
BACNET_EVENT_NOTIFICATION_DATA *event_data)
{
/* Fill the parameters common for all types of events. */
@@ -856,7 +830,6 @@ void Notification_Class_common_reporting_function(
uint32_t notify_index;
uint8_t index;
notify_index =
Notification_Class_Instance_To_Index(event_data->notificationClass);
@@ -865,7 +838,6 @@ void Notification_Class_common_reporting_function(
else
return;
/* Initiating Device Identifier */
event_data->initiatingObjectIdentifier.type = OBJECT_DEVICE;
event_data->initiatingObjectIdentifier.instance =
@@ -877,16 +849,17 @@ void Notification_Class_common_reporting_function(
event_data->priority =
CurrentNotify->Priority[TRANSITION_TO_NORMAL];
event_data->ackRequired =
(CurrentNotify->
Ack_Required & TRANSITION_TO_NORMAL_MASKED) ? true : false;
(CurrentNotify->Ack_Required & TRANSITION_TO_NORMAL_MASKED)
? true
: false;
break;
case EVENT_STATE_FAULT:
event_data->priority =
CurrentNotify->Priority[TRANSITION_TO_FAULT];
event_data->priority = CurrentNotify->Priority[TRANSITION_TO_FAULT];
event_data->ackRequired =
(CurrentNotify->
Ack_Required & TRANSITION_TO_FAULT_MASKED) ? true : false;
(CurrentNotify->Ack_Required & TRANSITION_TO_FAULT_MASKED)
? true
: false;
break;
case EVENT_STATE_OFFNORMAL:
@@ -896,10 +869,11 @@ void Notification_Class_common_reporting_function(
CurrentNotify->Priority[TRANSITION_TO_OFFNORMAL];
event_data->ackRequired =
(CurrentNotify->Ack_Required & TRANSITION_TO_OFFNORMAL_MASKED)
? true : false;
? true
: false;
break;
default: /* shouldn't happen */
default: /* shouldn't happen */
break;
}
@@ -909,7 +883,7 @@ void Notification_Class_common_reporting_function(
for (index = 0; index < NC_MAX_RECIPIENTS; index++, pBacDest++) {
/* check if recipient is defined */
if (pBacDest->Recipient.RecipientType == RECIPIENT_TYPE_NOTINITIALIZED)
break; /* recipient doesn't defined - end of list */
break; /* recipient doesn't defined - end of list */
if (IsRecipientActive(pBacDest, event_data->toState) == true) {
BACNET_ADDRESS dest;
@@ -928,9 +902,9 @@ void Notification_Class_common_reporting_function(
Send_CEvent_Notify(device_id, event_data);
else if (address_get_by_device(device_id, &max_apdu, &dest))
Send_UEvent_Notify(Handler_Transmit_Buffer, event_data,
&dest);
&dest);
} else if (pBacDest->Recipient.RecipientType ==
RECIPIENT_TYPE_ADDRESS) {
RECIPIENT_TYPE_ADDRESS) {
/* send notification to the address indicated */
if (pBacDest->ConfirmedNotify == true) {
if (address_get_device_id(&dest, &device_id))
@@ -938,7 +912,7 @@ void Notification_Class_common_reporting_function(
} else {
dest = pBacDest->Recipient._.Address;
Send_UEvent_Notify(Handler_Transmit_Buffer, event_data,
&dest);
&dest);
}
}
}
@@ -947,20 +921,18 @@ void Notification_Class_common_reporting_function(
/* This function tries to find the addresses of the defined devices. */
/* It should be called periodically (example once per minute). */
void Notification_Class_find_recipient(
void)
void Notification_Class_find_recipient(void)
{
NOTIFICATION_CLASS_INFO *CurrentNotify;
BACNET_DESTINATION *pBacDest;
BACNET_ADDRESS src = { 0 };
BACNET_ADDRESS src = {0};
unsigned max_apdu = 0;
uint32_t notify_index;
uint32_t DeviceID;
uint8_t idx;
for (notify_index = 0; notify_index < MAX_NOTIFICATION_CLASSES;
notify_index++) {
notify_index++) {
/* pointer to current notification */
CurrentNotify =
&NC_Info[Notification_Class_Instance_To_Index(notify_index)];
@@ -970,15 +942,14 @@ void Notification_Class_find_recipient(
if (CurrentNotify->Recipient_List[idx].Recipient.RecipientType ==
RECIPIENT_TYPE_DEVICE) {
/* Device ID */
DeviceID =
CurrentNotify->Recipient_List[idx].Recipient._.
DeviceIdentifier;
/* Send who_ is request only when address of device is unknown. */
DeviceID = CurrentNotify->Recipient_List[idx]
.Recipient._.DeviceIdentifier;
/* Send who_ is request only when address of device is unknown.
*/
if (!address_bind_request(DeviceID, &max_apdu, &src))
Send_WhoIs(DeviceID, DeviceID);
} else if (CurrentNotify->Recipient_List[idx].Recipient.
RecipientType == RECIPIENT_TYPE_ADDRESS) {
} else if (CurrentNotify->Recipient_List[idx]
.Recipient.RecipientType == RECIPIENT_TYPE_ADDRESS) {
}
}
}
+239 -358
View File
File diff suppressed because it is too large Load Diff
+57 -75
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* OctetString Value Objects - customize for your use */
@@ -35,12 +35,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "bactext.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "device.h"
#include "handlers.h"
#include "osv.h"
#ifndef MAX_OCTETSTRING_VALUES
#define MAX_OCTETSTRING_VALUES 4
#endif
@@ -49,28 +48,17 @@ OCTETSTRING_VALUE_DESCR AV_Descr[MAX_OCTETSTRING_VALUES];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int OctetString_Value_Properties_Required[] = {
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME,
PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
-1
};
PROP_OBJECT_IDENTIFIER, PROP_OBJECT_NAME, PROP_OBJECT_TYPE,
PROP_PRESENT_VALUE, PROP_STATUS_FLAGS, -1};
static const int OctetString_Value_Properties_Optional[] = {
PROP_EVENT_STATE,
PROP_OUT_OF_SERVICE,
PROP_DESCRIPTION,
-1
};
PROP_EVENT_STATE, PROP_OUT_OF_SERVICE, PROP_DESCRIPTION, -1};
static const int OctetString_Value_Properties_Proprietary[] = {
-1
};
static const int OctetString_Value_Properties_Proprietary[] = {-1};
void OctetString_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = OctetString_Value_Properties_Required;
@@ -142,8 +130,8 @@ unsigned OctetString_Value_Instance_To_Index(uint32_t object_instance)
* @return true if values are within range and present-value is set.
*/
bool OctetString_Value_Present_Value_Set(uint32_t object_instance,
BACNET_OCTET_STRING * value,
uint8_t priority)
BACNET_OCTET_STRING *value,
uint8_t priority)
{
unsigned index = 0;
bool status = false;
@@ -171,14 +159,14 @@ BACNET_OCTET_STRING *OctetString_Value_Present_Value(uint32_t object_instance)
/* note: the object name must be unique within this device */
bool OctetString_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_OCTETSTRING_VALUES) {
sprintf(text_string, "OCTETSTRING VALUE %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -186,9 +174,9 @@ bool OctetString_Value_Object_Name(uint32_t object_instance,
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
BACNET_OCTET_STRING *real_value = NULL;
@@ -204,8 +192,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
apdu = rpdata->application_data;
object_index =
OctetString_Value_Instance_To_Index(rpdata->object_instance);
object_index = OctetString_Value_Instance_To_Index(rpdata->object_instance);
if (object_index < MAX_OCTETSTRING_VALUES)
CurrentAV = &AV_Descr[object_index];
else
@@ -213,23 +200,21 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_OCTETSTRING_VALUE, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_OCTETSTRING_VALUE, rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
case PROP_DESCRIPTION:
OctetString_Value_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_OCTETSTRING_VALUE);
apdu_len = encode_application_enumerated(&apdu[0],
OBJECT_OCTETSTRING_VALUE);
break;
case PROP_PRESENT_VALUE:
@@ -244,7 +229,7 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
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,
CurrentAV->Out_Of_Service);
CurrentAV->Out_Of_Service);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -277,18 +262,17 @@ int OctetString_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
}
/* returns true if successful */
bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
OCTETSTRING_VALUE_DESCR *CurrentAV;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -317,8 +301,8 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (OctetString_Value_Present_Value_Set(wp_data->
object_instance, &value.type.Octet_String,
if (OctetString_Value_Present_Value_Set(
wp_data->object_instance, &value.type.Octet_String,
wp_data->priority)) {
status = true;
} else if (wp_data->priority == 6) {
@@ -341,7 +325,7 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
CurrentAV->Out_Of_Service = value.type.Boolean;
}
@@ -365,7 +349,6 @@ bool OctetString_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
return status;
}
void OctetString_Value_Intrinsic_Reporting(uint32_t object_instance)
{
}
@@ -375,10 +358,9 @@ void OctetString_Value_Intrinsic_Reporting(uint32_t object_instance)
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -388,10 +370,10 @@ bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE * pValue,
return false;
}
void testOctetString_Value(Test * pTest)
void testOctetString_Value(Test *pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -429,7 +411,7 @@ int main(void)
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+66 -78
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
/* Positiveinteger Value Objects - customize for your use */
@@ -35,12 +35,11 @@
#include "bacenum.h"
#include "bacapp.h"
#include "bactext.h"
#include "config.h" /* the custom stuff */
#include "config.h" /* the custom stuff */
#include "device.h"
#include "handlers.h"
#include "piv.h"
#ifndef MAX_POSITIVEINTEGER_VALUES
#define MAX_POSITIVEINTEGER_VALUES 4
#endif
@@ -55,21 +54,16 @@ static const int PositiveInteger_Value_Properties_Required[] = {
PROP_PRESENT_VALUE,
PROP_STATUS_FLAGS,
PROP_UNITS,
- 1
};
-1};
static const int PositiveInteger_Value_Properties_Optional[] = {
PROP_OUT_OF_SERVICE,
-1
};
PROP_OUT_OF_SERVICE, -1};
static const int PositiveInteger_Value_Properties_Proprietary[] = {
-1
};
static const int PositiveInteger_Value_Properties_Proprietary[] = {-1};
void PositiveInteger_Value_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = PositiveInteger_Value_Properties_Required;
@@ -140,8 +134,7 @@ unsigned PositiveInteger_Value_Instance_To_Index(uint32_t object_instance)
* @return true if values are within range and present-value is set.
*/
bool PositiveInteger_Value_Present_Value_Set(uint32_t object_instance,
uint32_t value,
uint8_t priority)
uint32_t value, uint8_t priority)
{
unsigned index = 0;
bool status = false;
@@ -169,14 +162,14 @@ uint32_t PositiveInteger_Value_Present_Value(uint32_t object_instance)
/* note: the object name must be unique within this device */
bool PositiveInteger_Value_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
bool status = false;
if (object_instance < MAX_POSITIVEINTEGER_VALUES) {
sprintf(text_string, "POSITIVEINTEGER VALUE %lu",
(unsigned long) object_instance);
(unsigned long)object_instance);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -184,9 +177,9 @@ bool PositiveInteger_Value_Object_Name(uint32_t object_instance,
}
/* return apdu len, or BACNET_STATUS_ERROR on error */
int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0; /* return value */
int apdu_len = 0; /* return value */
BACNET_BIT_STRING bit_string;
BACNET_CHARACTER_STRING char_string;
unsigned object_index = 0;
@@ -210,27 +203,26 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
switch (rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0],
OBJECT_POSITIVE_INTEGER_VALUE, rpdata->object_instance);
apdu_len = encode_application_object_id(
&apdu[0], OBJECT_POSITIVE_INTEGER_VALUE,
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
PositiveInteger_Value_Object_Name(rpdata->object_instance,
&char_string);
&char_string);
apdu_len =
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0],
OBJECT_POSITIVE_INTEGER_VALUE);
apdu_len = encode_application_enumerated(
&apdu[0], OBJECT_POSITIVE_INTEGER_VALUE);
break;
case PROP_PRESENT_VALUE:
apdu_len =
encode_application_unsigned(&apdu[0],
apdu_len = encode_application_unsigned(
&apdu[0],
PositiveInteger_Value_Present_Value(rpdata->object_instance));
break;
@@ -240,7 +232,7 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
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,
CurrentAV->Out_Of_Service);
CurrentAV->Out_Of_Service);
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
@@ -248,16 +240,15 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
case PROP_UNITS:
apdu_len =
encode_application_enumerated(&apdu[0], CurrentAV->Units);
break;
/* BACnet Testing Observed Incident oi00109
Positive Integer Value / Units returned wrong datatype - missing break.
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00031
BC 135.1: 9.20.1.7
BC 135.1: 9.20.1.9
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes have been reviewed
by all interested parties. Say 6 months -> September 2016 */
break;
/* BACnet Testing Observed Incident oi00109
Positive Integer Value / Units returned wrong datatype -
missing break. Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00031 BC
135.1: 9.20.1.7 BC 135.1: 9.20.1.9 Any discussions can be
directed to edward@bac-test.com Please feel free to remove this
comment when my changes have been reviewed by all interested
parties. Say 6 months -> September 2016 */
case PROP_OUT_OF_SERVICE:
state = CurrentAV->Out_Of_Service;
@@ -282,18 +273,17 @@ int PositiveInteger_Value_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
}
/* returns true if successful */
bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
bool status = false; /* return value */
bool status = false; /* return value */
unsigned int object_index = 0;
int len = 0;
BACNET_APPLICATION_DATA_VALUE value;
POSITIVEINTEGER_VALUE_DESCR *CurrentAV;
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -322,8 +312,8 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
/* Command priority 6 is reserved for use by Minimum On/Off
algorithm and may not be used for other purposes in any
object. */
if (PositiveInteger_Value_Present_Value_Set(wp_data->
object_instance, value.type.Unsigned_Int,
if (PositiveInteger_Value_Present_Value_Set(
wp_data->object_instance, value.type.Unsigned_Int,
wp_data->priority)) {
status = true;
} else if (wp_data->priority == 6) {
@@ -346,7 +336,7 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
case PROP_OUT_OF_SERVICE:
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
CurrentAV->Out_Of_Service = value.type.Boolean;
}
@@ -369,7 +359,6 @@ bool PositiveInteger_Value_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
return status;
}
void PositiveInteger_Value_Intrinsic_Reporting(uint32_t object_instance)
{
}
@@ -379,10 +368,9 @@ void PositiveInteger_Value_Intrinsic_Reporting(uint32_t object_instance)
#include <string.h>
#include "ctest.h"
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE * pValue,
uint8_t ucExpectedTag,
BACNET_ERROR_CLASS * pErrorClass,
BACNET_ERROR_CODE * pErrorCode)
bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE *pValue,
uint8_t ucExpectedTag, BACNET_ERROR_CLASS *pErrorClass,
BACNET_ERROR_CODE *pErrorCode)
{
pValue = pValue;
ucExpectedTag = ucExpectedTag;
@@ -392,10 +380,10 @@ bool WPValidateArgType(BACNET_APPLICATION_DATA_VALUE * pValue,
return false;
}
void testPositiveInteger_Value(Test * pTest)
void testPositiveInteger_Value(Test *pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -433,7 +421,7 @@ int main(void)
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+138 -147
View File
@@ -1,27 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
*
* Copyright (C) 2015 Nikola Jelic <nikola.jelic@euroicc.com>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*********************************************************************/
#include <stdbool.h>
#include <stdint.h>
@@ -55,21 +55,14 @@ static const int Schedule_Properties_Required[] = {
PROP_STATUS_FLAGS,
PROP_RELIABILITY,
PROP_OUT_OF_SERVICE,
-1
};
-1};
static const int Schedule_Properties_Optional[] = {
PROP_WEEKLY_SCHEDULE,
-1
};
static const int Schedule_Properties_Optional[] = {PROP_WEEKLY_SCHEDULE, -1};
static const int Schedule_Properties_Proprietary[] = {
-1
};
static const int Schedule_Properties_Proprietary[] = {-1};
void Schedule_Property_Lists(const int **pRequired,
const int **pOptional,
const int **pProprietary)
void Schedule_Property_Lists(const int **pRequired, const int **pOptional,
const int **pProprietary)
{
if (pRequired)
*pRequired = Schedule_Properties_Required;
@@ -98,9 +91,11 @@ void Schedule_Init(void)
Schedule_Descr[i].Present_Value = &Schedule_Descr[i].Schedule_Default;
Schedule_Descr[i].Schedule_Default.context_specific = false;
Schedule_Descr[i].Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL;
Schedule_Descr[i].Schedule_Default.type.Real = 21.0; /* 21 C, room temperature */
Schedule_Descr[i].obj_prop_ref_cnt = 0; /* no references, add as needed */
Schedule_Descr[i].Priority_For_Writing = 16; /* lowest priority */
Schedule_Descr[i].Schedule_Default.type.Real =
21.0; /* 21 C, room temperature */
Schedule_Descr[i].obj_prop_ref_cnt =
0; /* no references, add as needed */
Schedule_Descr[i].Priority_For_Writing = 16; /* lowest priority */
Schedule_Descr[i].Out_Of_Service = false;
}
}
@@ -135,15 +130,15 @@ unsigned Schedule_Instance_To_Index(uint32_t instance)
}
bool Schedule_Object_Name(uint32_t object_instance,
BACNET_CHARACTER_STRING * object_name)
BACNET_CHARACTER_STRING *object_name)
{
static char text_string[32] = ""; /* okay for single thread */
static char text_string[32] = ""; /* okay for single thread */
unsigned int index;
bool status = false;
index = Schedule_Instance_To_Index(object_instance);
if (index < MAX_SCHEDULES) {
sprintf(text_string, "SCHEDULE %lu", (unsigned long) index);
sprintf(text_string, "SCHEDULE %lu", (unsigned long)index);
status = characterstring_init_ansi(object_name, text_string);
}
@@ -151,15 +146,13 @@ bool Schedule_Object_Name(uint32_t object_instance,
}
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00032
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
void Schedule_Out_Of_Service_Set(
uint32_t object_instance,
bool value)
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00032 Any discussions
can be directed to edward@bac-test.com Please feel free to remove this
comment when my changes accepted after suitable time for review by all
interested parties. Say 6 months -> September 2016 */
void Schedule_Out_Of_Service_Set(uint32_t object_instance, bool value)
{
unsigned index = 0;
@@ -169,8 +162,7 @@ void Schedule_Out_Of_Service_Set(
}
}
int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
{
int apdu_len = 0;
unsigned object_index = 0;
@@ -192,11 +184,10 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
return BACNET_STATUS_ERROR;
apdu = rpdata->application_data;
switch ((int) rpdata->object_property) {
switch ((int)rpdata->object_property) {
case PROP_OBJECT_IDENTIFIER:
apdu_len =
encode_application_object_id(&apdu[0], OBJECT_SCHEDULE,
rpdata->object_instance);
apdu_len = encode_application_object_id(&apdu[0], OBJECT_SCHEDULE,
rpdata->object_instance);
break;
case PROP_OBJECT_NAME:
Schedule_Object_Name(rpdata->object_instance, &char_string);
@@ -204,49 +195,51 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
encode_application_character_string(&apdu[0], &char_string);
break;
case PROP_OBJECT_TYPE:
apdu_len =
encode_application_enumerated(&apdu[0], OBJECT_SCHEDULE);
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_SCHEDULE);
break;
case PROP_PRESENT_VALUE:
apdu_len = bacapp_encode_data(&apdu[0], CurrentSC->Present_Value);
break;
case PROP_EFFECTIVE_PERIOD:
/* BACnet Testing Observed Incident oi00110
Effective Period of Schedule object not correctly formatted
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00031
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
apdu_len = encode_application_date(&apdu[0], &CurrentSC->Start_Date);
/* BACnet Testing Observed Incident oi00110
Effective Period of Schedule object not correctly formatted
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00031 Any
discussions can be directed to edward@bac-test.com Please feel
free to remove this comment when my changes accepted after
suitable time for
review by all interested parties. Say 6 months -> September
2016 */
apdu_len =
encode_application_date(&apdu[0], &CurrentSC->Start_Date);
apdu_len +=
encode_application_date(&apdu[apdu_len], &CurrentSC->End_Date);
break;
case PROP_WEEKLY_SCHEDULE:
if (rpdata->array_index == 0) /* count, always 7 */
if (rpdata->array_index == 0) /* count, always 7 */
apdu_len = encode_application_unsigned(&apdu[0], 7);
else if (rpdata->array_index == BACNET_ARRAY_ALL) { /* full array */
int day;
for (day = 0; day < 7; day++) {
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count;
i++) {
apdu_len +=
bacapp_encode_time_value(&apdu[apdu_len],
i++) {
apdu_len += bacapp_encode_time_value(
&apdu[apdu_len],
&CurrentSC->Weekly_Schedule[day].Time_Values[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
}
} else if (rpdata->array_index <= 7) { /* some array element */
} else if (rpdata->array_index <= 7) { /* some array element */
int day = rpdata->array_index - 1;
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count; i++) {
apdu_len +=
bacapp_encode_time_value(&apdu[apdu_len],
apdu_len += bacapp_encode_time_value(
&apdu[apdu_len],
&CurrentSC->Weekly_Schedule[day].Time_Values[i]);
}
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
} else { /* out of bounds */
} else { /* out of bounds */
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_INVALID_ARRAY_INDEX;
apdu_len = BACNET_STATUS_ERROR;
@@ -258,15 +251,13 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
break;
case PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES:
for (i = 0; i < CurrentSC->obj_prop_ref_cnt; i++) {
apdu_len +=
bacapp_encode_device_obj_property_ref(&apdu[apdu_len],
&CurrentSC->Object_Property_References[i]);
apdu_len += bacapp_encode_device_obj_property_ref(
&apdu[apdu_len], &CurrentSC->Object_Property_References[i]);
}
break;
case PROP_PRIORITY_FOR_WRITING:
apdu_len =
encode_application_unsigned(&apdu[0],
CurrentSC->Priority_For_Writing);
apdu_len = encode_application_unsigned(
&apdu[0], CurrentSC->Priority_For_Writing);
break;
case PROP_STATUS_FLAGS:
bitstring_init(&bit_string);
@@ -277,21 +268,22 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
apdu_len = encode_application_bitstring(&apdu[0], &bit_string);
break;
case PROP_RELIABILITY:
apdu_len =
encode_application_enumerated(&apdu[0],
RELIABILITY_NO_FAULT_DETECTED);
apdu_len = encode_application_enumerated(
&apdu[0], RELIABILITY_NO_FAULT_DETECTED);
break;
case PROP_OUT_OF_SERVICE:
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00032
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
apdu_len = encode_application_boolean(&apdu[0],
CurrentSC->Out_Of_Service );
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00032 Any
discussions can be directed to edward@bac-test.com Please feel
free to remove this comment when my changes accepted after
suitable time for
review by all interested parties. Say 6 months -> September
2016 */
apdu_len =
encode_application_boolean(&apdu[0], CurrentSC->Out_Of_Service);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
@@ -300,8 +292,8 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
break;
}
if ((apdu_len >= 0) && (rpdata->object_property != PROP_WEEKLY_SCHEDULE)
&& (rpdata->array_index != BACNET_ARRAY_ALL)) {
if ((apdu_len >= 0) && (rpdata->object_property != PROP_WEEKLY_SCHEDULE) &&
(rpdata->array_index != BACNET_ARRAY_ALL)) {
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY;
apdu_len = BACNET_STATUS_ERROR;
@@ -310,28 +302,29 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA * rpdata)
return apdu_len;
}
bool Schedule_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
bool Schedule_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
{
/* Ed->Steve, I know that initializing stack values used to be 'safer', but warnings in latest compilers indicate when
uninitialized values are being used, and I think that the warnings are more useful to reveal bad code flow than the
"safety: of pre-intializing variables. Please give this some thought let me know if you agree we should start to
remove initializations */
unsigned object_index ;
bool status = false; /* return value */
int len ;
/* Ed->Steve, I know that initializing stack values used to be 'safer', but
warnings in latest compilers indicate when uninitialized values are being
used, and I think that the warnings are more useful to reveal bad code
flow than the "safety: of pre-intializing variables. Please give this
some thought let me know if you agree we should start to remove
initializations */
unsigned object_index;
bool status = false; /* return value */
int len;
BACNET_APPLICATION_DATA_VALUE value;
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00032
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00032 Any
discussions can be directed to edward@bac-test.com Please feel free to
remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
/* decode the some of the request */
len =
bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
len = bacapp_decode_application_data(wp_data->application_data,
wp_data->application_data_len, &value);
/* FIXME: len < application_data_len: more data? */
if (len < 0) {
/* error while decoding - a value larger than we can handle */
@@ -345,22 +338,23 @@ bool Schedule_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
return false;
}
switch ((int) wp_data->object_property) {
switch ((int)wp_data->object_property) {
case PROP_OUT_OF_SERVICE:
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 ( www.bac-test.com/bacnet-test-client-download )
BITS: BIT00032
Any discussions can be directed to edward@bac-test.com
Please feel free to remove this comment when my changes accepted after suitable time for
review by all interested parties. Say 6 months -> September 2016 */
/* BACnet Testing Observed Incident oi00106
Out of service was not supported by Schedule object
Revealed by BACnet Test Client v1.8.16 (
www.bac-test.com/bacnet-test-client-download ) BITS: BIT00032 Any
discussions can be directed to edward@bac-test.com Please feel
free to remove this comment when my changes accepted after
suitable time for
review by all interested parties. Say 6 months -> September
2016 */
status =
WPValidateArgType(&value, BACNET_APPLICATION_TAG_BOOLEAN,
&wp_data->error_class, &wp_data->error_code);
&wp_data->error_class, &wp_data->error_code);
if (status) {
Schedule_Out_Of_Service_Set(
wp_data->object_instance,
value.type.Boolean);
Schedule_Out_Of_Service_Set(wp_data->object_instance,
value.type.Boolean);
}
break;
@@ -387,8 +381,7 @@ bool Schedule_Write_Property(BACNET_WRITE_PROPERTY_DATA * wp_data)
return status;
}
bool Schedule_In_Effective_Period(SCHEDULE_DESCR * desc,
BACNET_DATE * date)
bool Schedule_In_Effective_Period(SCHEDULE_DESCR *desc, BACNET_DATE *date)
{
bool res = false;
@@ -401,29 +394,29 @@ bool Schedule_In_Effective_Period(SCHEDULE_DESCR * desc,
return res;
}
void Schedule_Recalculate_PV(SCHEDULE_DESCR * desc,
BACNET_WEEKDAY wday,
BACNET_TIME * time)
void Schedule_Recalculate_PV(SCHEDULE_DESCR *desc, BACNET_WEEKDAY wday,
BACNET_TIME *time)
{
int i;
desc->Present_Value = NULL;
/* for future development, here should be the loop for Exception Schedule */
/* Just a note to developers: We have a paying customer who has asked us to fully implement the Schedule Object.
In good spirit, they have agreed to allow us to release the code we develop back to the Open Source community after a 6-12 month waiting period.
However, if you are about to work on this yourself, please ping us at info@connect-ex.com, we may be able to broker an early release on a
case-by-case basis. */
for (i = 0;
i < desc->Weekly_Schedule[wday - 1].TV_Count &&
desc->Present_Value == NULL; i++) {
int diff = datetime_wildcard_compare_time(time,
&desc->Weekly_Schedule[wday - 1].Time_Values[i].Time);
/* Just a note to developers: We have a paying customer who has asked us to
fully implement the Schedule Object. In good spirit, they have agreed to
allow us to release the code we develop back to the Open Source community
after a 6-12 month waiting period. However, if you are about to work on
this yourself, please ping us at info@connect-ex.com, we may be able to
broker an early release on a case-by-case basis. */
for (i = 0; i < desc->Weekly_Schedule[wday - 1].TV_Count &&
desc->Present_Value == NULL;
i++) {
int diff = datetime_wildcard_compare_time(
time, &desc->Weekly_Schedule[wday - 1].Time_Values[i].Time);
if (diff >= 0 &&
desc->Weekly_Schedule[wday - 1].Time_Values[i].Value.tag !=
BACNET_APPLICATION_TAG_NULL) {
BACNET_APPLICATION_TAG_NULL) {
desc->Present_Value =
&desc->Weekly_Schedule[wday - 1].Time_Values[i].Value;
}
@@ -438,11 +431,10 @@ void Schedule_Recalculate_PV(SCHEDULE_DESCR * desc,
#include <string.h>
#include "ctest.h"
void testSchedule(Test * pTest)
void testSchedule(Test *pTest)
{
BACNET_READ_PROPERTY_DATA rpdata;
uint8_t apdu[MAX_APDU] = { 0 };
uint8_t apdu[MAX_APDU] = {0};
int len = 0;
uint32_t len_value = 0;
uint8_t tag_number = 0;
@@ -467,7 +459,6 @@ void testSchedule(Test * pTest)
return;
}
#ifdef TEST_SCHEDULE
int main(void)
@@ -482,7 +473,7 @@ int main(void)
ct_setStream(pTest, stdout);
ct_run(pTest);
(void) ct_report(pTest);
(void)ct_report(pTest);
ct_destroy(pTest);
return 0;
+385 -414
View File
File diff suppressed because it is too large Load Diff