Schedule encoding/decoding (#319)
* schedule: add decode_daily_schedule() and encode_daily_schedule() * schedule: encode/decode implemented + add to bacapp * add safe encode/decode functions for timevalue, schedule function renaming * fix unit tests build failing * add IDEA and test temporary files to .gitignore * try to make "deprecated" work in MSVC * add WeeklySchedule compare function * add bacnet_weeklyschedule_context_decode() * Add basic test for WeeklySchedule * Fix WeeklySchedule parsing and snprintf, decoder verified with real hardware * try to fix windows build * improve boolean parsing in 'bacapp_parse_application_data' * add parse function for weekly schedule * allow types > 16 in bacwp, show the decoded value before sending * add bacapp binaries to gitignore * remove bacwp logging * Add error checking to bacapp_parse_application_data * try to fix windows build * fix avr build * Fix error handling in RP Ack * add singleDay flag * show day name in single day weeklyschedule snprintf * show weeklyschedule inner tag in snprintf * improve weeklyschedule parsing and printing, supports type names now * add weekly schedule to bacapp_decode_data * move bacnet/bacnet_plat_compat.h to bacnet/basic/sys/platform.h * disable tag limit also in bacwpm * add ifdef's around strtoX helper functions in bacapp * move strtox to BACAPP_PRINT_ENABLED ifdef in bacapp * fix stm32 makefiles * fix at91sam7s build * use BACNET_UNSIGNED_INTEGER in BACnet_Short_Application_Data_Value * fix capitalization in BACnet_Daily_Schedule * add name to BACNET_TIME_VALUE struct * change bacwp bacwpm to use bacapp_known_property_tag() * fix some macros in bacdcode missing parentheses * Remove dummy fields from BACNET_SHORT_APPLICATION_DATA_VALUE, replace remaining uses of upcasting (adds extra overhead but is maybe safer), rename short DV to Primitive * fix new ci warnings * more fixes for ancient C * fix tests no longer building * primitive value renamed to shorter name
This commit is contained in:
+39
@@ -70,3 +70,42 @@ Release/
|
||||
apps/piface/libmcp23s17/
|
||||
apps/piface/libpifacedigital/
|
||||
|
||||
/test/build/
|
||||
/cmake-build-*
|
||||
/.idea
|
||||
|
||||
/apps/abort/bacabort
|
||||
/apps/ack-alarm/bacackalarm
|
||||
/apps/readfile/bacarf
|
||||
/apps/writefile/bacawf
|
||||
/apps/dcc/bacdcc
|
||||
/apps/epics/bacepics
|
||||
/apps/error/bacerror
|
||||
/apps/event/bacevent
|
||||
/apps/getevent/bacge
|
||||
/apps/iam/baciam
|
||||
/apps/iamrouter/baciamr
|
||||
/apps/initrouter/bacinitr
|
||||
/apps/netnumis/bacnni
|
||||
/apps/server-client/bacpoll
|
||||
/apps/readbdt/bacrbdt
|
||||
/apps/reinit/bacrd
|
||||
/apps/readfdt/bacrfdt
|
||||
/apps/readprop/bacrp
|
||||
/apps/readpropm/bacrpm
|
||||
/apps/readrange/bacrr
|
||||
/apps/scov/bacscov
|
||||
/apps/server/bacserv
|
||||
/apps/timesync/bacts
|
||||
/apps/ucov/bacucov
|
||||
/apps/uevent/bacuevent
|
||||
/apps/uptransfer/bacupt
|
||||
/apps/writebdt/bacwbdt
|
||||
/apps/whohas/bacwh
|
||||
/apps/whois/bacwi
|
||||
/apps/whatisnetnum/bacwinn
|
||||
/apps/whoisrouter/bacwir
|
||||
/apps/writeprop/bacwp
|
||||
/apps/writepropm/bacwpm
|
||||
/apps/mstpcap/mstpcap
|
||||
/apps/mstpcrc/mstpcrc
|
||||
|
||||
@@ -124,6 +124,10 @@ add_library(${PROJECT_NAME}
|
||||
src/bacnet/bactext.h
|
||||
src/bacnet/bactimevalue.c
|
||||
src/bacnet/bactimevalue.h
|
||||
src/bacnet/dailyschedule.c
|
||||
src/bacnet/dailyschedule.h
|
||||
src/bacnet/weeklyschedule.c
|
||||
src/bacnet/weeklyschedule.h
|
||||
$<$<BOOL:${BACDL_BIP}>:src/bacnet/basic/bbmd/h_bbmd.c>
|
||||
$<$<BOOL:${BACDL_BIP}>:src/bacnet/basic/bbmd/h_bbmd.h>
|
||||
$<$<BOOL:${BACDL_BIP6}>:src/bacnet/basic/bbmd6/h_bbmd6.c>
|
||||
|
||||
+33
-7
@@ -337,20 +337,46 @@ int main(int argc, char *argv[])
|
||||
value_string = argv[tag_value_arg];
|
||||
tag_value_arg++;
|
||||
args_remaining--;
|
||||
/* printf("tag[%d]=%u value[%d]=%s\n",
|
||||
i, property_tag, i, value_string); */
|
||||
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
|
||||
if (property_tag < 0) {
|
||||
property_tag = bacapp_known_property_tag(Target_Object_Type, Target_Object_Property);
|
||||
} else if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
|
||||
fprintf(stderr, "Error: tag=%u - it must be less than %u\n",
|
||||
property_tag, MAX_BACNET_APPLICATION_TAG);
|
||||
return 1;
|
||||
}
|
||||
status = bacapp_parse_application_data(
|
||||
property_tag, value_string, &Target_Object_Property_Value[i]);
|
||||
if (!status) {
|
||||
if (property_tag >= 0) {
|
||||
status = bacapp_parse_application_data(
|
||||
property_tag, value_string, &Target_Object_Property_Value[i]);
|
||||
if (!status) {
|
||||
/* FIXME: show the expected entry format for the tag */
|
||||
fprintf(stderr, "Error: unable to parse the tag value\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* FIXME: show the expected entry format for the tag */
|
||||
fprintf(stderr, "Error: unable to parse the tag value\n");
|
||||
fprintf(stderr, "Error: unable to parse the known property"
|
||||
" \"%s\"\r\n", value_string);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Print the written value (for debug)
|
||||
#if 0
|
||||
fprintf(stderr, "Writing: ");
|
||||
BACNET_OBJECT_PROPERTY_VALUE dummy_opv = {
|
||||
.value = &Target_Object_Property_Value[i],
|
||||
.array_index = Target_Object_Property_Index,
|
||||
};
|
||||
bacapp_print_value(stderr, &dummy_opv);
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
uint8_t apdu[1000];
|
||||
int len = bacapp_encode_application_data(apdu, &Target_Object_Property_Value[i]);
|
||||
for(int q=0;q<len;q++) {
|
||||
printf("%02x ", apdu[q]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
Target_Object_Property_Value[i].next = NULL;
|
||||
if (i > 0) {
|
||||
Target_Object_Property_Value[i - 1].next =
|
||||
|
||||
+14
-5
@@ -427,16 +427,25 @@ int main(int argc, char *argv[])
|
||||
if (Verbose) {
|
||||
printf("tag=%u value=%s\n", property_tag, value_string);
|
||||
}
|
||||
if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
|
||||
if (property_tag < 0) {
|
||||
property_tag = bacapp_known_property_tag(wpm_object->object_type, wpm_property->propertyIdentifier);
|
||||
} else if (property_tag >= MAX_BACNET_APPLICATION_TAG) {
|
||||
fprintf(stderr, "Error: tag=%u - it must be less than %u\n",
|
||||
property_tag, MAX_BACNET_APPLICATION_TAG);
|
||||
return 1;
|
||||
}
|
||||
status = bacapp_parse_application_data(
|
||||
property_tag, value_string, &wpm_property->value);
|
||||
if (!status) {
|
||||
if (property_tag >= 0) {
|
||||
status = bacapp_parse_application_data(
|
||||
property_tag, value_string, &wpm_property->value);
|
||||
if (!status) {
|
||||
/* FIXME: show the expected entry format for the tag */
|
||||
fprintf(stderr, "Error: unable to parse the tag value\n");
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
/* FIXME: show the expected entry format for the tag */
|
||||
fprintf(stderr, "Error: unable to parse the tag value\n");
|
||||
fprintf(stderr, "Error: unable to parse the known property"
|
||||
" \"%s\"\r\n", value_string);
|
||||
return 1;
|
||||
}
|
||||
wpm_property->value.next = NULL;
|
||||
|
||||
@@ -107,6 +107,9 @@ CORESRC = $(BACNET_CORE)/abort.c \
|
||||
$(BACNET_CORE)/rp.c \
|
||||
$(BACNET_CORE)/rpm.c \
|
||||
$(BACNET_CORE)/timestamp.c \
|
||||
$(BACNET_CORE)/weeklyschedule.c \
|
||||
$(BACNET_CORE)/dailyschedule.c \
|
||||
$(BACNET_CORE)/bactimevalue.c \
|
||||
$(BACNET_CORE)/whohas.c \
|
||||
$(BACNET_CORE)/whois.c \
|
||||
$(BACNET_CORE)/wp.c
|
||||
|
||||
@@ -76,6 +76,9 @@ BACNET_SRC = \
|
||||
$(BACNET_CORE)/rp.c \
|
||||
$(BACNET_CORE)/rpm.c \
|
||||
$(BACNET_CORE)/timestamp.c \
|
||||
$(BACNET_CORE)/weeklyschedule.c \
|
||||
$(BACNET_CORE)/dailyschedule.c \
|
||||
$(BACNET_CORE)/bactimevalue.c \
|
||||
$(BACNET_CORE)/whohas.c \
|
||||
$(BACNET_CORE)/whois.c \
|
||||
$(BACNET_CORE)/wp.c
|
||||
|
||||
@@ -74,6 +74,9 @@ BACNET_SRC = \
|
||||
$(BACNET_CORE)/rp.c \
|
||||
$(BACNET_CORE)/rpm.c \
|
||||
$(BACNET_CORE)/timestamp.c \
|
||||
$(BACNET_CORE)/weeklyschedule.c \
|
||||
$(BACNET_CORE)/dailyschedule.c \
|
||||
$(BACNET_CORE)/bactimevalue.c \
|
||||
$(BACNET_CORE)/whohas.c \
|
||||
$(BACNET_CORE)/whois.c \
|
||||
$(BACNET_CORE)/wp.c
|
||||
|
||||
+575
-26
@@ -37,6 +37,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for strtol */
|
||||
#include <ctype.h> /* for isalnum */
|
||||
#include <errno.h>
|
||||
#ifdef __STDC_ISO_10646__
|
||||
#include <wchar.h>
|
||||
#include <wctype.h>
|
||||
@@ -52,6 +53,8 @@
|
||||
#include "bacnet/bacstr.h"
|
||||
#include "bacnet/lighting.h"
|
||||
#include "bacnet/hostnport.h"
|
||||
#include "bacnet/weeklyschedule.h"
|
||||
#include "bacnet/basic/sys/platform.h"
|
||||
|
||||
/** @file bacapp.c Utilities for the BACnet_Application_Data_Value */
|
||||
|
||||
@@ -171,6 +174,11 @@ int bacapp_encode_application_data(
|
||||
apdu_len = color_command_encode(
|
||||
apdu, &value->type.Color_Command);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule */
|
||||
apdu_len = bacnet_weeklyschedule_encode(
|
||||
apdu, &value->type.Weekly_Schedule);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||
/* BACnetHostNPort */
|
||||
apdu_len = host_n_port_encode(apdu,
|
||||
@@ -318,6 +326,10 @@ int bacapp_decode_data(uint8_t *apdu,
|
||||
len = color_command_decode(
|
||||
apdu, len_value_type, NULL, &value->type.Color_Command);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
len = bacnet_weeklyschedule_decode(
|
||||
apdu, len_value_type, &value->type.Weekly_Schedule);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||
len = host_n_port_decode(
|
||||
apdu, len_value_type, NULL,
|
||||
@@ -638,6 +650,11 @@ int bacapp_encode_context_data_value(uint8_t *apdu,
|
||||
apdu_len = xy_color_context_encode(
|
||||
apdu, context_tag_number, &value->type.XY_Color);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule */
|
||||
apdu_len = bacnet_weeklyschedule_context_encode(
|
||||
apdu, context_tag_number, &value->type.Weekly_Schedule);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
||||
/* BACnetColorCommand */
|
||||
apdu_len = color_command_context_encode(
|
||||
@@ -1011,6 +1028,142 @@ static int decode_priority_value(uint8_t *apdu,
|
||||
#endif
|
||||
|
||||
#if defined(BACAPP_TYPES_EXTRA)
|
||||
int bacapp_known_property_tag(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
BACNET_PROPERTY_ID property)
|
||||
{
|
||||
switch (property) {
|
||||
case PROP_MEMBER_OF:
|
||||
case PROP_ZONE_MEMBERS:
|
||||
case PROP_DOOR_MEMBERS:
|
||||
case PROP_SUBORDINATE_LIST:
|
||||
case PROP_ACCESS_EVENT_CREDENTIAL:
|
||||
case PROP_ACCESS_DOORS:
|
||||
case PROP_ZONE_FROM:
|
||||
case PROP_ZONE_TO:
|
||||
case PROP_CREDENTIALS_IN_ZONE:
|
||||
case PROP_LAST_CREDENTIAL_ADDED:
|
||||
case PROP_LAST_CREDENTIAL_REMOVED:
|
||||
case PROP_ENTRY_POINTS:
|
||||
case PROP_EXIT_POINTS:
|
||||
case PROP_MEMBERS:
|
||||
case PROP_CREDENTIALS:
|
||||
case PROP_ACCOMPANIMENT:
|
||||
case PROP_BELONGS_TO:
|
||||
case PROP_LAST_ACCESS_POINT:
|
||||
/* Properties using BACnetDeviceObjectReference */
|
||||
return BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE;
|
||||
|
||||
case PROP_TIME_OF_ACTIVE_TIME_RESET:
|
||||
case PROP_TIME_OF_STATE_COUNT_RESET:
|
||||
case PROP_CHANGE_OF_STATE_TIME:
|
||||
case PROP_MAXIMUM_VALUE_TIMESTAMP:
|
||||
case PROP_MINIMUM_VALUE_TIMESTAMP:
|
||||
case PROP_VALUE_CHANGE_TIME:
|
||||
case PROP_START_TIME:
|
||||
case PROP_STOP_TIME:
|
||||
case PROP_MODIFICATION_DATE:
|
||||
case PROP_UPDATE_TIME:
|
||||
case PROP_COUNT_CHANGE_TIME:
|
||||
case PROP_LAST_CREDENTIAL_ADDED_TIME:
|
||||
case PROP_LAST_CREDENTIAL_REMOVED_TIME:
|
||||
case PROP_ACTIVATION_TIME:
|
||||
case PROP_EXPIRATION_TIME:
|
||||
case PROP_LAST_USE_TIME:
|
||||
/* Properties using BACnetDateTime value */
|
||||
return BACNET_APPLICATION_TAG_DATETIME;
|
||||
|
||||
case PROP_OBJECT_PROPERTY_REFERENCE:
|
||||
case PROP_LOG_DEVICE_OBJECT_PROPERTY:
|
||||
case PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES:
|
||||
/* Properties using BACnetDeviceObjectPropertyReference */
|
||||
return BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE;
|
||||
|
||||
case PROP_MANIPULATED_VARIABLE_REFERENCE:
|
||||
case PROP_CONTROLLED_VARIABLE_REFERENCE:
|
||||
case PROP_INPUT_REFERENCE:
|
||||
/* Properties using BACnetObjectPropertyReference */
|
||||
return BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE;
|
||||
|
||||
case PROP_EVENT_TIME_STAMPS:
|
||||
case PROP_LAST_RESTORE_TIME:
|
||||
case PROP_TIME_OF_DEVICE_RESTART:
|
||||
case PROP_ACCESS_EVENT_TIME:
|
||||
/* Properties using BACnetTimeStamp */
|
||||
return BACNET_APPLICATION_TAG_TIMESTAMP;
|
||||
|
||||
case PROP_DEFAULT_COLOR:
|
||||
/* Properties using BACnetxyColor */
|
||||
return BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
|
||||
case PROP_TRACKING_VALUE:
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (object_type == OBJECT_COLOR) {
|
||||
/* Properties using BACnetxyColor */
|
||||
return BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
}
|
||||
return -1;
|
||||
|
||||
case PROP_COLOR_COMMAND:
|
||||
/* Properties using BACnetColorCommand */
|
||||
return BACNET_APPLICATION_TAG_COLOR_COMMAND;
|
||||
|
||||
case PROP_LIGHTING_COMMAND:
|
||||
/* Properties using BACnetLightingCommand */
|
||||
return BACNET_APPLICATION_TAG_LIGHTING_COMMAND;
|
||||
|
||||
case PROP_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule ([7] BACnetDailySchedule*/
|
||||
return BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE;
|
||||
|
||||
case PROP_PRIORITY_ARRAY:
|
||||
/* [16] BACnetPriorityValue : 16x values (simple property) */
|
||||
return -1;
|
||||
|
||||
case PROP_LIST_OF_GROUP_MEMBERS:
|
||||
/* Properties using ReadAccessSpecification */
|
||||
return -1;
|
||||
|
||||
case PROP_EXCEPTION_SCHEDULE:
|
||||
/* BACnetSpecialEvent (Schedule) */
|
||||
return -1;
|
||||
|
||||
case PROP_DATE_LIST:
|
||||
/* FIXME: Properties using : BACnetCalendarEntry */
|
||||
return -1;
|
||||
|
||||
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
|
||||
/* FIXME: BACnetCOVSubscription */
|
||||
return -1;
|
||||
|
||||
case PROP_EFFECTIVE_PERIOD:
|
||||
/* FIXME: Properties using BACnetDateRange (Schedule) */
|
||||
return -1;
|
||||
|
||||
case PROP_RECIPIENT_LIST:
|
||||
/* FIXME: Properties using BACnetDestination */
|
||||
return -1;
|
||||
|
||||
case PROP_TIME_SYNCHRONIZATION_RECIPIENTS:
|
||||
case PROP_RESTART_NOTIFICATION_RECIPIENTS:
|
||||
case PROP_UTC_TIME_SYNCHRONIZATION_RECIPIENTS:
|
||||
/* FIXME: Properties using BACnetRecipient */
|
||||
return -1;
|
||||
|
||||
case PROP_DEVICE_ADDRESS_BINDING:
|
||||
case PROP_MANUAL_SLAVE_ADDRESS_BINDING:
|
||||
case PROP_SLAVE_ADDRESS_BINDING:
|
||||
/* FIXME: BACnetAddressBinding */
|
||||
return -1;
|
||||
|
||||
case PROP_ACTION:
|
||||
return -1;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Decodes a well-known, possibly complex property value
|
||||
* Used to reverse operations in bacapp_encode_application_data
|
||||
@@ -1028,6 +1181,15 @@ int bacapp_decode_known_property(uint8_t *apdu,
|
||||
{
|
||||
int len = 0;
|
||||
|
||||
// NOTE:
|
||||
// When adding impl for a new prop, also add its tag
|
||||
// to bacapp_known_property_tag()
|
||||
|
||||
int tag = bacapp_known_property_tag(object_type, property);
|
||||
if (tag != -1) {
|
||||
value->tag = tag;
|
||||
}
|
||||
|
||||
switch (property) {
|
||||
case PROP_MEMBER_OF:
|
||||
case PROP_ZONE_MEMBERS:
|
||||
@@ -1048,10 +1210,10 @@ int bacapp_decode_known_property(uint8_t *apdu,
|
||||
case PROP_BELONGS_TO:
|
||||
case PROP_LAST_ACCESS_POINT:
|
||||
/* Properties using BACnetDeviceObjectReference */
|
||||
value->tag = BACNET_APPLICATION_TAG_DEVICE_OBJECT_REFERENCE;
|
||||
len = bacapp_decode_device_obj_ref(
|
||||
apdu, &value->type.Device_Object_Reference);
|
||||
break;
|
||||
|
||||
case PROP_TIME_OF_ACTIVE_TIME_RESET:
|
||||
case PROP_TIME_OF_STATE_COUNT_RESET:
|
||||
case PROP_CHANGE_OF_STATE_TIME:
|
||||
@@ -1069,46 +1231,44 @@ int bacapp_decode_known_property(uint8_t *apdu,
|
||||
case PROP_EXPIRATION_TIME:
|
||||
case PROP_LAST_USE_TIME:
|
||||
/* Properties using BACnetDateTime value */
|
||||
value->tag = BACNET_APPLICATION_TAG_DATETIME;
|
||||
len = bacapp_decode_datetime(apdu, &value->type.Date_Time);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PROPERTY_REFERENCE:
|
||||
case PROP_LOG_DEVICE_OBJECT_PROPERTY:
|
||||
case PROP_LIST_OF_OBJECT_PROPERTY_REFERENCES:
|
||||
/* Properties using BACnetDeviceObjectPropertyReference */
|
||||
value->tag =
|
||||
BACNET_APPLICATION_TAG_DEVICE_OBJECT_PROPERTY_REFERENCE;
|
||||
len = bacapp_decode_device_obj_property_ref(apdu,
|
||||
&value->type.Device_Object_Property_Reference);
|
||||
break;
|
||||
|
||||
case PROP_MANIPULATED_VARIABLE_REFERENCE:
|
||||
case PROP_CONTROLLED_VARIABLE_REFERENCE:
|
||||
case PROP_INPUT_REFERENCE:
|
||||
/* Properties using BACnetObjectPropertyReference */
|
||||
value->tag = BACNET_APPLICATION_TAG_OBJECT_PROPERTY_REFERENCE;
|
||||
len = bacapp_decode_obj_property_ref(
|
||||
apdu, max_apdu_len,
|
||||
&value->type.Object_Property_Reference);
|
||||
break;
|
||||
|
||||
case PROP_EVENT_TIME_STAMPS:
|
||||
case PROP_LAST_RESTORE_TIME:
|
||||
case PROP_TIME_OF_DEVICE_RESTART:
|
||||
case PROP_ACCESS_EVENT_TIME:
|
||||
/* Properties using BACnetTimeStamp */
|
||||
value->tag = BACNET_APPLICATION_TAG_TIMESTAMP;
|
||||
len = bacapp_decode_timestamp(apdu, &value->type.Time_Stamp);
|
||||
break;
|
||||
|
||||
case PROP_DEFAULT_COLOR:
|
||||
/* Properties using BACnetxyColor */
|
||||
value->tag = BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
len = xy_color_decode(apdu, max_apdu_len,
|
||||
&value->type.XY_Color);
|
||||
break;
|
||||
|
||||
case PROP_TRACKING_VALUE:
|
||||
case PROP_PRESENT_VALUE:
|
||||
if (object_type == OBJECT_COLOR) {
|
||||
/* Properties using BACnetxyColor */
|
||||
value->tag = BACNET_APPLICATION_TAG_XY_COLOR;
|
||||
len = xy_color_decode(apdu, max_apdu_len,
|
||||
&value->type.XY_Color);
|
||||
} else {
|
||||
@@ -1117,26 +1277,34 @@ int bacapp_decode_known_property(uint8_t *apdu,
|
||||
property);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_COLOR_COMMAND:
|
||||
/* Properties using BACnetColorCommand */
|
||||
value->tag = BACNET_APPLICATION_TAG_COLOR_COMMAND;
|
||||
len = color_command_decode(apdu, max_apdu_len, NULL,
|
||||
&value->type.Color_Command);
|
||||
break;
|
||||
|
||||
case PROP_LIGHTING_COMMAND:
|
||||
/* Properties using BACnetLightingCommand */
|
||||
value->tag = BACNET_APPLICATION_TAG_LIGHTING_COMMAND;
|
||||
len = lighting_command_decode(apdu, max_apdu_len,
|
||||
&value->type.Lighting_Command);
|
||||
break;
|
||||
|
||||
case PROP_PRIORITY_ARRAY:
|
||||
/* [16] BACnetPriorityValue : 16x values (simple property) */
|
||||
len = decode_priority_value(apdu, max_apdu_len, value, property);
|
||||
break;
|
||||
|
||||
case PROP_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule ([7] BACnetDailySchedule*/
|
||||
len = bacnet_weeklyschedule_decode(
|
||||
apdu, max_apdu_len, &value->type.Weekly_Schedule);
|
||||
break;
|
||||
|
||||
/* properties without a specific decoder - fall through to default */
|
||||
|
||||
case PROP_LIST_OF_GROUP_MEMBERS:
|
||||
/* Properties using ReadAccessSpecification */
|
||||
case PROP_WEEKLY_SCHEDULE:
|
||||
/* BACnetDailySchedule[7] (Schedule) */
|
||||
case PROP_EXCEPTION_SCHEDULE:
|
||||
/* BACnetSpecialEvent (Schedule) */
|
||||
case PROP_DATE_LIST:
|
||||
@@ -1527,6 +1695,149 @@ static int bacapp_snprintf_time(char *str, size_t str_len, BACNET_TIME *btime)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACAPP_TYPES_EXTRA)
|
||||
static int bacapp_snprintf_weeklyschedule(
|
||||
char *str,
|
||||
size_t str_len,
|
||||
BACNET_WEEKLY_SCHEDULE *ws,
|
||||
BACNET_ARRAY_INDEX arrayIndex)
|
||||
{
|
||||
int slen;
|
||||
int ret_val = 0;
|
||||
int wi, ti;
|
||||
BACNET_OBJECT_PROPERTY_VALUE dummyPropValue;
|
||||
BACNET_APPLICATION_DATA_VALUE dummyDataValue;
|
||||
|
||||
const char *weekdaynames[7] = {
|
||||
"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
|
||||
};
|
||||
const int loopend = ((arrayIndex == BACNET_ARRAY_ALL) ? 7 : 1);
|
||||
|
||||
// Find what inner type it uses
|
||||
int inner_tag = -1;
|
||||
for (wi = 0; wi < loopend; wi++) {
|
||||
BACNET_DAILY_SCHEDULE *ds = &ws->weeklySchedule[wi];
|
||||
for (ti = 0; ti < ds->TV_Count; ti++) {
|
||||
int tag = ds->Time_Values[ti].Value.tag;
|
||||
if (inner_tag == -1) {
|
||||
inner_tag = tag;
|
||||
} else if (inner_tag != tag) {
|
||||
inner_tag = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (inner_tag == -1) {
|
||||
slen = snprintf(str, str_len, "(Null; ");
|
||||
} else if (inner_tag == -2) {
|
||||
slen = snprintf(str, str_len, "(MIXED_TYPES; ");
|
||||
} else {
|
||||
slen = snprintf(str, str_len, "(%s; ", bactext_application_tag_name(inner_tag));
|
||||
}
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (wi = 0; wi < loopend; wi++) {
|
||||
BACNET_DAILY_SCHEDULE *ds = &ws->weeklySchedule[wi];
|
||||
if (arrayIndex == BACNET_ARRAY_ALL) {
|
||||
slen = snprintf(str, str_len, "%s: [", weekdaynames[wi]);
|
||||
} else {
|
||||
slen = snprintf(
|
||||
str, str_len, "%s: [",
|
||||
(arrayIndex >= 1 && arrayIndex <= 7) ? weekdaynames[arrayIndex - 1] : "???"
|
||||
);
|
||||
}
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (ti = 0; ti < ds->TV_Count; ti++) {
|
||||
slen = bacapp_snprintf_time(str, str_len, &ds->Time_Values[ti].Time);
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
slen = snprintf(str, str_len, " ");
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bacnet_primitive_to_application_data_value(
|
||||
&dummyDataValue, &ds->Time_Values[ti].Value);
|
||||
dummyPropValue.value = &dummyDataValue;
|
||||
dummyPropValue.object_property = PROP_PRESENT_VALUE;
|
||||
dummyPropValue.object_type = OBJECT_SCHEDULE;
|
||||
|
||||
slen = bacapp_snprintf_value(str, str_len, &dummyPropValue);
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (ti < ds->TV_Count - 1) {
|
||||
slen = snprintf(str, str_len, ", ");
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wi < loopend - 1) {
|
||||
slen = snprintf(str, str_len, "]; ");
|
||||
ret_val += slen;
|
||||
if (str) {
|
||||
str += slen;
|
||||
if (str_len >= slen) {
|
||||
str_len -= slen;
|
||||
} else {
|
||||
str_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
slen = snprintf(str, str_len, "])");
|
||||
ret_val += slen;
|
||||
return ret_val;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Extract the value into a text string
|
||||
* @param str - the buffer to store the extracted value, or NULL for length
|
||||
@@ -1939,6 +2250,11 @@ int bacapp_snprintf_value(
|
||||
slen = snprintf(str, str_len, ")");
|
||||
ret_val += slen;
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule */
|
||||
ret_val = bacapp_snprintf_weeklyschedule(
|
||||
str, str_len, &value->type.Weekly_Schedule, object_value->array_index);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||
if (value->type.Host_Address.host_ip_address) {
|
||||
octet_str = octetstring_value(
|
||||
@@ -1988,6 +2304,7 @@ int bacapp_snprintf_value(
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ret_val = snprintf(str, str_len, "UnknownType(tag=%d)", value->tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2040,10 +2357,206 @@ bool bacapp_print_value(
|
||||
#endif
|
||||
|
||||
#ifdef BACAPP_PRINT_ENABLED
|
||||
static char* ltrim(char *str, const char *trimmedchars) {
|
||||
if (str[0] == 0) {
|
||||
return str;
|
||||
}
|
||||
while(strchr(trimmedchars, *str)) {
|
||||
str++;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static char* rtrim(char *str, const char *trimmedchars) {
|
||||
if (str[0] == 0) {
|
||||
return str;
|
||||
}
|
||||
char *end = str + strlen(str) - 1;
|
||||
while (strchr(trimmedchars, *end)) {
|
||||
*end = 0;
|
||||
if (end == str) break;
|
||||
end--;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static char* trim(char *str, const char *trimmedchars) {
|
||||
return ltrim(rtrim(str, trimmedchars), trimmedchars);
|
||||
}
|
||||
|
||||
#if defined (BACAPP_TYPES_EXTRA)
|
||||
static bool parse_weeklyschedule(char *str, BACNET_APPLICATION_DATA_VALUE *value)
|
||||
{
|
||||
char *chunk, *comma, *space, *t, *v;
|
||||
int daynum = 0, tvnum = 0;
|
||||
unsigned int inner_tag;
|
||||
BACNET_APPLICATION_DATA_VALUE dummy_value = { 0 };
|
||||
BACNET_DAILY_SCHEDULE *dsch;
|
||||
|
||||
/*
|
||||
Format:
|
||||
|
||||
(1; Mon: [02:00:00.00 FALSE, 07:35:00.00 active, 07:40:00.00 inactive]; Tue: [02:00:00.00 inactive]; ...)
|
||||
|
||||
- the first number is the inner tag (e.g. 1 = boolean, 4 = real, 9 = enum)
|
||||
- Day name prefix is optional and ignored.
|
||||
- Entries are separated by semicolons.
|
||||
- There can be a full week, or only one entry - when using array index to modify a single day
|
||||
- time-value array can be empty: []
|
||||
*/
|
||||
|
||||
value->tag = BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE;
|
||||
|
||||
// Parse the inner tag
|
||||
chunk = strtok(str, ";");
|
||||
chunk = ltrim(chunk, "(");
|
||||
if (false == bacapp_parse_application_data(BACNET_APPLICATION_TAG_UNSIGNED_INT, chunk, &dummy_value)) {
|
||||
// Try searching it by name
|
||||
if (false == bactext_application_tag_index(chunk, &inner_tag)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
inner_tag = (int)dummy_value.type.Unsigned_Int;
|
||||
}
|
||||
|
||||
chunk = strtok(NULL, ";");
|
||||
|
||||
while(chunk != NULL) {
|
||||
dsch = &value->type.Weekly_Schedule.weeklySchedule[daynum];
|
||||
|
||||
// Strip day name prefix, if present
|
||||
char *colonpos = strchr(chunk, ':');
|
||||
char *sqpos = strchr(chunk, '[');
|
||||
if (colonpos && colonpos < sqpos) {
|
||||
chunk = colonpos + 1;
|
||||
}
|
||||
|
||||
// Extract the inner list of time-values
|
||||
chunk = rtrim(ltrim(chunk, "([ "), " ])");
|
||||
|
||||
// The list can be empty
|
||||
if (chunk[0] != 0) {
|
||||
// loop through the time value pairs
|
||||
tvnum = 0;
|
||||
do {
|
||||
// Find the comma delimiter, replace with NUL (like strtok)
|
||||
comma = strchr(chunk, ',');
|
||||
if (comma) {
|
||||
*comma = 0;
|
||||
}
|
||||
// trim the time-value pair and find the delimiter space
|
||||
chunk = trim(chunk, " ");
|
||||
space = strchr(chunk, ' ');
|
||||
if (!space) {
|
||||
// malformed time-value pair
|
||||
return false;
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
// Extract time and value
|
||||
t = chunk;
|
||||
// value starts one byte after the space, and there can be multiple spaces
|
||||
chunk = ltrim(space + 1, " ");
|
||||
v = chunk;
|
||||
|
||||
// Parse time
|
||||
if (false == bacapp_parse_application_data(BACNET_APPLICATION_TAG_TIME, t, &dummy_value)) {
|
||||
return false;
|
||||
}
|
||||
dsch->Time_Values[tvnum].Time = dummy_value.type.Time;
|
||||
|
||||
// Parse value
|
||||
if (false == bacapp_parse_application_data(inner_tag, v, &dummy_value)) {
|
||||
return false;
|
||||
}
|
||||
if (BACNET_STATUS_OK !=
|
||||
bacnet_application_to_primitive_data_value(
|
||||
&dsch->Time_Values[tvnum].Value, &dummy_value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Advance past the comma to the next chunk
|
||||
if (comma) {
|
||||
chunk = comma + 1;
|
||||
}
|
||||
tvnum++;
|
||||
} while (comma != NULL);
|
||||
}
|
||||
|
||||
dsch->TV_Count = tvnum;
|
||||
|
||||
// Find the start of the next day
|
||||
chunk = strtok(NULL, ";");
|
||||
daynum++;
|
||||
}
|
||||
|
||||
if (daynum == 1) {
|
||||
value->type.Weekly_Schedule.singleDay = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACAPP_SIGNED) || defined(BACAPP_BOOLEAN)
|
||||
static bool strtol_checked(const char *s, long *out)
|
||||
{
|
||||
char *end;
|
||||
errno = 0;
|
||||
*out = strtol(s, &end, 0);
|
||||
if (end == s) {
|
||||
// Conversion was not possible
|
||||
return false;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
// Number too large
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACAPP_UNSIGNED) || defined(BACAPP_ENUMERATED)
|
||||
static bool strtoul_checked(const char *s, unsigned long *out)
|
||||
{
|
||||
char *end;
|
||||
errno = 0;
|
||||
*out = strtoul(s, &end, 0);
|
||||
if (end == s) {
|
||||
// Conversion was not possible
|
||||
return false;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
// Number too large
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BACAPP_REAL) || defined(BACAPP_DOUBLE)
|
||||
static bool strtod_checked(const char *s, double *out)
|
||||
{
|
||||
char *end;
|
||||
errno = 0;
|
||||
*out = strtod(s, &end);
|
||||
if (end == s) {
|
||||
// Conversion was not possible
|
||||
return false;
|
||||
}
|
||||
if (errno == ERANGE) {
|
||||
// Number too large
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* used to load the app data struct with the proper data
|
||||
converted from a command line argument */
|
||||
converted from a command line argument.
|
||||
"argv" is not const to allow using strtok internally. It MAY be modified. */
|
||||
bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
const char *argv,
|
||||
char *argv,
|
||||
BACNET_APPLICATION_DATA_VALUE *value)
|
||||
{
|
||||
int hour, min, sec, hundredths;
|
||||
@@ -2052,7 +2565,7 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
uint32_t instance = 0;
|
||||
bool status = false;
|
||||
long long_value = 0;
|
||||
unsigned long unsigned_long_value = 0;
|
||||
BACNET_UNSIGNED_INTEGER unsigned_long_value = 0;
|
||||
double double_value = 0.0;
|
||||
int count = 0;
|
||||
#if defined(BACAPP_TYPES_EXTRA)
|
||||
@@ -2066,34 +2579,59 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
switch (tag_number) {
|
||||
#if defined(BACAPP_BOOLEAN)
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
long_value = strtol(argv, NULL, 0);
|
||||
if (long_value)
|
||||
if (strcasecmp(argv, "true") == 0 || strcasecmp(argv, "active") == 0) {
|
||||
value->type.Boolean = true;
|
||||
else
|
||||
} else if (strcasecmp(argv, "false") == 0 || strcasecmp(argv, "inactive") == 0) {
|
||||
value->type.Boolean = false;
|
||||
} else {
|
||||
status = strtol_checked(argv, &long_value);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
if (long_value) {
|
||||
value->type.Boolean = true;
|
||||
} else {
|
||||
value->type.Boolean = false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_UNSIGNED)
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
unsigned_long_value = strtoul(argv, NULL, 0);
|
||||
status = strtoul_checked(argv, &unsigned_long_value);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
if (unsigned_long_value > BACNET_UNSIGNED_INTEGER_MAX) {
|
||||
return false;
|
||||
}
|
||||
value->type.Unsigned_Int = unsigned_long_value;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_SIGNED)
|
||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||
long_value = strtol(argv, NULL, 0);
|
||||
value->type.Signed_Int = long_value;
|
||||
status = strtol_checked(argv, &long_value);
|
||||
if (!status || long_value > INT32_MAX || long_value < INT32_MIN) {
|
||||
return false;
|
||||
}
|
||||
value->type.Signed_Int = (int32_t) long_value;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_REAL)
|
||||
case BACNET_APPLICATION_TAG_REAL:
|
||||
double_value = strtod(argv, NULL);
|
||||
status = strtod_checked(argv, &double_value);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
value->type.Real = (float)double_value;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_DOUBLE)
|
||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||
double_value = strtod(argv, NULL);
|
||||
status = strtod_checked(argv, &double_value);
|
||||
if (!status) {
|
||||
return false;
|
||||
}
|
||||
value->type.Double = double_value;
|
||||
break;
|
||||
#endif
|
||||
@@ -2116,8 +2654,11 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
#endif
|
||||
#if defined(BACAPP_ENUMERATED)
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
unsigned_long_value = strtoul(argv, NULL, 0);
|
||||
value->type.Enumerated = unsigned_long_value;
|
||||
status = strtoul_checked(argv, &unsigned_long_value);
|
||||
if (!status || unsigned_long_value > UINT32_MAX) {
|
||||
return false;
|
||||
}
|
||||
value->type.Enumerated = (uint32_t) unsigned_long_value;
|
||||
break;
|
||||
#endif
|
||||
#if defined(BACAPP_DATE)
|
||||
@@ -2190,6 +2731,9 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
|
||||
/* FIXME: add parsing for BACnetColorCommand */
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
status = parse_weeklyschedule(argv, value);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||
count = sscanf(argv, "%3u.%3u.%3u.%3u:%5u",
|
||||
&a[0], &a[1], &a[2], &a[3], &p);
|
||||
@@ -2221,7 +2765,7 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
#endif /* BACAPP_PRINT_ENABLED */
|
||||
|
||||
/**
|
||||
* Initialize an array (or single) #BACNET_APPLICATION_DATA_VALUE
|
||||
@@ -2405,6 +2949,11 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
|
||||
status = color_command_same(&value->type.Color_Command,
|
||||
&test_value->type.Color_Command);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
|
||||
/* BACnetWeeklySchedule */
|
||||
status = bacnet_weeklyschedule_same(&value->type.Weekly_Schedule,
|
||||
&test_value->type.Weekly_Schedule);
|
||||
break;
|
||||
case BACNET_APPLICATION_TAG_HOST_N_PORT:
|
||||
status = host_n_port_same(&value->type.Host_Address,
|
||||
&value->type.Host_Address);
|
||||
|
||||
+8
-1
@@ -36,6 +36,7 @@
|
||||
#include "bacnet/bacdevobjpropref.h"
|
||||
#include "bacnet/hostnport.h"
|
||||
#include "bacnet/timestamp.h"
|
||||
#include "bacnet/weeklyschedule.h"
|
||||
|
||||
struct BACnet_Application_Data_Value;
|
||||
typedef struct BACnet_Application_Data_Value {
|
||||
@@ -86,6 +87,7 @@ typedef struct BACnet_Application_Data_Value {
|
||||
BACNET_LIGHTING_COMMAND Lighting_Command;
|
||||
BACNET_COLOR_COMMAND Color_Command;
|
||||
BACNET_XY_COLOR XY_Color;
|
||||
BACNET_WEEKLY_SCHEDULE Weekly_Schedule;
|
||||
BACNET_HOST_N_PORT Host_Address;
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE
|
||||
Device_Object_Property_Reference;
|
||||
@@ -216,6 +218,11 @@ extern "C" {
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
BACNET_PROPERTY_ID property);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_known_property_tag(
|
||||
BACNET_OBJECT_TYPE object_type,
|
||||
BACNET_PROPERTY_ID property);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacapp_copy(
|
||||
BACNET_APPLICATION_DATA_VALUE * dest_value,
|
||||
@@ -260,7 +267,7 @@ extern "C" {
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacapp_parse_application_data(
|
||||
BACNET_APPLICATION_TAG tag_number,
|
||||
const char *argv,
|
||||
char *argv,
|
||||
BACNET_APPLICATION_DATA_VALUE * value);
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacapp_print_value(
|
||||
|
||||
@@ -617,23 +617,23 @@ extern "C" {
|
||||
|
||||
/* from clause 20.2.1.2 Tag Number */
|
||||
/* true if extended tag numbering is used */
|
||||
#define IS_EXTENDED_TAG_NUMBER(x) ((x & 0xF0) == 0xF0)
|
||||
#define IS_EXTENDED_TAG_NUMBER(x) (((x) & 0xF0) == 0xF0)
|
||||
|
||||
/* from clause 20.2.1.3.1 Primitive Data */
|
||||
/* true if the extended value is used */
|
||||
#define IS_EXTENDED_VALUE(x) ((x & 0x07) == 5)
|
||||
#define IS_EXTENDED_VALUE(x) (((x) & 0x07) == 5)
|
||||
|
||||
/* from clause 20.2.1.1 Class */
|
||||
/* true if the tag is context specific */
|
||||
#define IS_CONTEXT_SPECIFIC(x) ((x & BIT(3)) == BIT(3))
|
||||
#define IS_CONTEXT_SPECIFIC(x) (((x) & BIT(3)) == BIT(3))
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* true if the tag is an opening tag */
|
||||
#define IS_OPENING_TAG(x) ((x & 0x07) == 6)
|
||||
#define IS_OPENING_TAG(x) (((x) & 0x07) == 6)
|
||||
|
||||
/* from clause 20.2.1.3.2 Constructed Data */
|
||||
/* true if the tag is a closing tag */
|
||||
#define IS_CLOSING_TAG(x) ((x & 0x07) == 7)
|
||||
#define IS_CLOSING_TAG(x) (((x) & 0x07) == 7)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
+246
-36
@@ -34,57 +34,195 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h> /* memcpy */
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacnet/bactimevalue.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
|
||||
int bacapp_encode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
||||
static bool is_data_value_schedule_compatible(uint8_t tag) {
|
||||
switch (tag) {
|
||||
/* Every member of the union must be listed here to allow decoding */
|
||||
case BACNET_APPLICATION_TAG_NULL:
|
||||
return true;
|
||||
#if defined (BACAPP_BOOLEAN)
|
||||
case BACNET_APPLICATION_TAG_BOOLEAN:
|
||||
return true;
|
||||
#endif
|
||||
#if defined (BACAPP_UNSIGNED)
|
||||
case BACNET_APPLICATION_TAG_UNSIGNED_INT:
|
||||
return true;
|
||||
#endif
|
||||
#if defined (BACAPP_SIGNED)
|
||||
case BACNET_APPLICATION_TAG_SIGNED_INT:
|
||||
return true;
|
||||
#endif
|
||||
#if defined (BACAPP_REAL)
|
||||
case BACNET_APPLICATION_TAG_REAL:
|
||||
return true;
|
||||
#endif
|
||||
#if defined (BACAPP_DOUBLE)
|
||||
case BACNET_APPLICATION_TAG_DOUBLE:
|
||||
return true;
|
||||
#endif
|
||||
#if defined (BACAPP_ENUMERATED)
|
||||
case BACNET_APPLICATION_TAG_ENUMERATED:
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int bacnet_time_value_encode(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
len = encode_application_time(&apdu[apdu_len], &value->Time);
|
||||
if (!value || !is_data_value_schedule_compatible(value->Value.tag)) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_application_time(apdu_offset, &value->Time);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_application_data(&apdu[apdu_len], &value->Value);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
|
||||
BACNET_APPLICATION_DATA_VALUE adv;
|
||||
bacnet_primitive_to_application_data_value(&adv, &value->Value);
|
||||
|
||||
len = bacapp_encode_application_data(apdu_offset, &adv);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_encode_context_time_value(
|
||||
int bacapp_encode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value) {
|
||||
return bacnet_time_value_encode(apdu, value);
|
||||
}
|
||||
|
||||
int bacnet_time_value_context_encode(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
len = encode_opening_tag(&apdu[apdu_len], tag_number);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_opening_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_encode_time_value(&apdu[apdu_len], value);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = bacnet_time_value_encode(apdu_offset, value);
|
||||
apdu_len += len;
|
||||
|
||||
len = encode_closing_tag(&apdu[apdu_len], tag_number);
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_closing_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_encode_context_time_value(uint8_t *apdu, uint8_t tag_number, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
return bacnet_time_value_context_encode(apdu, tag_number, value);
|
||||
}
|
||||
|
||||
/** returns 0 if OK, -1 on error */
|
||||
int bacnet_application_to_primitive_data_value(
|
||||
struct BACnet_Primitive_Data_Value *dest,
|
||||
const struct BACnet_Application_Data_Value *src)
|
||||
{
|
||||
// make sure the value passed is valid
|
||||
if (!src || !dest || !is_data_value_schedule_compatible(src->tag)) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
memset(dest, 0, sizeof(struct BACnet_Primitive_Data_Value));
|
||||
dest->tag = src->tag;
|
||||
memcpy(&dest->type, &src->type, sizeof(dest->type));
|
||||
return BACNET_STATUS_OK;
|
||||
}
|
||||
|
||||
/** returns 0 if OK, -1 on error */
|
||||
int bacnet_primitive_to_application_data_value(
|
||||
struct BACnet_Application_Data_Value * dest,
|
||||
const struct BACnet_Primitive_Data_Value * src)
|
||||
{
|
||||
// make sure the value passed is valid
|
||||
if (!dest || !src) {
|
||||
return BACNET_STATUS_ERROR;
|
||||
}
|
||||
memset(dest, 0, sizeof(struct BACnet_Application_Data_Value));
|
||||
dest->tag = src->tag;
|
||||
memcpy(&dest->type, &src->type, sizeof(src->type));
|
||||
return BACNET_STATUS_OK; /* OK */
|
||||
}
|
||||
|
||||
int bacnet_time_value_decode(uint8_t *apdu, int max_apdu_len, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
BACNET_APPLICATION_DATA_VALUE full_data_value = { 0 };
|
||||
|
||||
len = bacnet_time_application_decode(&apdu[apdu_len], max_apdu_len, &value->Time);
|
||||
if (len <= 0) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_decode_application_data(&apdu[apdu_len], max_apdu_len - apdu_len, &full_data_value);
|
||||
if (len <= 0) {
|
||||
return -1;
|
||||
}
|
||||
if (BACNET_STATUS_OK !=
|
||||
bacnet_application_to_primitive_data_value(
|
||||
&value->Value, &full_data_value)) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacapp_decode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
return bacnet_time_value_decode(apdu, MAX_APDU, value);
|
||||
}
|
||||
|
||||
int bacnet_time_value_context_decode(uint8_t *apdu, int max_apdu_len, uint8_t tag_number, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
|
||||
len = decode_application_time(&apdu[apdu_len], &value->Time);
|
||||
if (len <= 0) {
|
||||
if ((max_apdu_len - apdu_len) >= 1 && decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len += 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
len = bacapp_decode_application_data(&apdu[apdu_len], 2048, &value->Value);
|
||||
if (len <= 0) {
|
||||
len = bacnet_time_value_decode(&apdu[apdu_len], max_apdu_len - apdu_len, value);
|
||||
if (len > 0) {
|
||||
apdu_len += len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((max_apdu_len - apdu_len) >= 1 && decode_is_closing_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len += 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
@@ -92,27 +230,99 @@ int bacapp_decode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value)
|
||||
int bacapp_decode_context_time_value(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_TIME_VALUE *value)
|
||||
{
|
||||
int len = 0;
|
||||
int section_length;
|
||||
|
||||
if (decode_is_opening_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
section_length = bacapp_decode_time_value(&apdu[len], value);
|
||||
if (section_length > 0) {
|
||||
len += section_length;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (decode_is_closing_tag_number(&apdu[len], tag_number)) {
|
||||
len++;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len;
|
||||
return bacnet_time_value_context_decode(apdu, MAX_APDU, tag_number, value);
|
||||
}
|
||||
|
||||
int bacnet_time_values_context_decode(
|
||||
uint8_t * apdu,
|
||||
const int max_apdu_len,
|
||||
const uint8_t tag_number,
|
||||
BACNET_TIME_VALUE *time_values,
|
||||
const unsigned int max_time_values,
|
||||
unsigned int *out_count)
|
||||
{
|
||||
unsigned int j;
|
||||
int len;
|
||||
int apdu_len = 0;
|
||||
unsigned int count_values = 0;
|
||||
BACNET_TIME_VALUE dummy;
|
||||
|
||||
/* day-schedule [0] SEQUENCE OF BACnetTimeValue */
|
||||
if (decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len++;
|
||||
while ((apdu_len < max_apdu_len) &&
|
||||
!decode_is_closing_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
if (count_values < max_time_values) {
|
||||
len = bacnet_time_value_decode(&apdu[apdu_len],
|
||||
max_apdu_len - apdu_len, &time_values[count_values++]);
|
||||
} else {
|
||||
len = bacnet_time_value_decode(
|
||||
&apdu[apdu_len], max_apdu_len - apdu_len, &dummy);
|
||||
}
|
||||
if (len < 0) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
/* Zeroing other values */
|
||||
for (j = count_values; j < max_time_values; j++) {
|
||||
time_values[j].Value.tag = BACNET_APPLICATION_TAG_NULL;
|
||||
time_values[j].Value.type.Unsigned_Int = 0;
|
||||
time_values[j].Time.hour = 0;
|
||||
time_values[j].Time.min = 0;
|
||||
time_values[j].Time.sec = 0;
|
||||
time_values[j].Time.hundredths = 0;
|
||||
}
|
||||
/* overflow ! */
|
||||
if (apdu_len >= max_apdu_len) {
|
||||
return -1;
|
||||
}
|
||||
apdu_len++; /* closing tag */
|
||||
if (out_count) {
|
||||
*out_count = count_values;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Encodes a : [x] SEQUENCE OF BACnetTimeValue into a fixed-size buffer */
|
||||
int bacnet_time_values_context_encode(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME_VALUE *time_values,
|
||||
unsigned int max_time_values)
|
||||
{
|
||||
unsigned int j;
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
BACNET_TIME t0 = { 0 };
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
/* day-schedule [x] SEQUENCE OF BACnetTimeValue */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
apdu_len += encode_opening_tag(apdu_offset, tag_number);
|
||||
|
||||
for (j = 0; j < max_time_values; j++)
|
||||
/* Encode only non-null values (NULL,00:00:00.00) */
|
||||
if (time_values[j].Value.tag != BACNET_APPLICATION_TAG_NULL ||
|
||||
datetime_compare_time(&t0, &time_values[j].Time) != 0) {
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len =
|
||||
bacnet_time_value_encode(apdu_offset,
|
||||
&time_values[j]);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
apdu_len += len;
|
||||
}
|
||||
/* close tag */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
apdu_len += encode_closing_tag(apdu_offset, tag_number);
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
+109
-6
@@ -29,39 +29,142 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "bacnet/basic/sys/platform.h"
|
||||
#include "bacnet/bacdef.h"
|
||||
#include "bacnet/bacenum.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
#include "bacnet/datetime.h"
|
||||
|
||||
typedef struct {
|
||||
/**
|
||||
* Smaller version of BACnet_Application_Data_Value used in BACnetTimeValue
|
||||
*
|
||||
* This must be a separate struct to avoid recursive structure.
|
||||
* Keeping it small also helps keep the size of BACNET_APPLICATION_DATA_VALUE
|
||||
* small. Besides, schedule can't contain complex types.
|
||||
*/
|
||||
typedef struct BACnet_Primitive_Data_Value {
|
||||
uint8_t tag; /* application tag data type */
|
||||
union {
|
||||
/*
|
||||
* ATTENTION! If a new type is added here, update
|
||||
* `is_data_value_schedule_compatible()` in bactimevalue.c!
|
||||
*/
|
||||
|
||||
/* NULL - not needed as it is encoded in the tag alone */
|
||||
#if defined (BACAPP_BOOLEAN)
|
||||
bool Boolean;
|
||||
#endif
|
||||
#if defined (BACAPP_UNSIGNED)
|
||||
BACNET_UNSIGNED_INTEGER Unsigned_Int;
|
||||
#endif
|
||||
#if defined (BACAPP_SIGNED)
|
||||
int32_t Signed_Int;
|
||||
#endif
|
||||
#if defined (BACAPP_REAL)
|
||||
float Real;
|
||||
#endif
|
||||
#if defined (BACAPP_DOUBLE)
|
||||
double Double;
|
||||
#endif
|
||||
#if defined (BACAPP_ENUMERATED)
|
||||
uint32_t Enumerated;
|
||||
#endif
|
||||
} type;
|
||||
} BACNET_PRIMITIVE_DATA_VALUE;
|
||||
|
||||
typedef struct BACnet_Time_Value {
|
||||
BACNET_TIME Time;
|
||||
BACNET_APPLICATION_DATA_VALUE Value;
|
||||
BACNET_PRIMITIVE_DATA_VALUE Value;
|
||||
} BACNET_TIME_VALUE;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
struct BACnet_Application_Data_Value;
|
||||
|
||||
/** returns 0 if OK, -1 on error */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_application_to_primitive_data_value(BACNET_PRIMITIVE_DATA_VALUE * dest,
|
||||
const struct BACnet_Application_Data_Value * src);
|
||||
|
||||
/** returns 0 if OK, -1 on error */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_primitive_to_application_data_value(
|
||||
struct BACnet_Application_Data_Value * dest,
|
||||
const BACNET_PRIMITIVE_DATA_VALUE * src);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_encode_time_value(uint8_t * apdu,
|
||||
int bacnet_time_value_encode(uint8_t * apdu,
|
||||
BACNET_TIME_VALUE * value);
|
||||
|
||||
BACNET_STACK_DEPRECATED("Use bacnet_time_value_encode() instead")
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_encode_context_time_value(uint8_t * apdu,
|
||||
int bacapp_encode_time_value(uint8_t *apdu, BACNET_TIME_VALUE *value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_time_value_context_encode(uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME_VALUE * value);
|
||||
|
||||
BACNET_STACK_DEPRECATED("Use bacnet_time_value_context_encode() instead")
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_encode_context_time_value(uint8_t *apdu, uint8_t tag_number, BACNET_TIME_VALUE *value);
|
||||
|
||||
BACNET_STACK_DEPRECATED("Use bacnet_time_value_decode() instead")
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_decode_time_value(uint8_t * apdu,
|
||||
BACNET_TIME_VALUE * value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_time_value_decode(uint8_t *apdu, int max_apdu_len,
|
||||
BACNET_TIME_VALUE *value);
|
||||
|
||||
BACNET_STACK_DEPRECATED("Use bacnet_time_value_context_decode() instead")
|
||||
BACNET_STACK_EXPORT
|
||||
int bacapp_decode_context_time_value(uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME_VALUE * value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_time_value_context_decode(uint8_t *apdu, int max_apdu_len,
|
||||
uint8_t tag_number, BACNET_TIME_VALUE *value);
|
||||
|
||||
/**
|
||||
* Decode array of time-values wrapped in a context tag
|
||||
* @param apdu
|
||||
* @param max_apdu_len
|
||||
* @param tag_number - number expected in the context tag; 0 used for DailySchedule
|
||||
* @param time_values
|
||||
* @param max_time_values - number of time values to encode
|
||||
* @param[out] out_count - actual number of time values found
|
||||
* @return used bytes, <0 if decoding failed
|
||||
*/
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_time_values_context_decode(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME_VALUE *time_values,
|
||||
unsigned int max_time_values,
|
||||
unsigned int *out_count);
|
||||
|
||||
/**
|
||||
* Encode array of time-values wrapped in a context tag
|
||||
* @param apdu - output buffer, NULL to just measure length
|
||||
* @param max_apdu_len
|
||||
* @param tag_number - number to use for the context tag; 0 used for DailySchedule
|
||||
* @param time_values
|
||||
* @param max_time_values - number of time values to encode
|
||||
* @return used bytes, <=0 if encoding failed
|
||||
*/
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_time_values_context_encode(
|
||||
uint8_t * apdu,
|
||||
uint8_t tag_number,
|
||||
BACNET_TIME_VALUE * time_values,
|
||||
unsigned int max_time_values);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif
|
||||
#endif /* _BAC_TIME_VALUE_H_ */
|
||||
|
||||
@@ -86,10 +86,10 @@ void Schedule_Init(void)
|
||||
for (j = 0; j < 7; j++) {
|
||||
psched->Weekly_Schedule[j].TV_Count = 0;
|
||||
}
|
||||
psched->Present_Value = &psched->Schedule_Default;
|
||||
memcpy(&psched->Present_Value, &psched->Schedule_Default, sizeof(psched->Present_Value));
|
||||
psched->Schedule_Default.context_specific = false;
|
||||
psched->Schedule_Default.tag = BACNET_APPLICATION_TAG_REAL;
|
||||
psched->Schedule_Default.type.Real = 21.0; /* 21 C, room temperature */
|
||||
psched->Schedule_Default.type.Real = 21.0f; /* 21 C, room temperature */
|
||||
psched->obj_prop_ref_cnt = 0; /* no references, add as needed */
|
||||
psched->Priority_For_Writing = 16; /* lowest priority */
|
||||
psched->Out_Of_Service = false;
|
||||
@@ -197,7 +197,7 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
apdu_len = encode_application_enumerated(&apdu[0], OBJECT_SCHEDULE);
|
||||
break;
|
||||
case PROP_PRESENT_VALUE:
|
||||
apdu_len = bacapp_encode_data(&apdu[0], CurrentSC->Present_Value);
|
||||
apdu_len = bacapp_encode_data(&apdu[0], &CurrentSC->Present_Value);
|
||||
break;
|
||||
case PROP_EFFECTIVE_PERIOD:
|
||||
/* BACnet Testing Observed Incident oi00110
|
||||
@@ -224,7 +224,7 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
|
||||
for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count;
|
||||
i++) {
|
||||
apdu_len += bacapp_encode_time_value(&apdu[apdu_len],
|
||||
apdu_len += bacnet_time_value_encode(&apdu[apdu_len],
|
||||
&CurrentSC->Weekly_Schedule[day].Time_Values[i]);
|
||||
}
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
|
||||
@@ -233,7 +233,7 @@ int Schedule_Read_Property(BACNET_READ_PROPERTY_DATA *rpdata)
|
||||
int day = rpdata->array_index - 1;
|
||||
apdu_len += encode_opening_tag(&apdu[apdu_len], 0);
|
||||
for (i = 0; i < CurrentSC->Weekly_Schedule[day].TV_Count; i++) {
|
||||
apdu_len += bacapp_encode_time_value(&apdu[apdu_len],
|
||||
apdu_len += bacnet_time_value_encode(&apdu[apdu_len],
|
||||
&CurrentSC->Weekly_Schedule[day].Time_Values[i]);
|
||||
}
|
||||
apdu_len += encode_closing_tag(&apdu[apdu_len], 0);
|
||||
@@ -396,7 +396,7 @@ void Schedule_Recalculate_PV(
|
||||
SCHEDULE_DESCR *desc, BACNET_WEEKDAY wday, BACNET_TIME *time)
|
||||
{
|
||||
int i;
|
||||
desc->Present_Value = NULL;
|
||||
desc->Present_Value.tag = BACNET_APPLICATION_TAG_NULL;
|
||||
|
||||
/* for future development, here should be the loop for Exception Schedule */
|
||||
|
||||
@@ -408,19 +408,19 @@ void Schedule_Recalculate_PV(
|
||||
broker an early release on a case-by-case basis. */
|
||||
|
||||
for (i = 0; i < desc->Weekly_Schedule[wday - 1].TV_Count &&
|
||||
desc->Present_Value == NULL;
|
||||
desc->Present_Value.tag == BACNET_APPLICATION_TAG_NULL;
|
||||
i++) {
|
||||
int diff = datetime_wildcard_compare_time(
|
||||
time, &desc->Weekly_Schedule[wday - 1].Time_Values[i].Time);
|
||||
if (diff >= 0 &&
|
||||
desc->Weekly_Schedule[wday - 1].Time_Values[i].Value.tag !=
|
||||
BACNET_APPLICATION_TAG_NULL) {
|
||||
desc->Present_Value =
|
||||
&desc->Weekly_Schedule[wday - 1].Time_Values[i].Value;
|
||||
bacnet_primitive_to_application_data_value(&desc->Present_Value,
|
||||
&desc->Weekly_Schedule[wday - 1].Time_Values[i].Value);
|
||||
}
|
||||
}
|
||||
|
||||
if (desc->Present_Value == NULL) {
|
||||
desc->Present_Value = &desc->Schedule_Default;
|
||||
if (desc->Present_Value.tag == BACNET_APPLICATION_TAG_NULL) {
|
||||
memcpy(&desc->Present_Value, &desc->Schedule_Default, sizeof(desc->Present_Value));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,19 +51,28 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct bacnet_daily_schedule {
|
||||
/*
|
||||
* Note:
|
||||
* This is a different struct from BACNET_DAILY_SCHEDULE used in prop value encoding!
|
||||
* The number of entries is different.
|
||||
*/
|
||||
typedef struct bacnet_obj_daily_schedule {
|
||||
BACNET_TIME_VALUE Time_Values[BACNET_WEEKLY_SCHEDULE_SIZE];
|
||||
uint16_t TV_Count; /* the number of time values actually used */
|
||||
} BACNET_DAILY_SCHEDULE;
|
||||
} BACNET_OBJ_DAILY_SCHEDULE;
|
||||
|
||||
typedef struct schedule {
|
||||
/* Effective Period: Start and End Date */
|
||||
BACNET_DATE Start_Date;
|
||||
BACNET_DATE End_Date;
|
||||
/* Properties concerning Present Value */
|
||||
BACNET_DAILY_SCHEDULE Weekly_Schedule[7];
|
||||
BACNET_OBJ_DAILY_SCHEDULE Weekly_Schedule[7];
|
||||
BACNET_APPLICATION_DATA_VALUE Schedule_Default;
|
||||
BACNET_APPLICATION_DATA_VALUE *Present_Value; /* must be set to a valid value
|
||||
/*
|
||||
* Caution: This is a converted to BACNET_PRIMITIVE_APPLICATION_DATA_VALUE.
|
||||
* Only some data types may be used!
|
||||
*/
|
||||
BACNET_APPLICATION_DATA_VALUE Present_Value; /* must be set to a valid value
|
||||
* default is Schedule_Default */
|
||||
BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE
|
||||
Object_Property_References[BACNET_SCHEDULE_OBJ_PROP_REF_SIZE];
|
||||
|
||||
@@ -39,6 +39,15 @@
|
||||
#include "bacnet/basic/services.h"
|
||||
#include "bacnet/basic/tsm/tsm.h"
|
||||
|
||||
#if PRINT_ENABLED
|
||||
#include <stdio.h>
|
||||
#define PRINTF(...) fprintf(stdout,__VA_ARGS__)
|
||||
#define PRINTF_ERR(...) fprintf(stderr,__VA_ARGS__)
|
||||
#else
|
||||
#define PRINTF(...)
|
||||
#define PRINTF_ERR(...)
|
||||
#endif
|
||||
|
||||
/** @file h_rp_a.c Handles Read Property Acknowledgments. */
|
||||
|
||||
/** For debugging...
|
||||
@@ -67,6 +76,14 @@ void rp_ack_print_data(BACNET_READ_PROPERTY_DATA *data)
|
||||
len = bacapp_decode_known_property(
|
||||
application_data, (unsigned)application_data_len, &value,
|
||||
data->object_type, data->object_property);
|
||||
|
||||
if (len < 0) {
|
||||
PRINTF_ERR("RP Ack: unable to decode! %s:%s\n",
|
||||
bactext_object_type_name(data->object_type),
|
||||
bactext_property_name(data->object_property));
|
||||
break;
|
||||
}
|
||||
|
||||
if (first_value && (len < application_data_len)) {
|
||||
first_value = false;
|
||||
#if PRINT_ENABLED
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
#ifndef BAC_PLATFORM_H
|
||||
#define BAC_PLATFORM_H
|
||||
|
||||
/*
|
||||
* Macros to support different compilers and platforms
|
||||
*/
|
||||
|
||||
# ifdef _MSC_VER
|
||||
# define BACNET_STACK_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# define BACNET_STACK_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# endif
|
||||
|
||||
# if defined(WIN32) || defined(WIN64)
|
||||
# define strcasecmp _stricmp
|
||||
# endif
|
||||
|
||||
#endif // BAC_PLATFORM_H
|
||||
@@ -0,0 +1,57 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
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 "bacnet/dailyschedule.h"
|
||||
#include "bacnet/bactimevalue.h"
|
||||
|
||||
int bacnet_dailyschedule_decode(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
BACNET_DAILY_SCHEDULE * day)
|
||||
{
|
||||
unsigned int tv_count = 0;
|
||||
int retval = bacnet_time_values_context_decode(
|
||||
apdu, max_apdu_len, 0, &day->Time_Values[0], MAX_DAY_SCHEDULE_VALUES, &tv_count);
|
||||
day->TV_Count = (uint16_t) tv_count;
|
||||
return retval;
|
||||
}
|
||||
|
||||
int bacnet_dailyschedule_encode(
|
||||
uint8_t * apdu,
|
||||
BACNET_DAILY_SCHEDULE * day)
|
||||
{
|
||||
return bacnet_time_values_context_encode(
|
||||
apdu, 0, &day->Time_Values[0], day->TV_Count);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
#ifndef DAILYSCHEDULE_H
|
||||
#define DAILYSCHEDULE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "bacnet/bactimevalue.h"
|
||||
|
||||
/* arbitrary value, shall be unlimited for B-OWS but we don't care, 640k shall be enough */
|
||||
/* however we try not to boost the bacnet application value structure size, */
|
||||
/* so 7 x (this value) x sizeof(BACNET_TIME_VALUE) fits. */
|
||||
#define MAX_DAY_SCHEDULE_VALUES 40
|
||||
|
||||
/*
|
||||
BACnetDailySchedule ::= SEQUENCE {
|
||||
day-schedule [0] SEQUENCE OF BACnetTimeValue
|
||||
}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct BACnet_Daily_Schedule {
|
||||
BACNET_TIME_VALUE Time_Values[MAX_DAY_SCHEDULE_VALUES];
|
||||
uint16_t TV_Count; /* the number of time values actually used */
|
||||
} BACNET_DAILY_SCHEDULE;
|
||||
|
||||
/** Decode DailySchedule (sequence of times and values) */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_dailyschedule_decode(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
BACNET_DAILY_SCHEDULE * day);
|
||||
|
||||
/** Encode DailySchedule (sequence of times and values) */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_dailyschedule_encode(
|
||||
uint8_t * apdu,
|
||||
BACNET_DAILY_SCHEDULE * day);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DAILYSCHEDULE_H */
|
||||
@@ -0,0 +1,187 @@
|
||||
/*####COPYRIGHTBEGIN####
|
||||
-------------------------------------------
|
||||
Copyright (C) 2022 Steve Karg <skarg@users.sourceforge.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
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 "bacnet/weeklyschedule.h"
|
||||
#include "bacnet/bacdcode.h"
|
||||
#include "bacapp.h"
|
||||
|
||||
int bacnet_weeklyschedule_decode(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
BACNET_WEEKLY_SCHEDULE *value)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
int wi;
|
||||
|
||||
value->singleDay = false;
|
||||
for (wi = 0; wi < 7; wi++) {
|
||||
len = bacnet_dailyschedule_decode(
|
||||
&apdu[apdu_len], max_apdu_len - apdu_len, &value->weeklySchedule[wi]);
|
||||
if (len < 0) {
|
||||
if (wi == 1) {
|
||||
value->singleDay = true;
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacnet_weeklyschedule_encode(
|
||||
uint8_t * apdu,
|
||||
BACNET_WEEKLY_SCHEDULE *value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len = 0;
|
||||
int wi;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
for (wi = 0; wi < (value->singleDay ? 1 : 7); wi++) {
|
||||
/* not enough room to write data */
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len =
|
||||
bacnet_dailyschedule_encode(apdu_offset, &value->weeklySchedule[wi]);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
apdu_len += len;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Encode a context tagged WeeklySchedule complex data type
|
||||
* @param apdu - the APDU buffer
|
||||
* @param tag_number - the APDU buffer size
|
||||
* @param value - WeeklySchedule structure
|
||||
* @return length of the APDU buffer, or 0 if not able to encode
|
||||
*/
|
||||
int bacnet_weeklyschedule_context_encode(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_WEEKLY_SCHEDULE *value)
|
||||
{
|
||||
int len = 0;
|
||||
int apdu_len = 0;
|
||||
uint8_t *apdu_offset = NULL;
|
||||
|
||||
if (value) {
|
||||
apdu_offset = apdu;
|
||||
len = encode_opening_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = bacnet_weeklyschedule_encode(apdu_offset, value);
|
||||
apdu_len += len;
|
||||
if (apdu) {
|
||||
apdu_offset = &apdu[apdu_len];
|
||||
}
|
||||
len = encode_closing_tag(apdu_offset, tag_number);
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
int bacnet_weeklyschedule_context_decode(
|
||||
uint8_t *apdu, int max_apdu_len, uint8_t tag_number,
|
||||
BACNET_WEEKLY_SCHEDULE *value)
|
||||
{
|
||||
int apdu_len = 0;
|
||||
int len;
|
||||
|
||||
if ((max_apdu_len - apdu_len) >= 1 && decode_is_opening_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len += 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (-1 == (len = bacnet_weeklyschedule_decode(&apdu[apdu_len], max_apdu_len - apdu_len, value))) {
|
||||
return -1;
|
||||
} else {
|
||||
apdu_len += len;
|
||||
}
|
||||
|
||||
if ((max_apdu_len - apdu_len) >= 1 && decode_is_closing_tag_number(&apdu[apdu_len], tag_number)) {
|
||||
apdu_len += 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return apdu_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compare the BACnetWeeklySchedule complex data
|
||||
* @param value1 - BACNET_COLOR_COMMAND structure
|
||||
* @param value2 - BACNET_COLOR_COMMAND structure
|
||||
* @return true if the same
|
||||
*/
|
||||
bool bacnet_weeklyschedule_same(
|
||||
BACNET_WEEKLY_SCHEDULE *value1, BACNET_WEEKLY_SCHEDULE *value2)
|
||||
{
|
||||
int wi, ti;
|
||||
for (wi = 0; wi < 7; wi++) {
|
||||
BACNET_DAILY_SCHEDULE *ds1 = &value1->weeklySchedule[wi];
|
||||
BACNET_DAILY_SCHEDULE *ds2 = &value2->weeklySchedule[wi];
|
||||
if (ds1->TV_Count != ds2->TV_Count) {
|
||||
return false;
|
||||
}
|
||||
for (ti = 0; ti < ds1->TV_Count; ti++) {
|
||||
BACNET_TIME_VALUE *tv1 = &ds1->Time_Values[ti];
|
||||
BACNET_TIME_VALUE *tv2 = &ds2->Time_Values[ti];
|
||||
if (0 != datetime_compare_time(&tv1->Time, &tv2->Time)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO the conversion can be avoided by adding a "primitive" variant of bacapp_same_value(),
|
||||
// at the cost of some code duplication
|
||||
BACNET_APPLICATION_DATA_VALUE adv1, adv2;
|
||||
bacnet_primitive_to_application_data_value(&adv1, &tv1->Value);
|
||||
bacnet_primitive_to_application_data_value(&adv2, &tv2->Value);
|
||||
|
||||
if (!bacapp_same_value(&adv1, &adv2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/**************************************************************************
|
||||
*
|
||||
* Copyright (C) 2012 Steve Karg <skarg@users.sourceforge.net>
|
||||
*
|
||||
* 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.
|
||||
*********************************************************************/
|
||||
#ifndef WEEKLYSCHEDULE_H
|
||||
#define WEEKLYSCHEDULE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "bacnet/bacnet_stack_exports.h"
|
||||
#include "bacnet/dailyschedule.h"
|
||||
#include "bacnet/bactimevalue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct BACnet_Weekly_Schedule {
|
||||
BACNET_DAILY_SCHEDULE weeklySchedule[7];
|
||||
bool singleDay;
|
||||
} BACNET_WEEKLY_SCHEDULE;
|
||||
|
||||
/** Decode WeeklySchedule */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_weeklyschedule_decode(
|
||||
uint8_t * apdu,
|
||||
int max_apdu_len,
|
||||
BACNET_WEEKLY_SCHEDULE * value);
|
||||
|
||||
/** Encode WeeklySchedule */
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_weeklyschedule_encode(
|
||||
uint8_t * apdu,
|
||||
BACNET_WEEKLY_SCHEDULE * value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_weeklyschedule_context_encode(
|
||||
uint8_t *apdu, uint8_t tag_number, BACNET_WEEKLY_SCHEDULE *value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
int bacnet_weeklyschedule_context_decode(
|
||||
uint8_t *apdu, int max_apdu_len, uint8_t tag_number,
|
||||
BACNET_WEEKLY_SCHEDULE *value);
|
||||
|
||||
BACNET_STACK_EXPORT
|
||||
bool bacnet_weeklyschedule_same(
|
||||
BACNET_WEEKLY_SCHEDULE *value1, BACNET_WEEKLY_SCHEDULE *value2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* WEEKLYSCHEDULE_H */
|
||||
@@ -70,6 +70,7 @@ list(APPEND testdirs
|
||||
bacnet/whohas
|
||||
bacnet/whois
|
||||
bacnet/wp
|
||||
bacnet/weeklyschedule
|
||||
)
|
||||
|
||||
# bacnet/basic/*
|
||||
|
||||
@@ -50,6 +50,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/datalink/bvlc.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -48,6 +48,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,8 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <ztest.h>
|
||||
#include "bacnet/bactimevalue.h"
|
||||
#include "bacnet/datetime.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -35,26 +36,30 @@ static void test_BACnetTimeValue(BACNET_TIME_VALUE *value)
|
||||
bool status = false;
|
||||
uint8_t tag_number = 0;
|
||||
|
||||
len = bacapp_encode_time_value(apdu, value);
|
||||
apdu_len = bacapp_decode_time_value(apdu, &test_value);
|
||||
len = bacnet_time_value_encode(apdu, value);
|
||||
apdu_len = bacnet_time_value_decode(apdu, len, &test_value);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
diff = datetime_compare_time(&test_value.Time, &value->Time);
|
||||
zassert_true(diff == 0, NULL);
|
||||
status = bacapp_same_value(&test_value.Value, &value->Value);
|
||||
status = bacapp_same_value(
|
||||
(BACNET_APPLICATION_DATA_VALUE *) &test_value.Value,
|
||||
(BACNET_APPLICATION_DATA_VALUE *) &value->Value);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
len = bacapp_encode_context_time_value(apdu, tag_number, value);
|
||||
apdu_len = bacapp_decode_context_time_value(apdu, tag_number, &test_value);
|
||||
len = bacnet_time_value_context_encode(apdu, tag_number, value);
|
||||
apdu_len = bacnet_time_value_context_decode(apdu, len, tag_number, &test_value);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
diff = datetime_compare_time(&test_value.Time, &value->Time);
|
||||
zassert_true(diff == 0, NULL);
|
||||
status = bacapp_same_value(&test_value.Value, &value->Value);
|
||||
status = bacapp_same_value(
|
||||
(BACNET_APPLICATION_DATA_VALUE *) &test_value.Value,
|
||||
(BACNET_APPLICATION_DATA_VALUE *) &value->Value);
|
||||
zassert_true(status, NULL);
|
||||
/* negative testing */
|
||||
tag_number++;
|
||||
apdu_len = bacapp_decode_context_time_value(apdu, tag_number, &test_value);
|
||||
apdu_len = bacnet_time_value_context_decode(apdu, len, tag_number, &test_value);
|
||||
zassert_true(apdu_len < 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -48,6 +48,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/basic/sys/days.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -52,6 +52,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -48,6 +48,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -50,6 +50,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -53,6 +53,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <ztest.h>
|
||||
#include <bacnet/basic/object/ai.h>
|
||||
#include <bacnet/bactext.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <ztest.h>
|
||||
#include <bacnet/basic/object/bi.h>
|
||||
#include <bacnet/bactext.h>
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -52,6 +52,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
|
||||
@@ -52,6 +52,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -52,6 +52,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -90,6 +90,8 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/reject.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
./stubs.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
./stubs.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -50,6 +50,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -52,6 +52,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/proplist.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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${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
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -50,6 +50,8 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/wp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -50,6 +50,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -51,6 +51,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/memcopy.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -50,6 +50,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# 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
|
||||
BACAPP_ALL
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${SRC_DIR}
|
||||
${TST_DIR}/ztest/include
|
||||
)
|
||||
|
||||
add_executable(${PROJECT_NAME}
|
||||
# File(s) under test
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Support files and stubs (pathname alphabetical)
|
||||
${SRC_DIR}/bacnet/bacapp.c
|
||||
${SRC_DIR}/bacnet/bacdcode.c
|
||||
${SRC_DIR}/bacnet/bacint.c
|
||||
${SRC_DIR}/bacnet/bacdevobjpropref.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/datetime.c
|
||||
${SRC_DIR}/bacnet/basic/sys/days.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/hostnport.c
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
${ZTST_DIR}/ztest.c
|
||||
)
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file
|
||||
* @brief Unit test for BACnetWeeklySchedule
|
||||
* @author Ondřej Hruška <ondra@ondrovo.com>
|
||||
* @date Aug 2022
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <ztest.h>
|
||||
#include "bacnet/bactimevalue.h"
|
||||
#include "bacnet/weeklyschedule.h"
|
||||
#include "bacnet/dailyschedule.h"
|
||||
#include "bacnet/datetime.h"
|
||||
#include "bacnet/bacapp.h"
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup bacnet_tests
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Test encode/decode API
|
||||
*/
|
||||
static void test_BACnetWeeklySchedule()
|
||||
{
|
||||
int len, apdu_len;
|
||||
uint8_t apdu[MAX_APDU] = { 0 };
|
||||
BACNET_WEEKLY_SCHEDULE empty_value = { 0 };
|
||||
BACNET_WEEKLY_SCHEDULE value = { 0 };
|
||||
BACNET_WEEKLY_SCHEDULE decoded = { 0 };
|
||||
int diff = 0;
|
||||
bool status = false;
|
||||
uint8_t tag_number = 0;
|
||||
|
||||
value.weeklySchedule[0].TV_Count = 2;
|
||||
|
||||
value.weeklySchedule[0].Time_Values[0].Time = (BACNET_TIME) {
|
||||
.hour = 5,
|
||||
.min = 30
|
||||
};
|
||||
value.weeklySchedule[0].Time_Values[0].Value = (BACNET_PRIMITIVE_DATA_VALUE) {
|
||||
.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||
.type.Unsigned_Int = 123,
|
||||
};
|
||||
|
||||
value.weeklySchedule[0].Time_Values[1].Time = (BACNET_TIME) {
|
||||
.hour = 15,
|
||||
.min = 0
|
||||
};
|
||||
value.weeklySchedule[0].Time_Values[1].Value = (BACNET_PRIMITIVE_DATA_VALUE) {
|
||||
.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||
.type.Unsigned_Int = 456,
|
||||
};
|
||||
|
||||
value.weeklySchedule[6].TV_Count = 1;
|
||||
value.weeklySchedule[6].Time_Values[0].Value = (BACNET_PRIMITIVE_DATA_VALUE) {
|
||||
.tag = BACNET_APPLICATION_TAG_UNSIGNED_INT,
|
||||
.type.Unsigned_Int = 777,
|
||||
};
|
||||
|
||||
|
||||
len = bacnet_weeklyschedule_encode(apdu, &value);
|
||||
apdu_len = bacnet_weeklyschedule_decode(apdu, len, &decoded);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
status = bacnet_weeklyschedule_same(&value, &decoded);
|
||||
zassert_true(status, NULL);
|
||||
// Check that the compare function really compares:
|
||||
status = bacnet_weeklyschedule_same(&empty_value, &decoded);
|
||||
zassert_false(status, NULL);
|
||||
|
||||
len = bacnet_weeklyschedule_context_encode(apdu, tag_number, &value);
|
||||
apdu_len = bacnet_weeklyschedule_context_decode(apdu, len, tag_number, &decoded);
|
||||
zassert_true(len > 0, NULL);
|
||||
zassert_true(apdu_len > 0, NULL);
|
||||
status = bacnet_weeklyschedule_same(&value, &decoded);
|
||||
zassert_true(status, NULL);
|
||||
|
||||
/* negative testing - the tag differs */
|
||||
tag_number++;
|
||||
apdu_len = bacnet_weeklyschedule_context_decode(apdu, len, tag_number, &decoded);
|
||||
zassert_true(apdu_len < 0, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(BACnetWeeklySchedule_tests,
|
||||
ztest_unit_test(test_BACnetWeeklySchedule)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(BACnetWeeklySchedule_tests);
|
||||
}
|
||||
@@ -49,6 +49,9 @@ add_executable(${PROJECT_NAME}
|
||||
${SRC_DIR}/bacnet/lighting.c
|
||||
${SRC_DIR}/bacnet/timestamp.c
|
||||
${SRC_DIR}/bacnet/indtext.c
|
||||
${SRC_DIR}/bacnet/weeklyschedule.c
|
||||
${SRC_DIR}/bacnet/bactimevalue.c
|
||||
${SRC_DIR}/bacnet/dailyschedule.c
|
||||
# Test and test library files
|
||||
./src/main.c
|
||||
${ZTST_DIR}/ztest_mock.c
|
||||
|
||||
Reference in New Issue
Block a user