1e889b633c
* Added Zephyr settings subsys to enable storing of BACnet values according to BACnet object property value path. * Added BACnet Basic features to enable basic samples. Refactored the zephyr BACnet profile B-SS sample to use BACnet basic subsys.
380 lines
12 KiB
C
380 lines
12 KiB
C
/**
|
|
* @file
|
|
* @brief Handle Get/Set of BACnet application encoded settings
|
|
* @date May 2024
|
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
|
* @copyright SPDX-License-Identifier: MIT
|
|
*/
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <zephyr/sys/byteorder.h>
|
|
#include <bacnet_settings/bacnet_storage.h>
|
|
#include <bacnet_settings/bacnet_settings.h>
|
|
#include "bacnet/bacdef.h"
|
|
#include "bacnet/bacapp.h"
|
|
#include "bacnet/bacdcode.h"
|
|
#include "bacnet/bacstr.h"
|
|
#include "bacnet/bacint.h"
|
|
|
|
/**
|
|
* @brief Get a BACnet SIGNED INTEGER value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param default_value [in] The default value if not found
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_value_get(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
BACNET_APPLICATION_DATA_VALUE *value)
|
|
{
|
|
uint8_t name[BACNET_STORAGE_VALUE_SIZE_MAX + 1] = { 0 };
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int stored_len, len;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
stored_len = bacnet_storage_get(&key, name, sizeof(name));
|
|
if (stored_len > 0) {
|
|
len = bacapp_decode_application_data(name, stored_len, value);
|
|
if (len <= 0) {
|
|
if (value) {
|
|
value->tag = MAX_BACNET_APPLICATION_TAG;
|
|
}
|
|
}
|
|
}
|
|
|
|
return stored_len;
|
|
}
|
|
|
|
/**
|
|
* @brief Store a BACnet SIGNED INTEGER value in non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param value [in] The value to store
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_value_set(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
BACNET_APPLICATION_DATA_VALUE *value)
|
|
{
|
|
uint8_t name[BACNET_STORAGE_VALUE_SIZE_MAX] = { 0 };
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int rc, len;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
len = bacapp_encode_application_data(NULL, value);
|
|
if (len <= 0) {
|
|
return false;
|
|
} else if (len > sizeof(name)) {
|
|
return false;
|
|
}
|
|
len = bacapp_encode_application_data(name, value);
|
|
rc = bacnet_storage_set(&key, name, len);
|
|
|
|
return rc == 0;
|
|
}
|
|
|
|
/**
|
|
* @brief Get a BACnet REAL value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param default_value [in] The default value if not found
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_real_get(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
float default_value, float *value)
|
|
{
|
|
int stored_len;
|
|
BACNET_APPLICATION_DATA_VALUE bvalue = { 0 };
|
|
|
|
stored_len =
|
|
bacnet_settings_value_get(object_type, object_instance,
|
|
property_id, array_index, &bvalue);
|
|
if ((stored_len >= 0) && (bvalue.tag == BACNET_APPLICATION_TAG_REAL)) {
|
|
if (value) {
|
|
*value = bvalue.type.Real;
|
|
}
|
|
} else {
|
|
if (value) {
|
|
*value = default_value;
|
|
}
|
|
}
|
|
|
|
return stored_len;
|
|
}
|
|
|
|
/**
|
|
* @brief Store a BACnet REAL value in non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param value [in] The value to store
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_real_set(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
float value)
|
|
{
|
|
BACNET_APPLICATION_DATA_VALUE bvalue = { 0 };
|
|
|
|
bvalue.context_specific = false;
|
|
bvalue.tag = BACNET_APPLICATION_TAG_REAL;
|
|
bvalue.type.Real = value;
|
|
|
|
return bacnet_settings_value_set(object_type, object_instance,
|
|
property_id, array_index, &bvalue);
|
|
}
|
|
|
|
/**
|
|
* @brief Get a BACnet UNSIGNED value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param default_value [in] The default value if not found
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_unsigned_get(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
BACNET_UNSIGNED_INTEGER default_value,
|
|
BACNET_UNSIGNED_INTEGER *value)
|
|
{
|
|
uint8_t name[BACNET_STORAGE_VALUE_SIZE_MAX + 1] = { 0 };
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int stored_len, len;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
stored_len = bacnet_storage_get(&key, name, sizeof(name));
|
|
if (stored_len > 0) {
|
|
len = bacnet_unsigned_application_decode(name, stored_len,
|
|
value);
|
|
if (len <= 0) {
|
|
if (value) {
|
|
*value = default_value;
|
|
}
|
|
}
|
|
} else {
|
|
if (value) {
|
|
*value = default_value;
|
|
}
|
|
}
|
|
|
|
return stored_len;
|
|
}
|
|
|
|
/**
|
|
* @brief Store a BACnet UNSIGNED value in non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param value [int] The value to store
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_unsigned_set(uint16_t object_type,
|
|
uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
BACNET_UNSIGNED_INTEGER value)
|
|
{
|
|
BACNET_APPLICATION_DATA_VALUE bvalue = { 0 };
|
|
|
|
bvalue.context_specific = false;
|
|
bvalue.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT;
|
|
bvalue.type.Unsigned_Int = value;
|
|
|
|
return bacnet_settings_value_set(object_type, object_instance,
|
|
property_id, array_index, &bvalue);
|
|
}
|
|
|
|
/**
|
|
* @brief Get a BACnet SIGNED INTEGER value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param default_value [in] The default value if not found
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_signed_get(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
int32_t default_value, int32_t *value)
|
|
{
|
|
uint8_t name[BACNET_STORAGE_VALUE_SIZE_MAX + 1] = { 0 };
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int stored_len, len;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
stored_len = bacnet_storage_get(&key, name, sizeof(name));
|
|
if (stored_len > 0) {
|
|
len = bacnet_signed_application_decode(name, stored_len, value);
|
|
if (len <= 0) {
|
|
if (value) {
|
|
*value = default_value;
|
|
}
|
|
}
|
|
} else {
|
|
if (value) {
|
|
*value = default_value;
|
|
}
|
|
}
|
|
|
|
return stored_len;
|
|
}
|
|
|
|
/**
|
|
* @brief Store a BACnet SIGNED INTEGER value in non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param array_index [in] The BACnet array index
|
|
* @param value [in] The value to store
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_signed_set(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
int32_t value)
|
|
{
|
|
BACNET_APPLICATION_DATA_VALUE bvalue = { 0 };
|
|
|
|
bvalue.context_specific = false;
|
|
bvalue.tag = BACNET_APPLICATION_TAG_SIGNED_INT;
|
|
bvalue.type.Signed_Int = value;
|
|
|
|
return bacnet_settings_value_set(object_type, object_instance,
|
|
property_id, array_index, &bvalue);
|
|
}
|
|
|
|
/**
|
|
* @brief Get a BACnet CHARACTER_STRING value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param default_value [in] The default value if not found
|
|
* @param value [out] The character string value
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_characterstring_get(uint16_t object_type,
|
|
uint32_t object_instance,
|
|
uint32_t property_id,
|
|
uint32_t array_index,
|
|
const char *default_value,
|
|
BACNET_CHARACTER_STRING *value)
|
|
{
|
|
uint8_t name[BACNET_STORAGE_VALUE_SIZE_MAX + 1] = { 0 };
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int stored_len, len;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
stored_len = bacnet_storage_get(&key, name, sizeof(name));
|
|
if (stored_len > 0) {
|
|
len = bacnet_character_string_application_decode(
|
|
name, stored_len, value);
|
|
if (len <= 0) {
|
|
characterstring_init_ansi(value, default_value);
|
|
}
|
|
} else {
|
|
characterstring_init_ansi(value, default_value);
|
|
}
|
|
|
|
return stored_len;
|
|
}
|
|
|
|
/**
|
|
* @brief Store a BACnet CHARACTER_STRING value to non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param default_value [in] The default value if not found
|
|
* @param value [out] The character string value
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_characterstring_ansi_set(uint16_t object_type,
|
|
uint32_t object_instance,
|
|
uint32_t property_id,
|
|
uint32_t array_index,
|
|
const char *cstring)
|
|
{
|
|
BACNET_APPLICATION_DATA_VALUE bvalue = { 0 };
|
|
bool status;
|
|
|
|
bvalue.context_specific = false;
|
|
bvalue.tag = BACNET_APPLICATION_TAG_CHARACTER_STRING;
|
|
status = characterstring_init_ansi(&bvalue.type.Character_String,
|
|
cstring);
|
|
if (!status) {
|
|
status = bacnet_settings_value_set(object_type, object_instance,
|
|
property_id, array_index,
|
|
&bvalue);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/**
|
|
* @brief Get a C-string value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param default_value [in] The default value if not found
|
|
* @param value [out] The string value
|
|
* @param value_size [in] The size of the string value
|
|
* @return stored data length on success 0..N, negative on failure.
|
|
*/
|
|
int bacnet_settings_string_get(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
const char *default_value, char *value,
|
|
size_t value_size)
|
|
{
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int rc;
|
|
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
rc = bacnet_storage_get(&key, value, value_size);
|
|
if (rc <= 0) {
|
|
if (default_value) {
|
|
strncpy(value, default_value, value_size);
|
|
rc = strlen(default_value);
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* @brief Get a C-string value from non-volatile storage
|
|
* @param object_type [in] The BACnet object type
|
|
* @param object_instance [in] The BACnet object instance
|
|
* @param property_id [in] The BACnet property id
|
|
* @param default_value [in] The default value if not found
|
|
* @param value [in] The character string value
|
|
* @return true on success, false on failure.
|
|
*/
|
|
bool bacnet_settings_string_set(uint16_t object_type, uint32_t object_instance,
|
|
uint32_t property_id, uint32_t array_index,
|
|
const char *value)
|
|
{
|
|
BACNET_STORAGE_KEY key = { 0 };
|
|
int rc;
|
|
|
|
if (!value) {
|
|
return false;
|
|
}
|
|
bacnet_storage_key_init(&key, object_type, object_instance, property_id,
|
|
array_index);
|
|
rc = bacnet_storage_set(&key, (const char *)value, strlen(value) + 1);
|
|
|
|
return rc == 0;
|
|
}
|