Feature/basic-program-object (#940)

* Added basic Program object and unit test.

* Integrate the basic Program object with example applications.
This commit is contained in:
Steve Karg
2025-03-13 15:51:37 -05:00
committed by GitHub
parent 4ee129e249
commit 4df896b820
17 changed files with 1442 additions and 16 deletions
+2
View File
@@ -389,6 +389,8 @@ add_library(${PROJECT_NAME}
src/bacnet/basic/object/osv.h
src/bacnet/basic/object/piv.c
src/bacnet/basic/object/piv.h
src/bacnet/basic/object/program.c
src/bacnet/basic/object/program.h
src/bacnet/basic/object/schedule.c
src/bacnet/basic/object/schedule.h
src/bacnet/basic/object/structured_view.c
+1
View File
@@ -36,6 +36,7 @@ BACNET_OBJECT_SRC := \
$(BACNET_OBJECT_DIR)/msv.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/piv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/time_value.c \
+1
View File
@@ -37,6 +37,7 @@ SRC = main.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/structured_view.c \
$(BACNET_OBJECT_DIR)/time_value.c
+1
View File
@@ -30,6 +30,7 @@ SRC = main.c \
$(BACNET_OBJECT_DIR)/msv.c \
$(BACNET_OBJECT_DIR)/osv.c \
$(BACNET_OBJECT_DIR)/piv.c \
$(BACNET_OBJECT_DIR)/program.c \
$(BACNET_OBJECT_DIR)/nc.c \
$(BACNET_OBJECT_DIR)/netport.c \
$(BACNET_OBJECT_DIR)/time_value.c \
@@ -197,6 +197,7 @@
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\nc.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\osv.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\piv.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\program.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\schedule.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\structured_view.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\time_value.c" />
@@ -81,6 +81,9 @@
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\piv.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\program.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\schedule.c">
<Filter>Source Files</Filter>
</ClCompile>
@@ -76,6 +76,7 @@
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\objects.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\osv.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\piv.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\program.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\schedule.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\structured_view.c" />
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\trendlog.c" />
@@ -384,6 +384,9 @@
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\piv.c">
<Filter>Source Files\src\bacnet\basic\object</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\program.c">
<Filter>Source Files\src\bacnet\basic\object</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\src\bacnet\basic\object\schedule.c">
<Filter>Source Files\src\bacnet\basic\object</Filter>
</ClCompile>
+8 -9
View File
@@ -1088,7 +1088,7 @@ typedef enum {
MAX_POLARITY = 2
} BACNET_POLARITY;
typedef enum {
typedef enum BACnetProgramRequest {
PROGRAM_REQUEST_READY = 0,
PROGRAM_REQUEST_LOAD = 1,
PROGRAM_REQUEST_RUN = 2,
@@ -1097,7 +1097,7 @@ typedef enum {
PROGRAM_REQUEST_UNLOAD = 5
} BACNET_PROGRAM_REQUEST;
typedef enum {
typedef enum BACnetProgramState {
PROGRAM_STATE_IDLE = 0,
PROGRAM_STATE_LOADING = 1,
PROGRAM_STATE_RUNNING = 2,
@@ -1106,18 +1106,17 @@ typedef enum {
PROGRAM_STATE_UNLOADING = 5
} BACNET_PROGRAM_STATE;
typedef enum {
typedef enum BACnetProgramError {
PROGRAM_ERROR_NORMAL = 0,
PROGRAM_ERROR_LOAD_FAILED = 1,
PROGRAM_ERROR_INTERNAL = 2,
PROGRAM_ERROR_PROGRAM = 3,
PROGRAM_ERROR_OTHER = 4,
/* Enumerated values 0-63 are reserved for definition by ASHRAE. */
/* Enumerated values 64-65535 may be used by others subject to */
/* the procedures and constraints described in Clause 23. */
/* do the max range inside of enum so that
compilers will allocate adequate sized datatype for enum
which is used to store decoding */
PROGRAM_ERROR_RESERVED_MIN = 5,
PROGRAM_ERROR_RESERVED_MAX = 63,
/* Enumerated values 0-63 are reserved for definition by ASHRAE.
Enumerated values 64-65535 may be used by others subject
to the procedures and constraints described in Clause 23. */
PROGRAM_ERROR_PROPRIETARY_MIN = 64,
PROGRAM_ERROR_PROPRIETARY_MAX = 65535
} BACNET_PROGRAM_ERROR;
+17 -7
View File
@@ -37,6 +37,7 @@
#include "bacnet/basic/object/bv.h"
#include "bacnet/basic/object/calendar.h"
#include "bacnet/basic/object/command.h"
#include "bacnet/basic/object/program.h"
#include "bacnet/basic/object/lc.h"
#include "bacnet/basic/object/lsp.h"
#include "bacnet/basic/object/lsz.h"
@@ -64,6 +65,7 @@
#include "bacnet/basic/object/netport.h"
#include "bacnet/basic/object/color_object.h"
#include "bacnet/basic/object/color_temperature.h"
#include "bacnet/basic/object/program.h"
/* external prototypes */
extern int Routed_Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata);
@@ -215,13 +217,13 @@ static object_functions_t My_Object_Table[] = {
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Integer_Value_Create, Integer_Value_Delete, NULL /* Timer */ },
#endif
{ OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance,
Command_Valid_Instance, Command_Object_Name, Command_Read_Property,
Command_Write_Property, Command_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_COMMAND, Command_Init, Command_Count, Command_Index_To_Instance,
Command_Valid_Instance, Command_Object_Name, Command_Read_Property,
Command_Write_Property, Command_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
#if defined(INTRINSIC_REPORTING)
{ OBJECT_NOTIFICATION_CLASS, Notification_Class_Init,
Notification_Class_Count, Notification_Class_Index_To_Instance,
@@ -376,6 +378,14 @@ static object_functions_t My_Object_Table[] = {
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
{ OBJECT_PROGRAM, Program_Init, Program_Count,
Program_Index_To_Instance, Program_Valid_Instance,
Program_Object_Name, Program_Read_Property,
Program_Write_Property, Program_Property_Lists,
NULL /* ReadRangeInfo */, NULL /* Iterator */, NULL /* Value_Lists */,
NULL /* COV */, NULL /* COV Clear */, NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
Program_Create, Program_Delete, Program_Timer },
{ MAX_BACNET_OBJECT_TYPE, NULL /* Init */, NULL /* Count */,
NULL /* Index_To_Instance */, NULL /* Valid_Instance */,
NULL /* Object_Name */, NULL /* Read_Property */,
File diff suppressed because it is too large Load Diff
+134
View File
@@ -0,0 +1,134 @@
/**
* @file
* @brief API for Program object type
* @author Steve Karg <skarg@users.sourceforge.net>
* @date March 2025
* @copyright SPDX-License-Identifier: MIT
*/
#ifndef BACNET_BASIC_OBJECT_PROGRAM_H
#define BACNET_BASIC_OBJECT_PROGRAM_H
#include <stdbool.h>
#include <stdint.h>
/* BACnet Stack defines - first */
#include "bacnet/bacdef.h"
/* BACnet Stack API */
#include "bacnet/bacerror.h"
#include "bacnet/wp.h"
#include "bacnet/rp.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
BACNET_STACK_EXPORT
void Program_Property_Lists(
const int **pRequired, const int **pOptional, const int **pProprietary);
BACNET_STACK_EXPORT
bool Program_Valid_Instance(uint32_t object_instance);
BACNET_STACK_EXPORT
unsigned Program_Count(void);
BACNET_STACK_EXPORT
uint32_t Program_Index_To_Instance(unsigned index);
BACNET_STACK_EXPORT
unsigned Program_Instance_To_Index(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Object_Name(
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name);
BACNET_STACK_EXPORT
bool Program_Name_Set(uint32_t object_instance, const char *new_name);
BACNET_STACK_EXPORT
const char *Program_Name_ASCII(uint32_t object_instance);
BACNET_STACK_EXPORT
int Program_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata);
BACNET_STACK_EXPORT
bool Program_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data);
BACNET_STACK_EXPORT
BACNET_PROGRAM_STATE Program_State(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_State_Set(uint32_t object_instance, BACNET_PROGRAM_STATE value);
BACNET_STACK_EXPORT
BACNET_PROGRAM_REQUEST Program_Change(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Change_Set(
uint32_t object_instance, BACNET_PROGRAM_REQUEST program_change);
BACNET_STACK_EXPORT
BACNET_PROGRAM_ERROR Program_Reason_For_Halt(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Reason_For_Halt_Set(
uint32_t object_instance, BACNET_PROGRAM_ERROR reason);
BACNET_STACK_EXPORT
bool Program_Description(
uint32_t object_instance, BACNET_CHARACTER_STRING *description);
BACNET_STACK_EXPORT
bool Program_Description_Set(uint32_t instance, const char *new_name);
BACNET_STACK_EXPORT
const char *Program_Description_ANSI(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Location(
uint32_t object_instance, BACNET_CHARACTER_STRING *description);
BACNET_STACK_EXPORT
bool Program_Location_Set(uint32_t instance, const char *new_name);
BACNET_STACK_EXPORT
const char *Program_Location_ANSI(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Instance_Of(
uint32_t object_instance, BACNET_CHARACTER_STRING *description);
BACNET_STACK_EXPORT
bool Program_Instance_Of_Set(uint32_t instance, const char *new_name);
BACNET_STACK_EXPORT
const char *Program_Instance_Of_ANSI(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Description_Of_Halt(
uint32_t object_instance, BACNET_CHARACTER_STRING *description);
BACNET_STACK_EXPORT
bool Program_Description_Of_Halt_Set(uint32_t instance, const char *new_name);
BACNET_STACK_EXPORT
const char *Program_Description_Of_Halt_ANSI(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Out_Of_Service(uint32_t instance);
BACNET_STACK_EXPORT
void Program_Out_Of_Service_Set(uint32_t instance, bool oos_flag);
BACNET_STACK_EXPORT
void Program_Timer(uint32_t object_instance, uint16_t milliseconds);
BACNET_STACK_EXPORT
uint32_t Program_Create(uint32_t object_instance);
BACNET_STACK_EXPORT
bool Program_Delete(uint32_t object_instance);
BACNET_STACK_EXPORT
void Program_Cleanup(void);
BACNET_STACK_EXPORT
void Program_Init(void);
/* API for the program requests */
BACNET_STACK_EXPORT
void Program_Context_Set(uint32_t object_instance, void *context);
BACNET_STACK_EXPORT
void Program_Load_Set(
uint32_t object_instance,
void (*load)(void *context, const char *location));
BACNET_STACK_EXPORT
void Program_Run_Set(uint32_t object_instance, void (*run)(void *context));
BACNET_STACK_EXPORT
void Program_Halt_Set(uint32_t object_instance, void (*halt)(void *context));
BACNET_STACK_EXPORT
void Program_Restart_Set(
uint32_t object_instance, void (*restart)(void *context));
BACNET_STACK_EXPORT
void Program_Unload_Set(
uint32_t object_instance, void (*unload)(void *context));
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+26
View File
@@ -46,6 +46,7 @@
#include "bacnet/basic/object/iv.h"
#include "bacnet/basic/object/time_value.h"
#include "bacnet/basic/object/channel.h"
#include "bacnet/basic/object/program.h"
#include "bacnet/basic/object/lo.h"
#include "bacnet/basic/object/blo.h"
#include "bacnet/basic/object/netport.h"
@@ -102,6 +103,7 @@
defined(CONFIG_BACNET_BASIC_OBJECT_FILE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_STRUCTURED_VIEW) || \
defined(CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE) || \
defined(CONFIG_BACNET_BASIC_OBJECT_PROGRAM) || \
defined(CONFIG_BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE))
#define CONFIG_BACNET_BASIC_OBJECT_ALL
#endif
@@ -130,6 +132,8 @@
#define CONFIG_BACNET_BASIC_OBJECT_FILE
#define CONFIG_BACNET_BASIC_OBJECT_STRUCTURED_VIEW
#define CONFIG_BACNET_BASIC_OBJECT_BITSTRING_VALUE
#define CONFIG_BACNET_BASIC_OBJECT_PROGRAM
#define CONFIG_BACNET_BASIC_OBJECT_CHARACTERSTRING_VALUE
#endif
#if (BACNET_PROTOCOL_REVISION < 14)
@@ -717,6 +721,28 @@ static object_functions_t Object_Table[] = {
CharacterString_Value_Create,
CharacterString_Value_Delete,
NULL /* Timer */ },
#endif
#if defined(CONFIG_BACNET_BASIC_OBJECT_PROGRAM)
{ OBJECT_BITSTRING_VALUE,
Program_Init,
Program_Count,
Program_Index_To_Instance,
Program_Valid_Instance,
Program_Object_Name,
Program_Read_Property,
Program_Write_Property,
Program_Property_Lists,
NULL /* ReadRangeInfo */,
NULL /* Iterator */,
NULL /* Value_Lists */,
NULL /* COV */,
NULL /* COV Clear */,
NULL /* Intrinsic Reporting */,
NULL /* Add_List_Element */,
NULL /* Remove_List_Element */,
Program_Create,
Program_Delete,
Program_Timer },
#endif
{
MAX_BACNET_OBJECT_TYPE,
+1
View File
@@ -160,6 +160,7 @@ list(APPEND testdirs
bacnet/basic/object/mso
bacnet/basic/object/msv
bacnet/basic/object/netport
bacnet/basic/object/program
bacnet/basic/object/nc
bacnet/basic/object/objects
bacnet/basic/object/osv
@@ -75,6 +75,7 @@ add_executable(${PROJECT_NAME}
${SRC_DIR}/bacnet/basic/object/netport.c
${SRC_DIR}/bacnet/basic/object/osv.c
${SRC_DIR}/bacnet/basic/object/piv.c
${SRC_DIR}/bacnet/basic/object/program.c
${SRC_DIR}/bacnet/basic/object/schedule.c
${SRC_DIR}/bacnet/basic/object/structured_view.c
${SRC_DIR}/bacnet/basic/object/time_value.c
@@ -0,0 +1,72 @@
# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.10 FATAL_ERROR)
get_filename_component(basename ${CMAKE_CURRENT_SOURCE_DIR} NAME)
project(test_${basename}
VERSION 1.0.0
LANGUAGES C)
string(REGEX REPLACE
"/test/bacnet/[a-zA-Z_/-]*$"
"/src"
SRC_DIR
${CMAKE_CURRENT_SOURCE_DIR})
string(REGEX REPLACE
"/test/bacnet/[a-zA-Z_/-]*$"
"/test"
TST_DIR
${CMAKE_CURRENT_SOURCE_DIR})
set(ZTST_DIR "${TST_DIR}/ztest/src")
add_compile_definitions(
BIG_ENDIAN=0
CONFIG_ZTEST=1
)
include_directories(
${SRC_DIR}
${TST_DIR}/bacnet/basic/object/test
${TST_DIR}/ztest/include
)
add_executable(${PROJECT_NAME}
# File(s) under test
${SRC_DIR}/bacnet/basic/object/program.c
# Support files and stubs (pathname alphabetical)
${SRC_DIR}/bacnet/access_rule.c
${SRC_DIR}/bacnet/bacaction.c
${SRC_DIR}/bacnet/bacaddr.c
${SRC_DIR}/bacnet/bacapp.c
${SRC_DIR}/bacnet/bacdcode.c
${SRC_DIR}/bacnet/bacdest.c
${SRC_DIR}/bacnet/bacdevobjpropref.c
${SRC_DIR}/bacnet/bacint.c
${SRC_DIR}/bacnet/bacreal.c
${SRC_DIR}/bacnet/bacstr.c
${SRC_DIR}/bacnet/bactext.c
${SRC_DIR}/bacnet/cov.c
${SRC_DIR}/bacnet/datetime.c
${SRC_DIR}/bacnet/indtext.c
${SRC_DIR}/bacnet/hostnport.c
${SRC_DIR}/bacnet/lighting.c
${SRC_DIR}/bacnet/proplist.c
${SRC_DIR}/bacnet/memcopy.c
${SRC_DIR}/bacnet/timestamp.c
${SRC_DIR}/bacnet/wp.c
${SRC_DIR}/bacnet/weeklyschedule.c
${SRC_DIR}/bacnet/bactimevalue.c
${SRC_DIR}/bacnet/dailyschedule.c
${SRC_DIR}/bacnet/calendar_entry.c
${SRC_DIR}/bacnet/special_event.c
${SRC_DIR}/bacnet/channel_value.c
${SRC_DIR}/bacnet/secure_connect.c
${SRC_DIR}/bacnet/basic/sys/bigend.c
${SRC_DIR}/bacnet/basic/sys/days.c
${SRC_DIR}/bacnet/basic/sys/keylist.c
# Test and test library files
./src/main.c
${TST_DIR}/bacnet/basic/object/test/property_test.c
${ZTST_DIR}/ztest_mock.c
${ZTST_DIR}/ztest.c
)
@@ -0,0 +1,60 @@
/**
* @file
* @brief Unit test for the Program object type
* @author Steve Karg <skarg@users.sourceforge.net>
* @date March 2025
* @section LICENSE
*
* SPDX-License-Identifier: MIT
*/
#include <zephyr/ztest.h>
#include <bacnet/basic/object/program.h>
#include <property_test.h>
/**
* @addtogroup bacnet_tests
* @{
*/
/**
* @brief Test
*/
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST(ao_tests, testProgramObject)
#else
static void testProgramObject(void)
#endif
{
bool status = false;
unsigned count = 0;
uint32_t object_instance = BACNET_MAX_INSTANCE, test_object_instance = 0;
const int skip_fail_property_list[] = { -1 };
Program_Init();
object_instance = Program_Create(object_instance);
count = Program_Count();
zassert_true(count == 1, NULL);
test_object_instance = Program_Index_To_Instance(0);
zassert_equal(object_instance, test_object_instance, NULL);
bacnet_object_properties_read_write_test(
OBJECT_PROGRAM, object_instance, Program_Property_Lists,
Program_Read_Property, Program_Write_Property, skip_fail_property_list);
bacnet_object_name_ascii_test(
object_instance, Program_Name_Set, Program_Name_ASCII);
status = Program_Delete(object_instance);
zassert_true(status, NULL);
}
/**
* @}
*/
#if defined(CONFIG_ZTEST_NEW_API)
ZTEST_SUITE(program_object_tests, NULL, NULL, NULL, NULL, NULL);
#else
void test_main(void)
{
ztest_test_suite(program_object_tests, ztest_unit_test(testProgramObject));
ztest_run_test_suite(program_object_tests);
}
#endif