Added Program object task state transitions from request and callbacks (#960)
This commit is contained in:
@@ -1094,7 +1094,8 @@ typedef enum BACnetProgramRequest {
|
||||
PROGRAM_REQUEST_RUN = 2,
|
||||
PROGRAM_REQUEST_HALT = 3,
|
||||
PROGRAM_REQUEST_RESTART = 4,
|
||||
PROGRAM_REQUEST_UNLOAD = 5
|
||||
PROGRAM_REQUEST_UNLOAD = 5,
|
||||
PROGRAM_REQUEST_MAX = 6
|
||||
} BACNET_PROGRAM_REQUEST;
|
||||
|
||||
typedef enum BACnetProgramState {
|
||||
@@ -1103,7 +1104,8 @@ typedef enum BACnetProgramState {
|
||||
PROGRAM_STATE_RUNNING = 2,
|
||||
PROGRAM_STATE_WAITING = 3,
|
||||
PROGRAM_STATE_HALTED = 4,
|
||||
PROGRAM_STATE_UNLOADING = 5
|
||||
PROGRAM_STATE_UNLOADING = 5,
|
||||
PROGRAM_STATE_MAX = 6
|
||||
} BACNET_PROGRAM_STATE;
|
||||
|
||||
typedef enum BACnetProgramError {
|
||||
|
||||
@@ -47,11 +47,12 @@ struct object_data {
|
||||
bool Out_Of_Service : 1;
|
||||
bool Changed : 1;
|
||||
void *Context;
|
||||
void (*Load)(void *context, const char *location);
|
||||
void (*Run)(void *context);
|
||||
void (*Halt)(void *context);
|
||||
void (*Restart)(void *context);
|
||||
void (*Unload)(void *context);
|
||||
/* return 0 for success, negative on error */
|
||||
int (*Load)(void *context, const char *location);
|
||||
int (*Run)(void *context);
|
||||
int (*Halt)(void *context);
|
||||
int (*Restart)(void *context);
|
||||
int (*Unload)(void *context);
|
||||
};
|
||||
|
||||
/* These three arrays are used by the ReadPropertyMultiple handler */
|
||||
@@ -595,6 +596,53 @@ bool Program_Change_Set(
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, writes the program change value
|
||||
*
|
||||
* Normally the value of the Program_Change property will be READY,
|
||||
* meaning that the program is ready to accept a new
|
||||
* request to change its operating state. If the Program_Change
|
||||
* property is not READY, then it may not be written to and any
|
||||
* attempt to write to the property shall return a Result(-).
|
||||
* If it has one of the other enumerated values, then a previous
|
||||
* request to change state has not yet been honored, so new requests
|
||||
* cannot be accepted. When the request to change state is finally
|
||||
* honored, then the Program_Change property value shall become
|
||||
* READY and the new state shall be reflected in the Program_State property.
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param program_change - property value
|
||||
* @param error_class - BACNET_ERROR_CLASS
|
||||
* @param error_code - BACNET_ERROR_CODE
|
||||
* @return true if the program change property value was written
|
||||
*/
|
||||
static bool Program_Change_Write(
|
||||
uint32_t object_instance,
|
||||
BACNET_PROGRAM_REQUEST program_change,
|
||||
BACNET_ERROR_CLASS *error_class,
|
||||
BACNET_ERROR_CODE *error_code)
|
||||
{
|
||||
bool status = false;
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
if (pObject) {
|
||||
if (pObject->Program_Change == PROGRAM_REQUEST_READY) {
|
||||
if (program_change <= PROGRAM_REQUEST_MAX) {
|
||||
pObject->Program_Change = program_change;
|
||||
status = true;
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
} else {
|
||||
*error_class = ERROR_CLASS_PROPERTY;
|
||||
*error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given object instance-number, returns the Reason_For_Halt
|
||||
*
|
||||
@@ -865,12 +913,9 @@ bool Program_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data)
|
||||
status = write_property_type_valid(
|
||||
wp_data, &value, BACNET_APPLICATION_TAG_ENUMERATED);
|
||||
if (status) {
|
||||
status = Program_Change_Set(
|
||||
wp_data->object_instance, value.type.Enumerated);
|
||||
if (!status) {
|
||||
wp_data->error_class = ERROR_CLASS_PROPERTY;
|
||||
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
|
||||
}
|
||||
status = Program_Change_Write(
|
||||
wp_data->object_instance, value.type.Enumerated,
|
||||
&wp_data->error_class, &wp_data->error_code);
|
||||
}
|
||||
break;
|
||||
case PROP_OUT_OF_SERVICE:
|
||||
@@ -917,7 +962,7 @@ void Program_Context_Set(uint32_t object_instance, void *context)
|
||||
* @param load [in] pointer to the Load function
|
||||
*/
|
||||
void Program_Load_Set(
|
||||
uint32_t object_instance, void (*load)(void *context, const char *location))
|
||||
uint32_t object_instance, int (*load)(void *context, const char *location))
|
||||
{
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
@@ -931,7 +976,7 @@ void Program_Load_Set(
|
||||
* @param object_instance [in] BACnet object instance number
|
||||
* @param run [in] pointer to the Run function
|
||||
*/
|
||||
void Program_Run_Set(uint32_t object_instance, void (*run)(void *context))
|
||||
void Program_Run_Set(uint32_t object_instance, int (*run)(void *context))
|
||||
{
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
@@ -945,7 +990,7 @@ void Program_Run_Set(uint32_t object_instance, void (*run)(void *context))
|
||||
* @param object_instance [in] BACnet object instance number
|
||||
* @param halt [in] pointer to the Halt function
|
||||
*/
|
||||
void Program_Halt_Set(uint32_t object_instance, void (*halt)(void *context))
|
||||
void Program_Halt_Set(uint32_t object_instance, int (*halt)(void *context))
|
||||
{
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
@@ -960,7 +1005,7 @@ void Program_Halt_Set(uint32_t object_instance, void (*halt)(void *context))
|
||||
* @param restart [in] pointer to the Restart function
|
||||
*/
|
||||
void Program_Restart_Set(
|
||||
uint32_t object_instance, void (*restart)(void *context))
|
||||
uint32_t object_instance, int (*restart)(void *context))
|
||||
{
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
@@ -974,7 +1019,7 @@ void Program_Restart_Set(
|
||||
* @param object_instance [in] BACnet object instance number
|
||||
* @param unload [in] pointer to the Unload function
|
||||
*/
|
||||
void Program_Unload_Set(uint32_t object_instance, void (*unload)(void *context))
|
||||
void Program_Unload_Set(uint32_t object_instance, int (*unload)(void *context))
|
||||
{
|
||||
struct object_data *pObject = Object_Data(object_instance);
|
||||
|
||||
@@ -983,8 +1028,211 @@ void Program_Unload_Set(uint32_t object_instance, void (*unload)(void *context))
|
||||
}
|
||||
}
|
||||
|
||||
static void Program_State_Idle_Handler(struct object_data *pObject)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pObject->Program_Change == PROGRAM_REQUEST_LOAD) {
|
||||
if (pObject->Load) {
|
||||
err = pObject->Load(pObject->Context, pObject->Program_Location);
|
||||
if (err == 0) {
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_RUN) {
|
||||
if (pObject->Load) {
|
||||
err = pObject->Load(pObject->Context, pObject->Program_Location);
|
||||
if (err == 0) {
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_RESTART) {
|
||||
if (pObject->Restart) {
|
||||
err = pObject->Restart(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_OTHER;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Program_State_Halted_Handler(struct object_data *pObject)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pObject->Program_Change == PROGRAM_REQUEST_UNLOAD) {
|
||||
if (pObject->Unload) {
|
||||
err = pObject->Unload(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_UNLOADING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_UNLOADING;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_LOAD) {
|
||||
if (pObject->Load) {
|
||||
err = pObject->Load(pObject->Context, pObject->Program_Location);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_RUN) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_RESTART) {
|
||||
if (pObject->Restart) {
|
||||
err = pObject->Restart(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_OTHER;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Program_State_Running_Handler(struct object_data *pObject)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (pObject->Program_Change == PROGRAM_REQUEST_UNLOAD) {
|
||||
if (pObject->Unload) {
|
||||
err = pObject->Unload(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_UNLOADING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_OTHER;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_UNLOADING;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_LOAD) {
|
||||
if (pObject->Load) {
|
||||
err = pObject->Load(pObject->Context, pObject->Program_Location);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_LOAD_FAILED;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_LOADING;
|
||||
}
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_HALT) {
|
||||
if (pObject->Halt) {
|
||||
pObject->Halt(pObject->Context);
|
||||
}
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_PROGRAM;
|
||||
pObject->Program_State = PROGRAM_STATE_HALTED;
|
||||
} else if (pObject->Program_Change == PROGRAM_REQUEST_RESTART) {
|
||||
if (pObject->Restart) {
|
||||
err = pObject->Restart(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_OTHER;
|
||||
}
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
pObject->Program_State = PROGRAM_STATE_RUNNING;
|
||||
}
|
||||
} else {
|
||||
if (pObject->Run) {
|
||||
err = pObject->Run(pObject->Context);
|
||||
if (err == 0) {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_NORMAL;
|
||||
} else {
|
||||
pObject->Reason_For_Halt = PROGRAM_ERROR_INTERNAL;
|
||||
pObject->Program_State = PROGRAM_STATE_HALTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates the object program operation
|
||||
*
|
||||
* 12.22.5 Program_Change
|
||||
*
|
||||
* This property, of type BACnetProgramRequest, is used to request changes
|
||||
* to the operating state of the process this object represents.
|
||||
* The Program_Change property provides one means for changing
|
||||
* the operating state of this process. The process may change its own
|
||||
* state as a consequence of execution as well.
|
||||
*
|
||||
* The values that may be taken on by this property are:
|
||||
* READY ready for change request (the normal state)
|
||||
* LOAD request that the application program be loaded, if not already loaded
|
||||
* RUN request that the process begin executing, if not already running
|
||||
* HALT request that the process halt execution
|
||||
* RESTART request that the process restart at its initialization point
|
||||
* UNLOAD request that the process halt execution and unload
|
||||
*
|
||||
* Normally the value of the Program_Change property will be READY,
|
||||
* meaning that the program is ready to accept a new
|
||||
* request to change its operating state. If the Program_Change property
|
||||
* is not READY, then it may not be written to and any
|
||||
* attempt to write to the property shall return a Result(-).
|
||||
* If it has one of the other enumerated values, then a previous request to
|
||||
* change state has not yet been honored, so new requests cannot
|
||||
* be accepted. When the request to change state is finally
|
||||
* honored, then the Program_Change property value shall become READY
|
||||
* and the new state shall be reflected in the Program_State property.
|
||||
* Depending on the current Program_State, certain requested values for
|
||||
* Program_Change may be invalid and would also return a Result(-)
|
||||
* if an attempt were made to write them.
|
||||
*
|
||||
* It is important to note that program loading could be terminated
|
||||
* either due to an error or a request to HALT that occurs
|
||||
* during loading. In either case, it is possible to have Program_State=HALTED
|
||||
* and yet not have a complete or operable program in place.
|
||||
* In this case, a request to RESTART is taken to mean LOAD instead.
|
||||
* If a complete program is loaded but HALTED for any reason,
|
||||
* then RESTART simply reenters program execution at its
|
||||
* initialization entry point.
|
||||
*
|
||||
* There may be BACnet devices
|
||||
* that support Program objects but do not require "loading"
|
||||
* of the application programs, as these applications may be built in.
|
||||
* In these cases, loading is taken to mean "preparing for execution,"
|
||||
* the specifics of which are a local matter.
|
||||
*
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param milliseconds - number of milliseconds elapsed
|
||||
*/
|
||||
@@ -995,9 +1243,30 @@ void Program_Timer(uint32_t object_instance, uint16_t milliseconds)
|
||||
(void)milliseconds;
|
||||
pObject = Keylist_Data(Object_List, object_instance);
|
||||
if (pObject) {
|
||||
if (pObject->Run) {
|
||||
pObject->Run(pObject->Context);
|
||||
switch (pObject->Program_State) {
|
||||
case PROGRAM_STATE_IDLE:
|
||||
Program_State_Idle_Handler(pObject);
|
||||
break;
|
||||
case PROGRAM_STATE_LOADING:
|
||||
pObject->Program_State = PROGRAM_STATE_HALTED;
|
||||
break;
|
||||
case PROGRAM_STATE_UNLOADING:
|
||||
pObject->Program_State = PROGRAM_STATE_IDLE;
|
||||
break;
|
||||
case PROGRAM_STATE_HALTED:
|
||||
Program_State_Halted_Handler(pObject);
|
||||
break;
|
||||
case PROGRAM_STATE_RUNNING:
|
||||
Program_State_Running_Handler(pObject);
|
||||
break;
|
||||
case PROGRAM_STATE_WAITING:
|
||||
Program_State_Running_Handler(pObject);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
pObject->Program_Change = PROGRAM_REQUEST_READY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,18 +115,16 @@ 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));
|
||||
uint32_t object_instance, int (*load)(void *context, const char *location));
|
||||
BACNET_STACK_EXPORT
|
||||
void Program_Run_Set(uint32_t object_instance, void (*run)(void *context));
|
||||
void Program_Run_Set(uint32_t object_instance, int (*run)(void *context));
|
||||
BACNET_STACK_EXPORT
|
||||
void Program_Halt_Set(uint32_t object_instance, void (*halt)(void *context));
|
||||
void Program_Halt_Set(uint32_t object_instance, int (*halt)(void *context));
|
||||
BACNET_STACK_EXPORT
|
||||
void Program_Restart_Set(
|
||||
uint32_t object_instance, void (*restart)(void *context));
|
||||
uint32_t object_instance, int (*restart)(void *context));
|
||||
BACNET_STACK_EXPORT
|
||||
void Program_Unload_Set(
|
||||
uint32_t object_instance, void (*unload)(void *context));
|
||||
void Program_Unload_Set(uint32_t object_instance, int (*unload)(void *context));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -16,6 +16,91 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int Program_Load(void *context, const char *location)
|
||||
{
|
||||
/* Placeholder for load function */
|
||||
(void)context;
|
||||
(void)location;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int Program_Run(void *context)
|
||||
{
|
||||
/* Placeholder for run function */
|
||||
(void)context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int Program_Halt(void *context)
|
||||
{
|
||||
/* Placeholder for halt function */
|
||||
(void)context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int Program_Restart(void *context)
|
||||
{
|
||||
/* Placeholder for restart function */
|
||||
(void)context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_program_task(uint32_t object_instance)
|
||||
{
|
||||
int context = 0;
|
||||
uint16_t milliseconds = 1000;
|
||||
bool status = false;
|
||||
BACNET_PROGRAM_REQUEST program_change = PROGRAM_REQUEST_READY;
|
||||
|
||||
Program_Context_Set(object_instance, &context);
|
||||
Program_Load_Set(object_instance, Program_Load);
|
||||
Program_Run_Set(object_instance, Program_Run);
|
||||
Program_Halt_Set(object_instance, Program_Halt);
|
||||
Program_Restart_Set(object_instance, Program_Restart);
|
||||
Program_Unload_Set(object_instance, NULL);
|
||||
|
||||
status = Program_Change_Set(object_instance, program_change);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_Change(object_instance), PROGRAM_REQUEST_READY, NULL);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_IDLE, NULL);
|
||||
|
||||
status = Program_Change_Set(object_instance, PROGRAM_REQUEST_LOAD);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(Program_Change(object_instance), PROGRAM_REQUEST_LOAD, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_Change(object_instance), PROGRAM_REQUEST_READY, NULL);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_LOADING, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_HALTED, NULL);
|
||||
status = Program_Change_Set(object_instance, PROGRAM_REQUEST_RUN);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(Program_Change(object_instance), PROGRAM_REQUEST_RUN, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_RUNNING, NULL);
|
||||
status = Program_Change_Set(object_instance, PROGRAM_REQUEST_HALT);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(Program_Change(object_instance), PROGRAM_REQUEST_HALT, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_HALTED, NULL);
|
||||
status = Program_Change_Set(object_instance, PROGRAM_REQUEST_RESTART);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(
|
||||
Program_Change(object_instance), PROGRAM_REQUEST_RESTART, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(Program_State(object_instance), PROGRAM_STATE_RUNNING, NULL);
|
||||
status = Program_Change_Set(object_instance, PROGRAM_REQUEST_UNLOAD);
|
||||
zassert_true(status, NULL);
|
||||
zassert_equal(
|
||||
Program_Change(object_instance), PROGRAM_REQUEST_UNLOAD, NULL);
|
||||
Program_Timer(object_instance, milliseconds);
|
||||
zassert_equal(
|
||||
Program_State(object_instance), PROGRAM_STATE_UNLOADING, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
*/
|
||||
@@ -41,6 +126,9 @@ static void testProgramObject(void)
|
||||
Program_Read_Property, Program_Write_Property, skip_fail_property_list);
|
||||
bacnet_object_name_ascii_test(
|
||||
object_instance, Program_Name_Set, Program_Name_ASCII);
|
||||
|
||||
test_program_task(object_instance);
|
||||
|
||||
status = Program_Delete(object_instance);
|
||||
zassert_true(status, NULL);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user