Feature/add bacnet binary lighting object (#522)
* Added Binary Lighting Output object example. * Changed piface example app to support binary-lighting-output object type and blink warn * Changed example device object to not create objects when device object-table is overridden * Fixed unit testing for device object
This commit is contained in:
@@ -188,6 +188,8 @@ add_library(${PROJECT_NAME}
|
||||
src/bacnet/basic/object/bacfile.h
|
||||
src/bacnet/basic/object/bi.c
|
||||
src/bacnet/basic/object/bi.h
|
||||
src/bacnet/basic/object/blo.c
|
||||
src/bacnet/basic/object/blo.h
|
||||
src/bacnet/basic/object/bo.c
|
||||
src/bacnet/basic/object/bo.h
|
||||
src/bacnet/basic/object/bv.c
|
||||
|
||||
+1
-4
@@ -118,9 +118,6 @@ static void Init_Service_Handlers(void)
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
/* handle the data coming back from private requests */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
|
||||
handler_unconfirmed_private_transfer);
|
||||
/* configure the cyclic timers */
|
||||
mstimer_set(&BACnet_Task_Timer, 1000UL);
|
||||
mstimer_set(&BACnet_TSM_Timer, 50UL);
|
||||
@@ -297,7 +294,7 @@ static void bacnet_output_init(void)
|
||||
Channel_Reference_List_Member_Element_Set(
|
||||
light_channel_instance, 1 + i, &member);
|
||||
|
||||
object_instance++;
|
||||
object_instance = 1 + i;
|
||||
}
|
||||
Color_Write_Present_Value_Callback_Set(Color_Write_Value_Handler);
|
||||
Color_Temperature_Write_Present_Value_Callback_Set(
|
||||
|
||||
@@ -15,6 +15,7 @@ BACNET_OBJECT_SRC := \
|
||||
$(BACNET_OBJECT_DIR)/ao.c \
|
||||
$(BACNET_OBJECT_DIR)/av.c \
|
||||
$(BACNET_OBJECT_DIR)/bi.c \
|
||||
$(BACNET_OBJECT_DIR)/blo.c \
|
||||
$(BACNET_OBJECT_DIR)/bo.c \
|
||||
$(BACNET_OBJECT_DIR)/bv.c \
|
||||
$(BACNET_OBJECT_DIR)/channel.c \
|
||||
|
||||
@@ -10,6 +10,7 @@ SRC = main.c \
|
||||
device.c \
|
||||
$(BACNET_OBJECT_DIR)/netport.c \
|
||||
$(BACNET_OBJECT_DIR)/bi.c \
|
||||
$(BACNET_OBJECT_DIR)/blo.c \
|
||||
$(BACNET_OBJECT_DIR)/bo.c
|
||||
|
||||
CFLAGS += -DMAX_TSM_TRANSACTIONS=1
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
/* include the OS specific */
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#include "bacnet/basic/object/bi.h"
|
||||
#include "bacnet/basic/object/blo.h"
|
||||
#include "bacnet/basic/object/bo.h"
|
||||
#if (BACNET_PROTOCOL_REVISION >= 17)
|
||||
#include "bacnet/basic/object/netport.h"
|
||||
@@ -88,6 +89,18 @@ static object_functions_t My_Object_Table[] = {
|
||||
Binary_Input_Change_Of_Value_Clear, NULL /* Intrinsic Reporting */,
|
||||
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
|
||||
NULL /* Create */, NULL /* Delete */, NULL /* Timer */ },
|
||||
{ OBJECT_BINARY_LIGHTING_OUTPUT, Binary_Lighting_Output_Init,
|
||||
Binary_Lighting_Output_Count, Binary_Lighting_Output_Index_To_Instance,
|
||||
Binary_Lighting_Output_Valid_Instance,
|
||||
Binary_Lighting_Output_Object_Name,
|
||||
Binary_Lighting_Output_Read_Property,
|
||||
Binary_Lighting_Output_Write_Property,
|
||||
Binary_Lighting_Output_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 */,
|
||||
Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete,
|
||||
Binary_Lighting_Output_Timer },
|
||||
{ OBJECT_BINARY_OUTPUT, Binary_Output_Init, Binary_Output_Count,
|
||||
Binary_Output_Index_To_Instance, Binary_Output_Valid_Instance,
|
||||
Binary_Output_Object_Name, Binary_Output_Read_Property,
|
||||
@@ -1979,3 +1992,30 @@ bool DeviceGetRRInfo(BACNET_READ_RANGE_DATA *pRequest, /* Info on the request */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates all the object timers with elapsed milliseconds
|
||||
* @param milliseconds - number of milliseconds elapsed
|
||||
*/
|
||||
void Device_Timer(uint16_t milliseconds)
|
||||
{
|
||||
struct object_functions *pObject;
|
||||
unsigned count = 0;
|
||||
uint32_t instance;
|
||||
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Count) {
|
||||
count = pObject->Object_Count();
|
||||
}
|
||||
while (count) {
|
||||
count--;
|
||||
if ((pObject->Object_Timer) &&
|
||||
(pObject->Object_Index_To_Instance)) {
|
||||
instance = pObject->Object_Index_To_Instance(count);
|
||||
pObject->Object_Timer(instance, milliseconds);
|
||||
}
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
}
|
||||
|
||||
+148
-65
@@ -1,33 +1,17 @@
|
||||
/**************************************************************************
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date January 2023
|
||||
*
|
||||
* Copyright (C) 2006 Steve Karg <skarg@users.sourceforge.net>
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* 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>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "bacnet/config.h"
|
||||
#include "bacnet/basic/binding/address.h"
|
||||
@@ -39,40 +23,117 @@
|
||||
#include "bacnet/npdu.h"
|
||||
#include "bacnet/apdu.h"
|
||||
#include "bacnet/iam.h"
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#include "bacnet/basic/object/bacfile.h"
|
||||
#include "bacnet/datalink/datalink.h"
|
||||
#include "bacnet/dcc.h"
|
||||
#include "bacnet/getevent.h"
|
||||
#include "bacport.h"
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
#include "bacnet/basic/sys/mstimer.h"
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
#include "bacnet/version.h"
|
||||
/* include the device object */
|
||||
#include "bacnet/basic/object/device.h"
|
||||
#include "bacnet/basic/object/bi.h"
|
||||
#include "bacnet/basic/object/blo.h"
|
||||
#include "bacnet/basic/object/bo.h"
|
||||
#include "pifacedigital.h"
|
||||
|
||||
/** @file server/main.c Example server application using the BACnet Stack. */
|
||||
|
||||
/* (Doxygen note: The next two lines pull all the following Javadoc
|
||||
* into the ServerDemo module.) */
|
||||
/** @addtogroup ServerDemo */
|
||||
/*@{*/
|
||||
/* number of binary outputs on the PiFace card */
|
||||
#define PIFACE_OUTPUTS_MAX 8
|
||||
|
||||
/** Buffer used for receiving */
|
||||
static uint8_t Rx_Buf[MAX_MPDU] = { 0 };
|
||||
|
||||
/* current version of the BACnet stack */
|
||||
static const char *BACnet_Version = BACNET_VERSION_TEXT;
|
||||
/* task timer for various BACnet timeouts */
|
||||
static struct mstimer BACnet_Task_Timer;
|
||||
/* task timer for TSM timeouts */
|
||||
static struct mstimer BACnet_TSM_Timer;
|
||||
/* task timer for address binding timeouts */
|
||||
static struct mstimer BACnet_Address_Timer;
|
||||
/* task timer for object functionality */
|
||||
static struct mstimer BACnet_Object_Timer;
|
||||
/* track the state of of the output */
|
||||
static bool PiFace_Output_State[PIFACE_OUTPUTS_MAX];
|
||||
|
||||
/**
|
||||
* @brief output write value request
|
||||
* @param index - 0..N index of the output
|
||||
* @param value - value of the write ON or OFF
|
||||
*/
|
||||
static void piface_write_output(int index, BACNET_BINARY_LIGHTING_PV value)
|
||||
{
|
||||
if (index < PIFACE_OUTPUTS_MAX) {
|
||||
if (value == BINARY_LIGHTING_PV_OFF) {
|
||||
pifacedigital_digital_write(index, 0);
|
||||
PiFace_Output_State[index] = false;
|
||||
printf("OUTPUT[%u]=OFF\n", index);
|
||||
} else if (value == BINARY_LIGHTING_PV_ON) {
|
||||
pifacedigital_digital_write(index, 1);
|
||||
PiFace_Output_State[index] = true;
|
||||
printf("OUTPUT[%u]=ON\n", index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for write value request
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param old_value - value prior to write
|
||||
* @param value - value of the write
|
||||
*/
|
||||
static void Binary_Lighting_Output_Write_Value_Handler(uint32_t object_instance,
|
||||
BACNET_BINARY_LIGHTING_PV old_value,
|
||||
BACNET_BINARY_LIGHTING_PV value)
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
index = Binary_Lighting_Output_Instance_To_Index(object_instance);
|
||||
if (index < PIFACE_OUTPUTS_MAX) {
|
||||
printf("BLO-WRITE: OUTPUT[%u]=%d present=%d feedback=%d target=%d\n",
|
||||
index, (int)value,
|
||||
(int)Binary_Lighting_Output_Present_Value(object_instance),
|
||||
(int)old_value,
|
||||
(int)Binary_Lighting_Output_Lighting_Command_Target_Value(
|
||||
object_instance));
|
||||
piface_write_output(index, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Callback for blink warning notification
|
||||
* @param object_instance - object-instance number of the object
|
||||
*/
|
||||
static void Binary_Lighting_Output_Blink_Warn_Handler(uint32_t object_instance)
|
||||
{
|
||||
unsigned index;
|
||||
|
||||
index = Binary_Lighting_Output_Instance_To_Index(object_instance);
|
||||
if (index < PIFACE_OUTPUTS_MAX) {
|
||||
/* blink is just toggle on/off every one second */
|
||||
if (PiFace_Output_State[index]) {
|
||||
printf("BLO-BLINK: OUTPUT[%u]=%d\n", index,
|
||||
BINARY_LIGHTING_PV_OFF);
|
||||
piface_write_output(index, BINARY_LIGHTING_PV_OFF);
|
||||
} else {
|
||||
printf(
|
||||
"BLO-BLINK: OUTPUT[%u]=%d\n", index, BINARY_LIGHTING_PV_ON);
|
||||
piface_write_output(index, BINARY_LIGHTING_PV_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize the handlers we will utilize.
|
||||
* @see Device_Init, apdu_set_unconfirmed_handler, apdu_set_confirmed_handler
|
||||
*/
|
||||
static void Init_Service_Handlers(void)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t object_instance;
|
||||
|
||||
Device_Init(NULL);
|
||||
/* we need to handle who-is to support dynamic device binding */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_WHO_IS, handler_who_is);
|
||||
@@ -107,9 +168,21 @@ static void Init_Service_Handlers(void)
|
||||
/* handle communication so we can shutup when asked */
|
||||
apdu_set_confirmed_handler(SERVICE_CONFIRMED_DEVICE_COMMUNICATION_CONTROL,
|
||||
handler_device_communication_control);
|
||||
/* handle the data coming back from private requests */
|
||||
apdu_set_unconfirmed_handler(SERVICE_UNCONFIRMED_PRIVATE_TRANSFER,
|
||||
handler_unconfirmed_private_transfer);
|
||||
/* configure the cyclic timers */
|
||||
mstimer_set(&BACnet_Task_Timer, 1000UL);
|
||||
mstimer_set(&BACnet_TSM_Timer, 50UL);
|
||||
mstimer_set(&BACnet_Address_Timer, 60UL * 1000UL);
|
||||
mstimer_set(&BACnet_Object_Timer, 1000UL);
|
||||
/* create some objects */
|
||||
for (i = 0; i < PIFACE_OUTPUTS_MAX; i++) {
|
||||
object_instance = 1 + i;
|
||||
Binary_Lighting_Output_Create(object_instance);
|
||||
Binary_Output_Create(object_instance);
|
||||
}
|
||||
Binary_Lighting_Output_Write_Value_Callback_Set(
|
||||
Binary_Lighting_Output_Write_Value_Handler);
|
||||
Binary_Lighting_Output_Blink_Warn_Callback_Set(
|
||||
Binary_Lighting_Output_Blink_Warn_Handler);
|
||||
}
|
||||
|
||||
static void piface_init(void)
|
||||
@@ -159,6 +232,7 @@ static void piface_task(void)
|
||||
unsigned i = 0;
|
||||
BACNET_BINARY_PV present_value = BINARY_INACTIVE;
|
||||
bool pin_status = false;
|
||||
uint32_t object_instance;
|
||||
|
||||
for (i = 0; i < MAX_BINARY_INPUTS; i++) {
|
||||
if (!Binary_Input_Out_Of_Service(i)) {
|
||||
@@ -181,13 +255,24 @@ static void piface_task(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < MAX_BINARY_OUTPUTS; i++) {
|
||||
if (!Binary_Output_Out_Of_Service(i)) {
|
||||
present_value = Binary_Output_Present_Value(i);
|
||||
for (i = 0; i < PIFACE_OUTPUTS_MAX; i++) {
|
||||
object_instance = Binary_Output_Index_To_Instance(i);
|
||||
if (Binary_Output_Valid_Instance(object_instance)) {
|
||||
if (!Binary_Output_Out_Of_Service(object_instance)) {
|
||||
present_value = Binary_Output_Present_Value(object_instance);
|
||||
if (present_value == BINARY_INACTIVE) {
|
||||
pifacedigital_digital_write(i, 0);
|
||||
if (PiFace_Output_State[i]) {
|
||||
printf("BO-WRITE: OUTPUT[%u]=%d\n", i,
|
||||
BINARY_LIGHTING_PV_OFF);
|
||||
piface_write_output(i, BINARY_LIGHTING_PV_OFF);
|
||||
}
|
||||
} else {
|
||||
pifacedigital_digital_write(i, 1);
|
||||
if (!PiFace_Output_State[i]) {
|
||||
printf("BO-WRITE: OUTPUT[%u]=%d\n", i,
|
||||
BINARY_LIGHTING_PV_OFF);
|
||||
piface_write_output(i, BINARY_LIGHTING_PV_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,12 +294,9 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
BACNET_ADDRESS src = { 0 }; /* address where message came from */
|
||||
uint16_t pdu_len = 0;
|
||||
unsigned timeout = 1; /* milliseconds */
|
||||
time_t last_seconds = 0;
|
||||
time_t current_seconds = 0;
|
||||
uint32_t elapsed_seconds = 0;
|
||||
uint32_t elapsed_milliseconds = 0;
|
||||
uint32_t address_binding_tmr = 0;
|
||||
unsigned timeout_ms = 1; /* milliseconds */
|
||||
unsigned long seconds = 0;
|
||||
unsigned long milliseconds;
|
||||
|
||||
/* allow the device ID to be set */
|
||||
if (argc > 1) {
|
||||
@@ -233,41 +315,42 @@ int main(int argc, char *argv[])
|
||||
atexit(datalink_cleanup);
|
||||
piface_init();
|
||||
atexit(piface_cleanup);
|
||||
/* configure the timeout values */
|
||||
last_seconds = time(NULL);
|
||||
/* broadcast an I-Am on startup */
|
||||
Send_I_Am(&Handler_Transmit_Buffer[0]);
|
||||
/* loop forever */
|
||||
for (;;) {
|
||||
/* input */
|
||||
current_seconds = time(NULL);
|
||||
|
||||
/* returns 0 bytes on timeout */
|
||||
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout);
|
||||
|
||||
pdu_len = datalink_receive(&src, &Rx_Buf[0], MAX_MPDU, timeout_ms);
|
||||
/* process */
|
||||
if (pdu_len) {
|
||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||
}
|
||||
/* at least one second has passed */
|
||||
elapsed_seconds = (uint32_t)(current_seconds - last_seconds);
|
||||
if (elapsed_seconds) {
|
||||
last_seconds = current_seconds;
|
||||
dcc_timer_seconds(elapsed_seconds);
|
||||
datalink_maintenance_timer(elapsed_seconds);
|
||||
dlenv_maintenance_timer(elapsed_seconds);
|
||||
elapsed_milliseconds = elapsed_seconds * 1000;
|
||||
handler_cov_timer_seconds(elapsed_seconds);
|
||||
tsm_timer_milliseconds(elapsed_milliseconds);
|
||||
if (mstimer_expired(&BACnet_Task_Timer)) {
|
||||
mstimer_reset(&BACnet_Task_Timer);
|
||||
/* 1 second tasks */
|
||||
dcc_timer_seconds(1);
|
||||
datalink_maintenance_timer(1);
|
||||
dlenv_maintenance_timer(1);
|
||||
handler_cov_timer_seconds(1);
|
||||
}
|
||||
if (mstimer_expired(&BACnet_TSM_Timer)) {
|
||||
mstimer_reset(&BACnet_TSM_Timer);
|
||||
tsm_timer_milliseconds(mstimer_interval(&BACnet_TSM_Timer));
|
||||
}
|
||||
handler_cov_task();
|
||||
/* scan cache address */
|
||||
address_binding_tmr += elapsed_seconds;
|
||||
if (address_binding_tmr >= 60) {
|
||||
address_cache_timer(address_binding_tmr);
|
||||
address_binding_tmr = 0;
|
||||
if (mstimer_expired(&BACnet_Address_Timer)) {
|
||||
mstimer_reset(&BACnet_Address_Timer);
|
||||
/* address cache */
|
||||
seconds = mstimer_interval(&BACnet_Address_Timer) / 1000;
|
||||
address_cache_timer(seconds);
|
||||
}
|
||||
/* output/input */
|
||||
if (mstimer_expired(&BACnet_Object_Timer)) {
|
||||
mstimer_reset(&BACnet_Object_Timer);
|
||||
milliseconds = mstimer_interval(&BACnet_Object_Timer);
|
||||
Device_Timer(milliseconds);
|
||||
}
|
||||
piface_task();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ SRC = main.c \
|
||||
$(BACNET_OBJECT_DIR)/av.c \
|
||||
$(BACNET_OBJECT_DIR)/bi.c \
|
||||
$(BACNET_OBJECT_DIR)/bo.c \
|
||||
$(BACNET_OBJECT_DIR)/blo.c \
|
||||
$(BACNET_OBJECT_DIR)/bv.c \
|
||||
$(BACNET_OBJECT_DIR)/channel.c \
|
||||
$(BACNET_OBJECT_DIR)/color_object.c \
|
||||
|
||||
+12
-2
@@ -2206,13 +2206,23 @@ int bacapp_snprintf_value(
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
case PROP_RELINQUISH_DEFAULT:
|
||||
if (object_type < OBJECT_PROPRIETARY_MIN) {
|
||||
switch (object_type) {
|
||||
case OBJECT_BINARY_INPUT:
|
||||
case OBJECT_BINARY_OUTPUT:
|
||||
case OBJECT_BINARY_VALUE:
|
||||
ret_val = snprintf(str, str_len, "%s",
|
||||
bactext_binary_present_value_name(
|
||||
value->type.Enumerated));
|
||||
} else {
|
||||
break;
|
||||
case OBJECT_BINARY_LIGHTING_OUTPUT:
|
||||
ret_val = snprintf(str, str_len, "%s",
|
||||
bactext_binary_lighting_pv_name(
|
||||
value->type.Enumerated));
|
||||
break;
|
||||
default:
|
||||
ret_val = snprintf(str, str_len, "%lu",
|
||||
(unsigned long)value->type.Enumerated);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PROP_RELIABILITY:
|
||||
|
||||
@@ -1079,7 +1079,7 @@ typedef enum {
|
||||
PROP_STATE_EXAMPLE_TWO = 257
|
||||
} BACNET_PROPERTY_STATES;
|
||||
|
||||
typedef enum {
|
||||
typedef enum BACnetReliability {
|
||||
RELIABILITY_NO_FAULT_DETECTED = 0,
|
||||
RELIABILITY_NO_SENSOR = 1,
|
||||
RELIABILITY_OVER_RANGE = 2,
|
||||
@@ -2106,6 +2106,7 @@ typedef enum BACnetBinaryLightingPV {
|
||||
BINARY_LIGHTING_PV_WARN_OFF = 3,
|
||||
BINARY_LIGHTING_PV_WARN_RELINQUISH = 4,
|
||||
BINARY_LIGHTING_PV_STOP = 5,
|
||||
BINARY_LIGHTING_PV_MAX = 6,
|
||||
/* -- Enumerated values 0-63 are reserved for definition by ASHRAE.
|
||||
-- Enumerated values 64-255 may be used by others
|
||||
-- subject to the procedures and constraints described in Clause 23. */
|
||||
|
||||
+30
-1
@@ -1750,12 +1750,41 @@ const char *bactext_lighting_operation_name(unsigned index)
|
||||
}
|
||||
}
|
||||
|
||||
bool bactext_bactext_lighting_operation_strtol(const char *search_name, unsigned *found_index)
|
||||
bool bactext_lighting_operation_strtol(const char *search_name, unsigned *found_index)
|
||||
{
|
||||
return bactext_strtol_index(
|
||||
bacnet_lighting_operation_names, search_name, found_index);
|
||||
}
|
||||
|
||||
INDTEXT_DATA bacnet_binary_lighting_pv_names[] = {
|
||||
{ BINARY_LIGHTING_PV_OFF, "off" },
|
||||
{ BINARY_LIGHTING_PV_ON, "on" },
|
||||
{ BINARY_LIGHTING_PV_WARN, "warn" },
|
||||
{ BINARY_LIGHTING_PV_WARN_OFF, "warn-off" },
|
||||
{ BINARY_LIGHTING_PV_WARN_RELINQUISH, "warn-relinquish" },
|
||||
{ BINARY_LIGHTING_PV_STOP, "stop" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
const char *bactext_binary_lighting_pv_name(unsigned index)
|
||||
{
|
||||
if (index < BINARY_LIGHTING_PV_PROPRIETARY_MIN) {
|
||||
return indtext_by_index_default(
|
||||
bacnet_binary_lighting_pv_names, index, ASHRAE_Reserved_String);
|
||||
} else if (index <= BINARY_LIGHTING_PV_PROPRIETARY_MAX) {
|
||||
return Vendor_Proprietary_String;
|
||||
} else {
|
||||
return "Invalid BACnetBinaryLightingPV";
|
||||
}
|
||||
}
|
||||
|
||||
bool bactext_binary_lighting_pv_names_strtol(const char *search_name,
|
||||
unsigned *found_index)
|
||||
{
|
||||
return bactext_strtol_index(
|
||||
bacnet_binary_lighting_pv_names, search_name, found_index);
|
||||
}
|
||||
|
||||
INDTEXT_DATA bacnet_color_operation_names[] = { { BACNET_COLOR_OPERATION_NONE,
|
||||
"none" },
|
||||
{ BACNET_COLOR_OPERATION_FADE_TO_COLOR, "fade-to-color" },
|
||||
|
||||
+10
-1
@@ -201,7 +201,16 @@ extern "C" {
|
||||
unsigned index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bactext_bactext_lighting_operation_strtol(
|
||||
bool bactext_lighting_operation_strtol(
|
||||
const char *search_name,
|
||||
unsigned *found_index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
const char *bactext_binary_lighting_pv_name(
|
||||
unsigned index);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bactext_binary_lighting_pv_names_strtol(
|
||||
const char *search_name,
|
||||
unsigned *found_index);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file
|
||||
* @author Steve Karg
|
||||
* @date 2023
|
||||
* @brief Binary Lighting Output object
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#ifndef BINARY_LIGHTING_OUTPUT_H
|
||||
#define BINARY_LIGHTING_OUTPUT_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacerror.h"
|
||||
#include "bacnet/rp.h"
|
||||
#include "bacnet/wp.h"
|
||||
|
||||
/**
|
||||
* @brief Callback for write value request
|
||||
* @param object_instance - object-instance number of the object
|
||||
* @param old_value - value prior to write
|
||||
* @param value - value of the write
|
||||
*/
|
||||
typedef void (*binary_lighting_output_write_value_callback)(
|
||||
uint32_t object_instance,
|
||||
BACNET_BINARY_LIGHTING_PV old_value,
|
||||
BACNET_BINARY_LIGHTING_PV value);
|
||||
|
||||
/**
|
||||
* @brief Callback for blink warning notification
|
||||
* @param object_instance - object-instance number of the object
|
||||
*/
|
||||
typedef void (*binary_lighting_output_blink_warn_callback)(
|
||||
uint32_t object_instance);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Property_Lists(
|
||||
const int **pRequired, const int **pOptional, const int **pProprietary);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Valid_Instance(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
unsigned Binary_Lighting_Output_Count(void);
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t Binary_Lighting_Output_Index_To_Instance(unsigned index);
|
||||
BACNET_STACK_EXPORT
|
||||
unsigned Binary_Lighting_Output_Instance_To_Index(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Object_Instance_Add(uint32_t instance);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_BINARY_LIGHTING_PV Binary_Lighting_Output_Present_Value(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
unsigned Binary_Lighting_Output_Present_Value_Priority(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Present_Value_Set(uint32_t object_instance,
|
||||
BACNET_BINARY_LIGHTING_PV value,
|
||||
unsigned priority);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Present_Value_Relinquish(
|
||||
uint32_t object_instance, unsigned priority);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_BINARY_LIGHTING_PV Binary_Lighting_Output_Relinquish_Default(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Relinquish_Default_Set(
|
||||
uint32_t object_instance, BACNET_BINARY_LIGHTING_PV value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_RELIABILITY Binary_Lighting_Output_Reliability(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Reliability_Set(
|
||||
uint32_t object_instance, BACNET_RELIABILITY value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Object_Name(
|
||||
uint32_t object_instance, BACNET_CHARACTER_STRING *object_name);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Name_Set(uint32_t object_instance, char *new_name);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
char *Binary_Lighting_Output_Description(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Description_Set(uint32_t instance, char *new_name);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Out_Of_Service(uint32_t instance);
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Out_Of_Service_Set(
|
||||
uint32_t instance, bool oos_flag);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_BINARY_LIGHTING_PV Binary_Lighting_Output_Lighting_Command_Target_Value(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
unsigned Binary_Lighting_Output_Lighting_Command_Target_Priority(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Lighting_Command_Set(
|
||||
uint32_t object_instance, BACNET_BINARY_LIGHTING_PV value, unsigned priority);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
BACNET_BINARY_LIGHTING_PV Binary_Lighting_Output_Feedback_Value(
|
||||
uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Feedback_Value_Set(
|
||||
uint32_t object_instance, BACNET_BINARY_LIGHTING_PV value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Blink_Warn_Enable(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Blink_Warn_Enable_Set(
|
||||
uint32_t object_instance, bool enable);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t Binary_Lighting_Output_Egress_Time(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Egress_Time_Set(
|
||||
uint32_t object_instance, uint32_t seconds);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Egress_Active(uint32_t object_instance);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Timer(
|
||||
uint32_t object_instance, uint16_t milliseconds);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Write_Value_Callback_Set(
|
||||
binary_lighting_output_write_value_callback cb);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Blink_Warn_Callback_Set(
|
||||
binary_lighting_output_blink_warn_callback cb);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
uint32_t Binary_Lighting_Output_Create(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Delete(uint32_t object_instance);
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Cleanup(void);
|
||||
BACNET_STACK_EXPORT
|
||||
void Binary_Lighting_Output_Init(void);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int Binary_Lighting_Output_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata);
|
||||
BACNET_STACK_EXPORT
|
||||
bool Binary_Lighting_Output_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
@@ -51,6 +51,9 @@
|
||||
#include "bacnet/basic/object/ao.h"
|
||||
#include "bacnet/basic/object/av.h"
|
||||
#include "bacnet/basic/object/bi.h"
|
||||
#if (BACNET_PROTOCOL_REVISION >= 16)
|
||||
#include "bacnet/basic/object/blo.h"
|
||||
#endif
|
||||
#include "bacnet/basic/object/bo.h"
|
||||
#include "bacnet/basic/object/bv.h"
|
||||
#include "bacnet/basic/object/channel.h"
|
||||
@@ -267,6 +270,20 @@ static object_functions_t My_Object_Table[] = {
|
||||
NULL /* Add_List_Element */, NULL /* Remove_List_Element */,
|
||||
Channel_Create, Channel_Delete, NULL /* Timer */ },
|
||||
#endif
|
||||
#if (BACNET_PROTOCOL_REVISION >= 16)
|
||||
{ OBJECT_BINARY_LIGHTING_OUTPUT, Binary_Lighting_Output_Init,
|
||||
Binary_Lighting_Output_Count, Binary_Lighting_Output_Index_To_Instance,
|
||||
Binary_Lighting_Output_Valid_Instance,
|
||||
Binary_Lighting_Output_Object_Name,
|
||||
Binary_Lighting_Output_Read_Property,
|
||||
Binary_Lighting_Output_Write_Property,
|
||||
Binary_Lighting_Output_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 */,
|
||||
Binary_Lighting_Output_Create, Binary_Lighting_Output_Delete,
|
||||
Binary_Lighting_Output_Timer },
|
||||
#endif
|
||||
#if (BACNET_PROTOCOL_REVISION >= 24)
|
||||
{ OBJECT_COLOR, Color_Init, Color_Count, Color_Index_To_Instance,
|
||||
Color_Valid_Instance, Color_Object_Name, Color_Read_Property,
|
||||
@@ -2201,6 +2218,7 @@ void Device_Init(object_functions_t *object_table)
|
||||
pObject++;
|
||||
}
|
||||
/* create some dynamically created objects as examples */
|
||||
if (!object_table) {
|
||||
pObject = Object_Table;
|
||||
while (pObject->Object_Type < MAX_BACNET_OBJECT_TYPE) {
|
||||
if (pObject->Object_Create) {
|
||||
@@ -2208,6 +2226,7 @@ void Device_Init(object_functions_t *object_table)
|
||||
}
|
||||
pObject++;
|
||||
}
|
||||
}
|
||||
#if (BACNET_PROTOCOL_REVISION >= 14)
|
||||
Channel_Write_Property_Internal_Callback_Set(Device_Write_Property);
|
||||
#endif
|
||||
|
||||
@@ -48,10 +48,6 @@
|
||||
/* me! */
|
||||
#include "bacnet/basic/object/lo.h"
|
||||
|
||||
#ifndef MAX_LIGHTING_OUTPUTS
|
||||
#define MAX_LIGHTING_OUTPUTS 8
|
||||
#endif
|
||||
|
||||
struct object_data {
|
||||
float Present_Value;
|
||||
float Tracking_Value;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define KEYLIST_H
|
||||
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "key.h"
|
||||
#include "bacnet/basic/sys/key.h"
|
||||
|
||||
/* This is a key sorted linked list data library that */
|
||||
/* uses a key or index to access the data. */
|
||||
|
||||
@@ -113,6 +113,7 @@ list(APPEND testdirs
|
||||
bacnet/basic/object/av
|
||||
bacnet/basic/object/bacfile
|
||||
bacnet/basic/object/bi
|
||||
bacnet/basic/object/blo
|
||||
bacnet/basic/object/bo
|
||||
bacnet/basic/object/bv
|
||||
bacnet/basic/object/channel
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# 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}/ztest/include
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
# File(s) under test
|
||||
${SRC_DIR}/bacnet/basic/object/blo.c
|
||||
# Support files and stubs (pathname alphabetical)
|
||||
${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/bacerror.c
|
||||
${SRC_DIR}/bacnet/bacint.c
|
||||
${SRC_DIR}/bacnet/bacreal.c
|
||||
${SRC_DIR}/bacnet/bacstr.c
|
||||
${SRC_DIR}/bacnet/bactext.c
|
||||
${SRC_DIR}/bacnet/basic/sys/bigend.c
|
||||
${SRC_DIR}/bacnet/basic/sys/days.c
|
||||
${SRC_DIR}/bacnet/basic/sys/keylist.c
|
||||
${SRC_DIR}/bacnet/basic/sys/linear.c
|
||||
${SRC_DIR}/bacnet/datetime.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.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
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
../mock/device_mock.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
m)
|
||||
@@ -0,0 +1,277 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for object
|
||||
* @author Steve Karg <skarg@users.sourceforge.net>
|
||||
* @date September 2023
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
#include <zephyr/ztest.h>
|
||||
#include <bacnet/bactext.h>
|
||||
#include <bacnet/basic/object/blo.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Test
|
||||
*/
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(lo_tests, testBinaryLightingOutput)
|
||||
#else
|
||||
static void testBinaryLightingOutput(void)
|
||||
#endif
|
||||
{
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
int len = 0, test_len = 0;
|
||||
BACNET_READ_PROPERTY_DATA rpdata;
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
const int *pRequired = NULL;
|
||||
const int *pOptional = NULL;
|
||||
const int *pProprietary = NULL;
|
||||
const uint32_t instance = 123;
|
||||
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||
bool status = false;
|
||||
unsigned index;
|
||||
|
||||
Binary_Lighting_Output_Init();
|
||||
Binary_Lighting_Output_Create(instance);
|
||||
status = Binary_Lighting_Output_Valid_Instance(instance);
|
||||
zassert_true(status, NULL);
|
||||
index = Binary_Lighting_Output_Instance_To_Index(instance);
|
||||
zassert_equal(index, 0, NULL);
|
||||
|
||||
rpdata.application_data = &apdu[0];
|
||||
rpdata.application_data_len = sizeof(apdu);
|
||||
rpdata.object_type = OBJECT_BINARY_LIGHTING_OUTPUT;
|
||||
rpdata.object_instance = instance;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
|
||||
Binary_Lighting_Output_Property_Lists(
|
||||
&pRequired, &pOptional, &pProprietary);
|
||||
while ((*pRequired) >= 0) {
|
||||
rpdata.object_property = *pRequired;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Binary_Lighting_Output_Read_Property(&rpdata);
|
||||
zassert_not_equal(len, BACNET_STATUS_ERROR,
|
||||
"property '%s': failed to ReadProperty!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
if (len >= 0) {
|
||||
test_len = bacapp_decode_known_property(rpdata.application_data,
|
||||
len, &value, rpdata.object_type, rpdata.object_property);
|
||||
if (rpdata.object_property != PROP_PRIORITY_ARRAY) {
|
||||
zassert_equal(len, test_len,
|
||||
"property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
/* check WriteProperty properties */
|
||||
wpdata.object_type = rpdata.object_type;
|
||||
wpdata.object_instance = rpdata.object_instance;
|
||||
wpdata.object_property = rpdata.object_property;
|
||||
wpdata.array_index = rpdata.array_index;
|
||||
memcpy(&wpdata.application_data, rpdata.application_data, MAX_APDU);
|
||||
wpdata.application_data_len = len;
|
||||
wpdata.error_code = ERROR_CODE_SUCCESS;
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
if (!status) {
|
||||
/* verify WriteProperty property is known */
|
||||
zassert_not_equal(wpdata.error_code,
|
||||
ERROR_CODE_UNKNOWN_PROPERTY,
|
||||
"property '%s': WriteProperty Unknown!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
}
|
||||
pRequired++;
|
||||
}
|
||||
while ((*pOptional) != -1) {
|
||||
rpdata.object_property = *pOptional;
|
||||
rpdata.array_index = BACNET_ARRAY_ALL;
|
||||
len = Binary_Lighting_Output_Read_Property(&rpdata);
|
||||
zassert_not_equal(len, BACNET_STATUS_ERROR,
|
||||
"property '%s': failed to ReadProperty!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
if (len > 0) {
|
||||
test_len = bacapp_decode_application_data(rpdata.application_data,
|
||||
(uint8_t)rpdata.application_data_len, &value);
|
||||
zassert_equal(len, test_len, "property '%s': failed to decode!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
/* check WriteProperty properties */
|
||||
wpdata.object_type = rpdata.object_type;
|
||||
wpdata.object_instance = rpdata.object_instance;
|
||||
wpdata.object_property = rpdata.object_property;
|
||||
wpdata.array_index = rpdata.array_index;
|
||||
memcpy(&wpdata.application_data, rpdata.application_data, MAX_APDU);
|
||||
wpdata.application_data_len = len;
|
||||
wpdata.error_code = ERROR_CODE_SUCCESS;
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
if (!status) {
|
||||
/* verify WriteProperty property is known */
|
||||
zassert_not_equal(wpdata.error_code,
|
||||
ERROR_CODE_UNKNOWN_PROPERTY,
|
||||
"property '%s': WriteProperty Unknown!\n",
|
||||
bactext_property_name(rpdata.object_property));
|
||||
}
|
||||
}
|
||||
pOptional++;
|
||||
}
|
||||
/* check for unsupported property - use ALL */
|
||||
rpdata.object_property = PROP_ALL;
|
||||
len = Binary_Lighting_Output_Read_Property(&rpdata);
|
||||
zassert_equal(len, BACNET_STATUS_ERROR, NULL);
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
zassert_false(status, NULL);
|
||||
/* check the delete function */
|
||||
status = Binary_Lighting_Output_Delete(instance);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t object_instance;
|
||||
BACNET_BINARY_LIGHTING_PV old_pv;
|
||||
BACNET_BINARY_LIGHTING_PV pv;
|
||||
uint32_t count;
|
||||
} BLO_Value;
|
||||
static void Binary_Lighting_Output_Write_Value_Handler(uint32_t object_instance,
|
||||
BACNET_BINARY_LIGHTING_PV old_value,
|
||||
BACNET_BINARY_LIGHTING_PV value)
|
||||
{
|
||||
BLO_Value.object_instance = object_instance;
|
||||
BLO_Value.old_pv = old_value;
|
||||
BLO_Value.pv = value;
|
||||
BLO_Value.count++;
|
||||
}
|
||||
|
||||
static struct {
|
||||
uint32_t object_instance;
|
||||
uint32_t count;
|
||||
} BLO_Blink;
|
||||
static void Binary_Lighting_Output_Blink_Warn_Handler(uint32_t object_instance)
|
||||
{
|
||||
BLO_Blink.object_instance = object_instance;
|
||||
BLO_Blink.count++;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST(lo_tests, testBinaryLightingOutputBlink)
|
||||
#else
|
||||
static void testBinaryLightingOutputBlink(void)
|
||||
#endif
|
||||
{
|
||||
const uint32_t object_instance = 123;
|
||||
bool status = false;
|
||||
uint16_t milliseconds, milliseconds_elapsed;
|
||||
BACNET_BINARY_LIGHTING_PV pv, test_pv, expect_pv;
|
||||
unsigned test_priority;
|
||||
BACNET_WRITE_PROPERTY_DATA wpdata = { 0 };
|
||||
BACNET_APPLICATION_DATA_VALUE value = { 0 };
|
||||
|
||||
Binary_Lighting_Output_Init();
|
||||
Binary_Lighting_Output_Create(object_instance);
|
||||
status = Binary_Lighting_Output_Valid_Instance(object_instance);
|
||||
zassert_true(status, NULL);
|
||||
Binary_Lighting_Output_Write_Value_Callback_Set(
|
||||
Binary_Lighting_Output_Write_Value_Handler);
|
||||
Binary_Lighting_Output_Blink_Warn_Callback_Set(
|
||||
Binary_Lighting_Output_Blink_Warn_Handler);
|
||||
/* check the blink warning engine at defaults */
|
||||
milliseconds_elapsed = 100;
|
||||
expect_pv = BINARY_LIGHTING_PV_OFF;
|
||||
Binary_Lighting_Output_Timer(object_instance, milliseconds_elapsed);
|
||||
zassert_equal(BLO_Blink.count, 0, "count=%u", BLO_Blink.count);
|
||||
zassert_equal(BLO_Value.count, 0, "count=%u", BLO_Value.count);
|
||||
zassert_equal(BLO_Value.pv, expect_pv, "value=%u", BLO_Value.pv);
|
||||
|
||||
/* check WriteProperty properties */
|
||||
wpdata.object_type = OBJECT_BINARY_LIGHTING_OUTPUT;
|
||||
wpdata.object_instance = object_instance;
|
||||
wpdata.object_property = PROP_PRESENT_VALUE;
|
||||
wpdata.priority = BACNET_MAX_PRIORITY;
|
||||
wpdata.array_index = BACNET_ARRAY_ALL;
|
||||
wpdata.error_class = ERROR_CLASS_PROPERTY;
|
||||
wpdata.error_code = ERROR_CODE_SUCCESS;
|
||||
/* ON */
|
||||
pv = BINARY_LIGHTING_PV_ON;
|
||||
expect_pv = BINARY_LIGHTING_PV_ON;
|
||||
wpdata.application_data_len =
|
||||
encode_application_enumerated(wpdata.application_data, pv);
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
zassert_true(status, NULL);
|
||||
milliseconds = 2000;
|
||||
milliseconds_elapsed = 100;
|
||||
while (milliseconds) {
|
||||
Binary_Lighting_Output_Timer(object_instance, milliseconds_elapsed);
|
||||
test_pv = Binary_Lighting_Output_Present_Value(object_instance);
|
||||
zassert_equal(expect_pv, test_pv, NULL);
|
||||
test_priority =
|
||||
Binary_Lighting_Output_Present_Value_Priority(object_instance);
|
||||
zassert_equal(wpdata.priority, test_priority,
|
||||
"priority=%u test_priority=%u", wpdata.priority, test_priority);
|
||||
zassert_equal(BLO_Blink.count, 0, NULL);
|
||||
zassert_equal(BLO_Value.count, 1, "count=%u", BLO_Value.count);
|
||||
zassert_equal(BLO_Value.pv, expect_pv, NULL);
|
||||
milliseconds -= milliseconds_elapsed;
|
||||
}
|
||||
/* OFF */
|
||||
pv = BINARY_LIGHTING_PV_OFF;
|
||||
expect_pv = BINARY_LIGHTING_PV_OFF;
|
||||
wpdata.application_data_len =
|
||||
encode_application_enumerated(wpdata.application_data, pv);
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
zassert_true(status, NULL);
|
||||
milliseconds = 2000;
|
||||
milliseconds_elapsed = 100;
|
||||
while (milliseconds) {
|
||||
Binary_Lighting_Output_Timer(object_instance, milliseconds_elapsed);
|
||||
test_pv = Binary_Lighting_Output_Present_Value(object_instance);
|
||||
zassert_equal(expect_pv, test_pv, NULL);
|
||||
test_priority =
|
||||
Binary_Lighting_Output_Present_Value_Priority(object_instance);
|
||||
zassert_equal(wpdata.priority, test_priority,
|
||||
"priority=%u test_priority=%u", wpdata.priority, test_priority);
|
||||
zassert_equal(BLO_Blink.count, 0, NULL);
|
||||
zassert_equal(BLO_Value.count, 2, "count=%u", BLO_Value.count);
|
||||
zassert_equal(BLO_Value.pv, expect_pv, NULL);
|
||||
milliseconds -= milliseconds_elapsed;
|
||||
}
|
||||
/* WARN - already off */
|
||||
pv = BINARY_LIGHTING_PV_WARN;
|
||||
expect_pv = BINARY_LIGHTING_PV_OFF;
|
||||
wpdata.application_data_len =
|
||||
encode_application_enumerated(wpdata.application_data, pv);
|
||||
status = Binary_Lighting_Output_Write_Property(&wpdata);
|
||||
zassert_true(status, NULL);
|
||||
milliseconds = 2000;
|
||||
milliseconds_elapsed = 100;
|
||||
while (milliseconds) {
|
||||
Binary_Lighting_Output_Timer(object_instance, milliseconds_elapsed);
|
||||
test_pv = Binary_Lighting_Output_Present_Value(object_instance);
|
||||
zassert_equal(expect_pv, test_pv, "pv=%u", test_pv);
|
||||
test_priority =
|
||||
Binary_Lighting_Output_Present_Value_Priority(object_instance);
|
||||
zassert_equal(wpdata.priority, test_priority,
|
||||
"priority=%u test_priority=%u", wpdata.priority, test_priority);
|
||||
zassert_equal(BLO_Blink.count, 0, NULL);
|
||||
zassert_equal(BLO_Value.count, 2, "count=%u", BLO_Value.count);
|
||||
zassert_equal(BLO_Value.pv, expect_pv, NULL);
|
||||
milliseconds -= milliseconds_elapsed;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_ZTEST_NEW_API)
|
||||
ZTEST_SUITE(blo_tests, NULL, NULL, NULL, NULL, NULL);
|
||||
#else
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(blo_tests, ztest_unit_test(testBinaryLightingOutput),
|
||||
ztest_unit_test(testBinaryLightingOutputBlink));
|
||||
|
||||
ztest_run_test_suite(blo_tests);
|
||||
}
|
||||
#endif
|
||||
@@ -52,6 +52,7 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/basic/object/ao.c
|
||||
${SRC_DIR}/bacnet/basic/object/av.c
|
||||
${SRC_DIR}/bacnet/basic/object/bi.c
|
||||
${SRC_DIR}/bacnet/basic/object/blo.c
|
||||
${SRC_DIR}/bacnet/basic/object/bo.c
|
||||
${SRC_DIR}/bacnet/basic/object/bv.c
|
||||
${SRC_DIR}/bacnet/basic/object/channel.c
|
||||
|
||||
Reference in New Issue
Block a user