Secured BACnetTimeValue codec, and improved unit test coverage. (#648)
* Secured BACnetTimeValue codec, and improved unit test coverage.
This commit is contained in:
+54
-90
@@ -1,37 +1,11 @@
|
|||||||
/*####COPYRIGHTBEGIN####
|
/**
|
||||||
-------------------------------------------
|
* @file
|
||||||
Copyright (C) 2015 Nikola Jelic
|
* @brief BACnetTimeValue complex data type encode and decode
|
||||||
|
* @author Nikola Jelic <nikola.jelic@euroicc.com>
|
||||||
This program is free software; you can redistribute it and/or
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
modify it under the terms of the GNU General Public License
|
* @date 2015
|
||||||
as published by the Free Software Foundation; either version 2
|
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||||
of the License, or (at your option) any later version.
|
*/
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
The Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
As a special exception, if other files instantiate templates or
|
|
||||||
use macros or inline functions from this file, or you compile
|
|
||||||
this file and link it with other works to produce a work based
|
|
||||||
on this file, this file does not by itself cause the resulting
|
|
||||||
work to be covered by the GNU General Public License. However
|
|
||||||
the source code for this file must still be made available in
|
|
||||||
accordance with section (3) of the GNU General Public License.
|
|
||||||
|
|
||||||
This exception does not invalidate any other reasons why a work
|
|
||||||
based on this file might be covered by the GNU General Public
|
|
||||||
License.
|
|
||||||
-------------------------------------------
|
|
||||||
####COPYRIGHTEND####*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h> /* memcpy */
|
#include <string.h> /* memcpy */
|
||||||
@@ -95,24 +69,18 @@ int bacnet_time_value_encode(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
uint8_t *apdu_offset = NULL;
|
BACNET_APPLICATION_DATA_VALUE data;
|
||||||
BACNET_APPLICATION_DATA_VALUE adv;
|
|
||||||
|
|
||||||
if (!value || !is_data_value_schedule_compatible(value->Value.tag)) {
|
if (!value || !is_data_value_schedule_compatible(value->Value.tag)) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
len = encode_application_time(apdu, &value->Time);
|
||||||
if (apdu) {
|
|
||||||
apdu_offset = &apdu[apdu_len];
|
|
||||||
}
|
|
||||||
len = encode_application_time(apdu_offset, &value->Time);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
if (apdu) {
|
if (apdu) {
|
||||||
apdu_offset = &apdu[apdu_len];
|
apdu += len;
|
||||||
}
|
}
|
||||||
bacnet_primitive_to_application_data_value(&adv, &value->Value);
|
bacnet_primitive_to_application_data_value(&data, &value->Value);
|
||||||
len = bacapp_encode_application_data(apdu_offset, &adv);
|
len = bacapp_encode_application_data(apdu, &data);
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
@@ -136,24 +104,18 @@ int bacnet_time_value_context_encode(
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
uint8_t *apdu_offset = NULL;
|
|
||||||
|
|
||||||
if (apdu) {
|
len = encode_opening_tag(apdu, tag_number);
|
||||||
apdu_offset = &apdu[apdu_len];
|
|
||||||
}
|
|
||||||
len = encode_opening_tag(apdu_offset, tag_number);
|
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
if (apdu) {
|
if (apdu) {
|
||||||
apdu_offset = &apdu[apdu_len];
|
apdu += len;
|
||||||
}
|
}
|
||||||
len = bacnet_time_value_encode(apdu_offset, value);
|
len = bacnet_time_value_encode(apdu, value);
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
if (apdu) {
|
if (apdu) {
|
||||||
apdu_offset = &apdu[apdu_len];
|
apdu += len;
|
||||||
}
|
}
|
||||||
len = encode_closing_tag(apdu_offset, tag_number);
|
len = encode_closing_tag(apdu, tag_number);
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
@@ -182,6 +144,7 @@ int bacnet_application_to_primitive_data_value(
|
|||||||
memset(dest, 0, sizeof(struct BACnet_Primitive_Data_Value));
|
memset(dest, 0, sizeof(struct BACnet_Primitive_Data_Value));
|
||||||
dest->tag = src->tag;
|
dest->tag = src->tag;
|
||||||
memcpy(&dest->type, &src->type, sizeof(dest->type));
|
memcpy(&dest->type, &src->type, sizeof(dest->type));
|
||||||
|
|
||||||
return BACNET_STATUS_OK;
|
return BACNET_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +165,7 @@ int bacnet_primitive_to_application_data_value(
|
|||||||
memset(dest, 0, sizeof(struct BACnet_Application_Data_Value));
|
memset(dest, 0, sizeof(struct BACnet_Application_Data_Value));
|
||||||
dest->tag = src->tag;
|
dest->tag = src->tag;
|
||||||
memcpy(&dest->type, &src->type, sizeof(src->type));
|
memcpy(&dest->type, &src->type, sizeof(src->type));
|
||||||
|
|
||||||
return BACNET_STATUS_OK;
|
return BACNET_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,26 +173,26 @@ int bacnet_primitive_to_application_data_value(
|
|||||||
* @brief decode a BACnetTimeValue
|
* @brief decode a BACnetTimeValue
|
||||||
*
|
*
|
||||||
* @param apdu - buffer of data to be decoded
|
* @param apdu - buffer of data to be decoded
|
||||||
* @param max_apdu_len - number of bytes in the buffer
|
* @param apdu_size - number of bytes in the buffer
|
||||||
* @param value - stores the decoded property value
|
* @param value - stores the decoded property value
|
||||||
* @return number of bytes decoded, or BACNET_STATUS_ERROR if errors occur
|
* @return number of bytes decoded, or BACNET_STATUS_ERROR if errors occur
|
||||||
*/
|
*/
|
||||||
int bacnet_time_value_decode(
|
int bacnet_time_value_decode(
|
||||||
uint8_t *apdu, int max_apdu_len, BACNET_TIME_VALUE *value)
|
uint8_t *apdu, int apdu_size, BACNET_TIME_VALUE *value)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
BACNET_APPLICATION_DATA_VALUE full_data_value = { 0 };
|
BACNET_APPLICATION_DATA_VALUE full_data_value = { 0 };
|
||||||
|
|
||||||
len = bacnet_time_application_decode(
|
len = bacnet_time_application_decode(
|
||||||
&apdu[apdu_len], max_apdu_len, &value->Time);
|
&apdu[apdu_len], apdu_size, &value->Time);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
|
||||||
len = bacapp_decode_application_data(
|
len = bacapp_decode_application_data(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, &full_data_value);
|
&apdu[apdu_len], apdu_size - apdu_len, &full_data_value);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -250,34 +214,32 @@ int bacapp_decode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
|||||||
/**
|
/**
|
||||||
* @brief decode a context encoded BACnetTimeValue
|
* @brief decode a context encoded BACnetTimeValue
|
||||||
* @param apdu - buffer of data to be decoded
|
* @param apdu - buffer of data to be decoded
|
||||||
* @param max_apdu_len - number of bytes in the buffer
|
* @param apdu_size - number of bytes in the buffer
|
||||||
* @param tag_number - context tag number to match
|
* @param tag_number - context tag number to match
|
||||||
* @param value - stores the decoded property value
|
* @param value - stores the decoded property value
|
||||||
* @return number of bytes decoded, or BACNET_STATUS_ERROR if an error occurs
|
* @return number of bytes decoded, or BACNET_STATUS_ERROR if an error occurs
|
||||||
*/
|
*/
|
||||||
int bacnet_time_value_context_decode(uint8_t *apdu,
|
int bacnet_time_value_context_decode(
|
||||||
int max_apdu_len,
|
uint8_t *apdu, int apdu_size, uint8_t tag_number, BACNET_TIME_VALUE *value)
|
||||||
uint8_t tag_number,
|
|
||||||
BACNET_TIME_VALUE *value)
|
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
|
|
||||||
if (bacnet_is_opening_tag_number(
|
if (bacnet_is_opening_tag_number(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, tag_number, &len)) {
|
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
len = bacnet_time_value_decode(
|
len =
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, value);
|
bacnet_time_value_decode(&apdu[apdu_len], apdu_size - apdu_len, value);
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
if (bacnet_is_closing_tag_number(
|
if (bacnet_is_closing_tag_number(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, tag_number, &len)) {
|
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
} else {
|
} else {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
@@ -295,14 +257,15 @@ int bacapp_decode_context_time_value(
|
|||||||
/**
|
/**
|
||||||
* @brief decode a context encoded list of BACnetTimeValue
|
* @brief decode a context encoded list of BACnetTimeValue
|
||||||
* @param apdu - buffer of data to be decoded
|
* @param apdu - buffer of data to be decoded
|
||||||
* @param max_apdu_len - number of bytes in the buffer
|
* @param apdu_size - number of bytes in the buffer
|
||||||
* @param tag_number - context tag number to match
|
* @param tag_number - context tag number to match
|
||||||
* @param time_values - stores the decoded property values
|
* @param time_values - stores the decoded property values
|
||||||
* @param max_time_values - number of values to be able to store
|
* @param max_time_values - number of values to be able to store
|
||||||
* @return number of bytes decoded, or BACNET_STATUS_ERROR if an error occurs
|
* @return number of bytes decoded, or BACNET_STATUS_ERROR if an error occurs
|
||||||
*/
|
*/
|
||||||
int bacnet_time_values_context_decode(uint8_t *apdu,
|
int bacnet_time_values_context_decode(
|
||||||
const int max_apdu_len,
|
uint8_t *apdu,
|
||||||
|
const int apdu_size,
|
||||||
const uint8_t tag_number,
|
const uint8_t tag_number,
|
||||||
BACNET_TIME_VALUE *time_values,
|
BACNET_TIME_VALUE *time_values,
|
||||||
const unsigned int max_time_values,
|
const unsigned int max_time_values,
|
||||||
@@ -316,16 +279,17 @@ int bacnet_time_values_context_decode(uint8_t *apdu,
|
|||||||
|
|
||||||
/* day-schedule [0] SEQUENCE OF BACnetTimeValue */
|
/* day-schedule [0] SEQUENCE OF BACnetTimeValue */
|
||||||
if (bacnet_is_opening_tag_number(
|
if (bacnet_is_opening_tag_number(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, tag_number, &len)) {
|
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
while (!bacnet_is_closing_tag_number(
|
while (!bacnet_is_closing_tag_number(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, tag_number, &len)) {
|
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
|
||||||
if (count_values < max_time_values) {
|
if (count_values < max_time_values) {
|
||||||
len = bacnet_time_value_decode(&apdu[apdu_len],
|
len = bacnet_time_value_decode(
|
||||||
max_apdu_len - apdu_len, &time_values[count_values++]);
|
&apdu[apdu_len], apdu_size - apdu_len,
|
||||||
|
&time_values[count_values++]);
|
||||||
} else {
|
} else {
|
||||||
len = bacnet_time_value_decode(
|
len = bacnet_time_value_decode(
|
||||||
&apdu[apdu_len], max_apdu_len - apdu_len, &dummy);
|
&apdu[apdu_len], apdu_size - apdu_len, &dummy);
|
||||||
}
|
}
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
@@ -365,7 +329,8 @@ int bacnet_time_values_context_decode(uint8_t *apdu,
|
|||||||
* @param value - value to be encoded
|
* @param value - value to be encoded
|
||||||
* @return the number of apdu bytes encoded, or BACNET_STATUS_ERROR
|
* @return the number of apdu bytes encoded, or BACNET_STATUS_ERROR
|
||||||
*/
|
*/
|
||||||
int bacnet_time_values_context_encode(uint8_t *apdu,
|
int bacnet_time_values_context_encode(
|
||||||
|
uint8_t *apdu,
|
||||||
uint8_t tag_number,
|
uint8_t tag_number,
|
||||||
BACNET_TIME_VALUE *time_values,
|
BACNET_TIME_VALUE *time_values,
|
||||||
unsigned int max_time_values)
|
unsigned int max_time_values)
|
||||||
@@ -374,31 +339,30 @@ int bacnet_time_values_context_encode(uint8_t *apdu,
|
|||||||
int apdu_len = 0;
|
int apdu_len = 0;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
BACNET_TIME t0 = { 0 };
|
BACNET_TIME t0 = { 0 };
|
||||||
uint8_t *apdu_offset = NULL;
|
|
||||||
|
|
||||||
/* day-schedule [x] SEQUENCE OF BACnetTimeValue */
|
/* day-schedule [x] SEQUENCE OF BACnetTimeValue */
|
||||||
|
len = encode_opening_tag(apdu, tag_number);
|
||||||
|
apdu_len += len;
|
||||||
if (apdu) {
|
if (apdu) {
|
||||||
apdu_offset = &apdu[apdu_len];
|
apdu += len;
|
||||||
}
|
}
|
||||||
apdu_len += encode_opening_tag(apdu_offset, tag_number);
|
for (j = 0; j < max_time_values; j++) {
|
||||||
for (j = 0; j < max_time_values; j++)
|
|
||||||
/* Encode only non-null values (NULL,00:00:00.00) */
|
/* Encode only non-null values (NULL,00:00:00.00) */
|
||||||
if (time_values[j].Value.tag != BACNET_APPLICATION_TAG_NULL ||
|
if (time_values[j].Value.tag != BACNET_APPLICATION_TAG_NULL ||
|
||||||
datetime_compare_time(&t0, &time_values[j].Time) != 0) {
|
datetime_compare_time(&t0, &time_values[j].Time) != 0) {
|
||||||
if (apdu) {
|
len = bacnet_time_value_encode(apdu, &time_values[j]);
|
||||||
apdu_offset = &apdu[apdu_len];
|
|
||||||
}
|
|
||||||
len = bacnet_time_value_encode(apdu_offset, &time_values[j]);
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return BACNET_STATUS_ERROR;
|
return BACNET_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
apdu_len += len;
|
apdu_len += len;
|
||||||
|
if (apdu) {
|
||||||
|
apdu += len;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* close tag */
|
|
||||||
if (apdu) {
|
|
||||||
apdu_offset = &apdu[apdu_len];
|
|
||||||
}
|
}
|
||||||
apdu_len += encode_closing_tag(apdu_offset, tag_number);
|
/* close tag */
|
||||||
|
len = encode_closing_tag(apdu, tag_number);
|
||||||
|
apdu_len += len;
|
||||||
|
|
||||||
return apdu_len;
|
return apdu_len;
|
||||||
}
|
}
|
||||||
|
|||||||
+47
-38
@@ -1,56 +1,65 @@
|
|||||||
/*####COPYRIGHTBEGIN####
|
/**
|
||||||
-------------------------------------------
|
* @file
|
||||||
Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
* @brief BACnetDailySchedule complex data type encode and decode
|
||||||
|
* @author Ondřej Hruška <ondra@ondrovo.com>
|
||||||
This program is free software; you can redistribute it and/or
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
modify it under the terms of the GNU General Public License
|
* @date February 2024
|
||||||
as published by the Free Software Foundation; either version 2
|
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||||
of the License, or (at your option) any later version.
|
*/
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to:
|
|
||||||
The Free Software Foundation, Inc.
|
|
||||||
59 Temple Place - Suite 330
|
|
||||||
Boston, MA 02111-1307, USA.
|
|
||||||
|
|
||||||
As a special exception, if other files instantiate templates or
|
|
||||||
use macros or inline functions from this file, or you compile
|
|
||||||
this file and link it with other works to produce a work based
|
|
||||||
on this file, this file does not by itself cause the resulting
|
|
||||||
work to be covered by the GNU General Public License. However
|
|
||||||
the source code for this file must still be made available in
|
|
||||||
accordance with section (3) of the GNU General Public License.
|
|
||||||
|
|
||||||
This exception does not invalidate any other reasons why a work
|
|
||||||
based on this file might be covered by the GNU General Public
|
|
||||||
License.
|
|
||||||
-------------------------------------------
|
|
||||||
####COPYRIGHTEND####*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bacnet/dailyschedule.h"
|
#include "bacnet/dailyschedule.h"
|
||||||
#include "bacnet/bactimevalue.h"
|
#include "bacnet/bactimevalue.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encode a BACnetDailySchedule value to a buffer
|
||||||
|
* @param apdu [out] Buffer to encode to
|
||||||
|
* @param apdu_size [in] Size of the buffer
|
||||||
|
* @param tag_number [in] Tag number to use
|
||||||
|
* @param day [in] Value to encode
|
||||||
|
* @return Number of bytes encoded, or BACNET_STATUS_ERROR if an error occurs
|
||||||
|
*/
|
||||||
int bacnet_dailyschedule_context_decode(uint8_t *apdu,
|
int bacnet_dailyschedule_context_decode(uint8_t *apdu,
|
||||||
int max_apdu_len,
|
int apdu_size,
|
||||||
uint8_t tag_number,
|
uint8_t tag_number,
|
||||||
BACNET_DAILY_SCHEDULE *day)
|
BACNET_DAILY_SCHEDULE *day)
|
||||||
{
|
{
|
||||||
unsigned int tv_count = 0;
|
unsigned int tv_count = 0;
|
||||||
int retval = bacnet_time_values_context_decode(apdu, max_apdu_len,
|
int len = 0;
|
||||||
tag_number, &day->Time_Values[0], MAX_DAY_SCHEDULE_VALUES, &tv_count);
|
|
||||||
|
if (day == NULL) {
|
||||||
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
if (apdu == NULL) {
|
||||||
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
len = bacnet_time_values_context_decode(apdu, apdu_size,
|
||||||
|
tag_number, &day->Time_Values[0], ARRAY_SIZE(day->Time_Values),
|
||||||
|
&tv_count);
|
||||||
|
if (len < 0) {
|
||||||
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
day->TV_Count = (uint16_t)tv_count;
|
day->TV_Count = (uint16_t)tv_count;
|
||||||
return retval;
|
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encode a BACnetDailySchedule value to a buffer
|
||||||
|
* @param apdu [out] Buffer to encode to
|
||||||
|
* @param tag_number [in] Tag number to use
|
||||||
|
* @param day [in] Value to encode
|
||||||
|
* @return Number of bytes encoded, or BACNET_STATUS_ERROR if an error occurs
|
||||||
|
*/
|
||||||
int bacnet_dailyschedule_context_encode(
|
int bacnet_dailyschedule_context_encode(
|
||||||
uint8_t *apdu, uint8_t tag_number, BACNET_DAILY_SCHEDULE *day)
|
uint8_t *apdu, uint8_t tag_number, BACNET_DAILY_SCHEDULE *day)
|
||||||
{
|
{
|
||||||
|
if (day == NULL) {
|
||||||
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
if (day->TV_Count > ARRAY_SIZE(day->Time_Values)) {
|
||||||
|
return BACNET_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
return bacnet_time_values_context_encode(
|
return bacnet_time_values_context_encode(
|
||||||
apdu, tag_number, &day->Time_Values[0], day->TV_Count);
|
apdu, tag_number, &day->Time_Values[0], day->TV_Count);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@
|
|||||||
* @author Ondřej Hruška <ondra@ondrovo.com>
|
* @author Ondřej Hruška <ondra@ondrovo.com>
|
||||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
* @date May 2022
|
* @date May 2022
|
||||||
* @section LICENSE
|
* @copyright SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ add_compile_definitions(
|
|||||||
BIG_ENDIAN=0
|
BIG_ENDIAN=0
|
||||||
CONFIG_ZTEST=1
|
CONFIG_ZTEST=1
|
||||||
BACAPP_ALL
|
BACAPP_ALL
|
||||||
|
BACAPP_PRINT_ENABLED
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
|||||||
@@ -2,11 +2,10 @@
|
|||||||
* @file
|
* @file
|
||||||
* @brief Unit test for BACnetTimeValue
|
* @brief Unit test for BACnetTimeValue
|
||||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||||
|
* @author Greg Shue <greg.shue@outlook.com>
|
||||||
* @date June 2022
|
* @date June 2022
|
||||||
*
|
* @copyright SPDX-License-Identifier: MIT
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -28,14 +27,16 @@
|
|||||||
*/
|
*/
|
||||||
static void test_BACnetTimeValue(BACNET_TIME_VALUE *value)
|
static void test_BACnetTimeValue(BACNET_TIME_VALUE *value)
|
||||||
{
|
{
|
||||||
int len, apdu_len;
|
int len, apdu_len, null_len = 0;
|
||||||
uint8_t apdu[MAX_APDU] = { 0 };
|
uint8_t apdu[MAX_APDU] = { 0 };
|
||||||
BACNET_TIME_VALUE test_value = { 0 };
|
BACNET_TIME_VALUE test_value = { 0 };
|
||||||
int diff = 0;
|
int diff = 0;
|
||||||
bool status = false;
|
bool status = false;
|
||||||
uint8_t tag_number = 0;
|
uint8_t tag_number = 0;
|
||||||
|
|
||||||
|
null_len = bacnet_time_value_encode(NULL, value);
|
||||||
len = bacnet_time_value_encode(apdu, value);
|
len = bacnet_time_value_encode(apdu, value);
|
||||||
|
zassert_equal(len, null_len, NULL);
|
||||||
apdu_len = bacnet_time_value_decode(apdu, len, &test_value);
|
apdu_len = bacnet_time_value_decode(apdu, len, &test_value);
|
||||||
zassert_true(len > 0, NULL);
|
zassert_true(len > 0, NULL);
|
||||||
zassert_true(apdu_len > 0, NULL);
|
zassert_true(apdu_len > 0, NULL);
|
||||||
@@ -45,8 +46,15 @@ static void test_BACnetTimeValue(BACNET_TIME_VALUE *value)
|
|||||||
(BACNET_APPLICATION_DATA_VALUE *)&test_value.Value,
|
(BACNET_APPLICATION_DATA_VALUE *)&test_value.Value,
|
||||||
(BACNET_APPLICATION_DATA_VALUE *)&value->Value);
|
(BACNET_APPLICATION_DATA_VALUE *)&value->Value);
|
||||||
zassert_true(status, NULL);
|
zassert_true(status, NULL);
|
||||||
|
/* apdu too short testing */
|
||||||
|
while (--apdu_len) {
|
||||||
|
len = bacnet_time_value_decode(apdu, apdu_len, &test_value);
|
||||||
|
zassert_true(len < 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
len = bacnet_time_value_context_encode(apdu, tag_number, value);
|
len = bacnet_time_value_context_encode(apdu, tag_number, value);
|
||||||
|
null_len = bacnet_time_value_context_encode(NULL,tag_number, value);
|
||||||
|
zassert_equal(len, null_len, NULL);
|
||||||
apdu_len =
|
apdu_len =
|
||||||
bacnet_time_value_context_decode(apdu, len, tag_number, &test_value);
|
bacnet_time_value_context_decode(apdu, len, tag_number, &test_value);
|
||||||
zassert_true(len > 0, NULL);
|
zassert_true(len > 0, NULL);
|
||||||
@@ -57,6 +65,11 @@ static void test_BACnetTimeValue(BACNET_TIME_VALUE *value)
|
|||||||
(BACNET_APPLICATION_DATA_VALUE *)&test_value.Value,
|
(BACNET_APPLICATION_DATA_VALUE *)&test_value.Value,
|
||||||
(BACNET_APPLICATION_DATA_VALUE *)&value->Value);
|
(BACNET_APPLICATION_DATA_VALUE *)&value->Value);
|
||||||
zassert_true(status, NULL);
|
zassert_true(status, NULL);
|
||||||
|
/* apdu too short testing */
|
||||||
|
while (--apdu_len) {
|
||||||
|
len = bacnet_time_value_context_decode(apdu, apdu_len, tag_number, &test_value);
|
||||||
|
zassert_true(len < 0, NULL);
|
||||||
|
}
|
||||||
/* negative testing */
|
/* negative testing */
|
||||||
tag_number++;
|
tag_number++;
|
||||||
apdu_len =
|
apdu_len =
|
||||||
@@ -73,17 +86,91 @@ ZTEST(BACnetTimeValue_tests, test_BACnetTimeValues)
|
|||||||
static void test_BACnetTimeValues(void)
|
static void test_BACnetTimeValues(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||||
BACNET_TIME_VALUE time_value = { 0 };
|
BACNET_TIME_VALUE time_value = { 0 };
|
||||||
|
int rc = BACNET_STATUS_OK;
|
||||||
|
bool status = false;
|
||||||
|
|
||||||
test_BACnetTimeValue(&time_value);
|
test_BACnetTimeValue(&time_value);
|
||||||
bacapp_parse_application_data(
|
|
||||||
BACNET_APPLICATION_TAG_REAL, "4.2", &time_value.Value);
|
status = bacapp_parse_application_data(
|
||||||
datetime_time_init_ascii(&time_value.Time, "12:00");
|
BACNET_APPLICATION_TAG_BOOLEAN, "active", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
datetime_time_init_ascii(&time_value.Time, "00:00.01");
|
||||||
test_BACnetTimeValue(&time_value);
|
test_BACnetTimeValue(&time_value);
|
||||||
bacapp_parse_application_data(
|
|
||||||
BACNET_APPLICATION_TAG_UNSIGNED_INT, "99999", &time_value.Value);
|
status = bacapp_parse_application_data(
|
||||||
datetime_time_init_ascii(&time_value.Time, "23:59:59");
|
BACNET_APPLICATION_TAG_UNSIGNED_INT, "99999", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
status = datetime_time_init_ascii(&time_value.Time, "23:59:59");
|
||||||
|
zassert_true(status, NULL);
|
||||||
test_BACnetTimeValue(&time_value);
|
test_BACnetTimeValue(&time_value);
|
||||||
|
|
||||||
|
status = bacapp_parse_application_data(
|
||||||
|
BACNET_APPLICATION_TAG_SIGNED_INT, "-42", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
status = datetime_time_init_ascii(&time_value.Time, "13:00:59.99");
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_BACnetTimeValue(&time_value);
|
||||||
|
|
||||||
|
status = bacapp_parse_application_data(
|
||||||
|
BACNET_APPLICATION_TAG_REAL, "4.2", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
status = datetime_time_init_ascii(&time_value.Time, "12:00");
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_BACnetTimeValue(&time_value);
|
||||||
|
|
||||||
|
status = bacapp_parse_application_data(
|
||||||
|
BACNET_APPLICATION_TAG_DOUBLE, "3.141593", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
status = datetime_time_init_ascii(&time_value.Time, "3:14.15.93");
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_BACnetTimeValue(&time_value);
|
||||||
|
|
||||||
|
status = bacapp_parse_application_data(
|
||||||
|
BACNET_APPLICATION_TAG_ENUMERATED, "42", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_OK, NULL);
|
||||||
|
status = datetime_time_init_ascii(&time_value.Time, "8:00.00.00");
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
test_BACnetTimeValue(&time_value);
|
||||||
|
|
||||||
|
status = bacapp_parse_application_data(
|
||||||
|
BACNET_APPLICATION_TAG_OBJECT_ID, "8:4194303", &value);
|
||||||
|
zassert_true(status, NULL);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_ERROR ,"rc=%d", rc);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(NULL, &value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_ERROR ,"rc=%d", rc);
|
||||||
|
rc = bacnet_application_to_primitive_data_value(&time_value.Value, NULL);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_ERROR ,"rc=%d", rc);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(NULL, &time_value.Value);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_ERROR, NULL);
|
||||||
|
rc = bacnet_primitive_to_application_data_value(&value, NULL);
|
||||||
|
zassert_equal(rc, BACNET_STATUS_ERROR, NULL);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* @brief Unit test for BACnetSpecialEvent. This test also indirectly tests
|
* @brief Unit test for BACnetSpecialEvent. This test also indirectly tests
|
||||||
* BACnetCalendarEntry
|
* BACnetCalendarEntry, BACnetDailySchedule, and BACnetTimeValue.
|
||||||
* @author Ondřej Hruška <ondra@ondrovo.com>
|
* @author Ondřej Hruška <ondra@ondrovo.com>
|
||||||
* @date Aug 2023
|
* @date Aug 2023
|
||||||
*
|
* @copyright SPDX-License-Identifier: MIT
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user