Implement missing data types for calendar and schedule (#474)

* Added the SpecialEvent struct for the Exception_Schedule property of Schedule, encode/decode/same functions, unit tests, and integrated into bacapp functions.

* Added the CalendarEntry struct for the Date_List property of Calendar and the SpecialEvent struct, encode/decode functions, unit tests, and integrated into bacapp functions.

* Added the DateRange struct for the Effective_Period property of Schedule, encode/decode functions, unit tests, and integrated into bacapp functions.

---------

Co-authored-by: Steve Karg <skarg@users.sourceforge.net>
This commit is contained in:
Ondřej Hruška
2024-02-01 17:57:46 +01:00
committed by GitHub
parent 7ad82f19a0
commit 340bd09561
120 changed files with 2003 additions and 124 deletions
+149 -12
View File
@@ -55,6 +55,8 @@
#include "bacnet/lighting.h"
#include "bacnet/hostnport.h"
#include "bacnet/weeklyschedule.h"
#include "bacnet/calendar_entry.h"
#include "bacnet/special_event.h"
#include "bacnet/basic/sys/platform.h"
/** @file bacapp.c Utilities for the BACnet_Application_Data_Value */
@@ -157,6 +159,11 @@ int bacapp_encode_application_data(
apdu_len = bacapp_encode_datetime(apdu, &value->type.Date_Time);
break;
#endif
#if defined(BACAPP_DATERANGE)
case BACNET_APPLICATION_TAG_DATERANGE:
apdu_len = bacnet_daterange_encode(apdu, &value->type.Date_Range);
break;
#endif
#if defined(BACAPP_LIGHTING_COMMAND)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
/* BACnetLightingCommand */
@@ -184,6 +191,20 @@ int bacapp_encode_application_data(
apdu, &value->type.Weekly_Schedule);
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
/* BACnetCalendarEntry */
apdu_len = bacnet_calendar_entry_encode(
apdu, &value->type.Calendar_Entry);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
/* BACnetSpecialEvent */
apdu_len = bacnet_special_event_encode(
apdu, &value->type.Special_Event);
break;
#endif
#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
/* BACnetHostNPort */
@@ -336,6 +357,12 @@ int bacapp_decode_data(uint8_t *apdu,
apdu, len_value_type, &value->type.Date_Time);
break;
#endif
#if defined(BACAPP_DATERANGE)
case BACNET_APPLICATION_TAG_DATERANGE:
len = bacnet_daterange_decode(apdu, len_value_type,
&value->type.Date_Range);
break;
#endif
#if defined(BACAPP_LIGHTING_COMMAND)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
len = lighting_command_decode(
@@ -359,7 +386,19 @@ int bacapp_decode_data(uint8_t *apdu,
#if defined(BACAPP_WEEKLY_SCHEDULE)
case BACNET_APPLICATION_TAG_WEEKLY_SCHEDULE:
len = bacnet_weeklyschedule_decode(
apdu, len_value_type, &value->type.Weekly_Schedule);
apdu, (int) len_value_type, &value->type.Weekly_Schedule);
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
len = bacnet_calendar_entry_decode(
apdu, len_value_type, &value->type.Calendar_Entry);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
len = bacnet_special_event_decode(
apdu, (int) len_value_type, &value->type.Special_Event);
break;
#endif
#if defined(BACAPP_HOST_N_PORT)
@@ -692,6 +731,12 @@ int bacapp_encode_context_data_value(uint8_t *apdu,
apdu, context_tag_number, &value->type.Date_Time);
break;
#endif
#if defined(BACAPP_DATERANGE)
case BACNET_APPLICATION_TAG_DATERANGE:
apdu_len = bacnet_daterange_context_encode(
apdu, context_tag_number, &value->type.Date_Range);
break;
#endif
#if defined(BACAPP_LIGHTING_COMMAND)
case BACNET_APPLICATION_TAG_LIGHTING_COMMAND:
apdu_len = lighting_command_encode_context(
@@ -705,6 +750,20 @@ int bacapp_encode_context_data_value(uint8_t *apdu,
apdu, context_tag_number, &value->type.XY_Color);
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
/* BACnetWeeklySchedule */
apdu_len = bacnet_calendar_entry_context_encode(
apdu, context_tag_number, &value->type.Calendar_Entry);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
/* BACnetWeeklySchedule */
apdu_len = bacnet_special_event_context_encode(
apdu, context_tag_number, &value->type.Special_Event);
break;
#endif
#if defined(BACAPP_COLOR_COMMAND)
case BACNET_APPLICATION_TAG_COLOR_COMMAND:
/* BACnetColorCommand */
@@ -1216,19 +1275,19 @@ int bacapp_known_property_tag(
case PROP_EXCEPTION_SCHEDULE:
/* BACnetSpecialEvent (Schedule) */
return -1;
return BACNET_APPLICATION_TAG_SPECIAL_EVENT;
case PROP_DATE_LIST:
/* FIXME: Properties using : BACnetCalendarEntry */
return -1;
/* BACnetCalendarEntry */
return BACNET_APPLICATION_TAG_CALENDAR_ENTRY;
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
/* FIXME: BACnetCOVSubscription */
return -1;
case PROP_EFFECTIVE_PERIOD:
/* FIXME: Properties using BACnetDateRange (Schedule) */
return -1;
/* BACnetDateRange (Schedule) */
return BACNET_APPLICATION_TAG_DATERANGE;
case PROP_RECIPIENT_LIST:
/* Properties using BACnetDestination */
@@ -1417,19 +1476,37 @@ int bacapp_decode_known_property(uint8_t *apdu,
#endif
break;
case PROP_DATE_LIST:
#ifdef BACAPP_CALENDAR_ENTRY
/* List of BACnetCalendarEntry */
len = bacnet_calendar_entry_decode(
apdu, max_apdu_len, &value->type.Calendar_Entry);
#endif
break;
case PROP_EXCEPTION_SCHEDULE:
#ifdef BACAPP_SPECIAL_EVENT
/* List of BACnetSpecialEvent (Schedule) */
len = bacnet_special_event_decode(
apdu, max_apdu_len, &value->type.Special_Event);
#endif
break;
case PROP_EFFECTIVE_PERIOD:
#ifdef BACAPP_DATERANGE
/* BACnetDateRange (Schedule) */
len = bacnet_daterange_decode(
apdu, max_apdu_len, &value->type.Date_Range);
#endif
break;
/* properties without a specific decoder - fall through to default
*/
case PROP_LIST_OF_GROUP_MEMBERS:
/* Properties using ReadAccessSpecification */
case PROP_EXCEPTION_SCHEDULE:
/* BACnetSpecialEvent (Schedule) */
case PROP_DATE_LIST:
/* FIXME: Properties using : BACnetCalendarEntry */
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
/* FIXME: BACnetCOVSubscription */
case PROP_EFFECTIVE_PERIOD:
/* FIXME: Properties using BACnetDateRange (Schedule) */
case PROP_TIME_SYNCHRONIZATION_RECIPIENTS:
case PROP_RESTART_NOTIFICATION_RECIPIENTS:
case PROP_UTC_TIME_SYNCHRONIZATION_RECIPIENTS:
@@ -2305,6 +2382,26 @@ int bacapp_snprintf_value(
ret_val += slen;
break;
#endif
#if defined(BACAPP_DATERANGE)
case BACNET_APPLICATION_TAG_DATERANGE:
slen = bacapp_snprintf_date(str, str_len, &value->type.Date_Range.startdate);
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;
slen = bacapp_snprintf_date(str, str_len, &value->type.Date_Range.enddate);
ret_val += slen;
break;
#endif
#if defined(BACAPP_TIMESTAMP)
case BACNET_APPLICATION_TAG_TIMESTAMP:
/*ISO 8601 format */
@@ -2389,6 +2486,20 @@ int bacapp_snprintf_value(
&value->type.Weekly_Schedule, object_value->array_index);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
/* FIXME: add printing for BACnetSpecialEvent */
ret_val =
snprintf(str, str_len, "SpecialEvent(TODO)");
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
/* FIXME: add printing for BACnetCalendarEntry */
ret_val =
snprintf(str, str_len, "CalendarEntry(TODO)");
break;
#endif
#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
/* BACnetHostNPort */
@@ -2901,6 +3012,16 @@ bool bacapp_parse_application_data(BACNET_APPLICATION_TAG tag_number,
status = parse_weeklyschedule(argv, value);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
/* FIXME: add parsing for BACnetSpecialEvent */
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
/* FIXME: add parsing for BACnetCalendarEntry */
break;
#endif
#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
status =
@@ -3360,6 +3481,22 @@ bool bacapp_same_value(BACNET_APPLICATION_DATA_VALUE *value,
&test_value->type.Weekly_Schedule);
break;
#endif
#if defined(BACAPP_CALENDAR_ENTRY)
case BACNET_APPLICATION_TAG_CALENDAR_ENTRY:
/* BACnetCalendarEntry */
status =
bacnet_calendar_entry_same(&value->type.Calendar_Entry,
&test_value->type.Calendar_Entry);
break;
#endif
#if defined(BACAPP_SPECIAL_EVENT)
case BACNET_APPLICATION_TAG_SPECIAL_EVENT:
/* BACnetSpecialEvent */
status =
bacnet_special_event_same(&value->type.Special_Event,
&test_value->type.Special_Event);
break;
#endif
#if defined(BACAPP_HOST_N_PORT)
case BACNET_APPLICATION_TAG_HOST_N_PORT:
status = host_n_port_same(
+11
View File
@@ -38,6 +38,8 @@
#include "bacnet/hostnport.h"
#include "bacnet/timestamp.h"
#include "bacnet/weeklyschedule.h"
#include "bacnet/calendar_entry.h"
#include "bacnet/special_event.h"
struct BACnet_Application_Data_Value;
typedef struct BACnet_Application_Data_Value {
@@ -88,6 +90,9 @@ typedef struct BACnet_Application_Data_Value {
#if defined (BACAPP_DATETIME)
BACNET_DATE_TIME Date_Time;
#endif
#if defined (BACAPP_DATERANGE)
BACNET_DATE_RANGE Date_Range;
#endif
#if defined (BACAPP_LIGHTING_COMMAND)
BACNET_LIGHTING_COMMAND Lighting_Command;
#endif
@@ -117,6 +122,12 @@ typedef struct BACnet_Application_Data_Value {
#endif
#if defined (BACAPP_DESTINATION)
BACNET_DESTINATION Destination;
#endif
#if defined (BACAPP_CALENDAR_ENTRY)
BACNET_CALENDAR_ENTRY Calendar_Entry;
#endif
#if defined (BACAPP_SPECIAL_EVENT)
BACNET_SPECIAL_EVENT Special_Event;
#endif
} type;
/* simple linked list if needed */
+363
View File
@@ -0,0 +1,363 @@
/**
* @file
* @brief BACnetCalendarEntry complex data type encode and decode
* @author Ondřej Hruška <ondra@ondrovo.com>
* @author Steve Karg <skarg@users.sourceforge.net>
* @date May 2022
* @section LICENSE
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*/
#include <stdint.h>
#include "bacnet/calendar_entry.h"
#include "bacnet/bacapp.h"
#include "bacnet/bacdcode.h"
#include "bacnet/bactimevalue.h"
#include "bacnet/datetime.h"
#include "bacnet/basic/sys/days.h"
/** @file calendar_entry.c Manipulate BACnet calendar entry values */
/*
* @brief Encode the BACnetCalendarEntry complex data
*
* BACnetCalendarEntry ::= CHOICE {
* date [0] Date,
* date-range [1] BACnetDateRange,
* weekNDay [2] BACnetWeekNDay
* }
*
* @param apdu Pointer to the buffer for encoding, or NULL for only length
* @param value Pointer to the property data to be encoded.
* @return bytes encoded or zero on error.
*/
int bacnet_calendar_entry_encode(uint8_t *apdu, BACNET_CALENDAR_ENTRY *value)
{
int len = 0;
int apdu_len = 0;
BACNET_OCTET_STRING octetstring = { 0 };
switch (value->tag) {
case BACNET_CALENDAR_DATE:
len = encode_context_date(apdu, value->tag, &value->type.Date);
apdu_len += len;
break;
case BACNET_CALENDAR_DATE_RANGE:
len = bacnet_daterange_context_encode(
apdu, value->tag, &value->type.DateRange);
apdu_len += len;
break;
case BACNET_CALENDAR_WEEK_N_DAY:
octetstring.value[0] = value->type.WeekNDay.month;
octetstring.value[1] = value->type.WeekNDay.weekofmonth;
octetstring.value[2] = value->type.WeekNDay.dayofweek;
octetstring.length = 3;
len = encode_context_octet_string(apdu, value->tag, &octetstring);
apdu_len += len;
break;
default:
/* do nothing */
break;
}
return apdu_len;
}
/**
* @brief Encodes into bytes from the calendar-entry structure
* a context tagged chunk (opening and closing tag)
* @param apdu Pointer to the buffer for encoding, or NULL for only length
* @param tag_number - tag number to encode this chunk
* @param value - calendar entry value to encode
* @return number of bytes encoded, or 0 if unable to encode.
*/
int bacnet_calendar_entry_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_CALENDAR_ENTRY *value)
{
int len = 0;
int apdu_len = 0;
if (value) {
len = encode_opening_tag(apdu, tag_number);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = bacnet_calendar_entry_encode(apdu, value);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_closing_tag(apdu, tag_number);
apdu_len += len;
}
return apdu_len;
}
/**
* @brief Decodes from bytes into the calendar-entry structure
* @param apdu - buffer to hold the bytes
* @param apdu_size - number of bytes in the buffer to decode
* @param entry - calendar entry value to place the decoded values
* @return number of bytes decoded, or BACNET_STATUS_REJECT
*/
int bacnet_calendar_entry_decode(
uint8_t *apdu, uint32_t apdu_size, BACNET_CALENDAR_ENTRY *entry)
{
int apdu_len = 0;
int len = 0;
BACNET_TAG tag = { 0 };
BACNET_OCTET_STRING octet_string = { 0 };
if (!apdu || !entry) {
return BACNET_STATUS_REJECT;
}
len = bacnet_tag_decode(&apdu[apdu_len], apdu_size - apdu_len, &tag);
if (len <= 0) {
return BACNET_STATUS_REJECT;
}
if (tag.context || tag.opening) {
entry->tag = tag.number;
} else {
return BACNET_STATUS_REJECT;
}
switch (entry->tag) {
case BACNET_CALENDAR_DATE:
len = bacnet_date_context_decode(&apdu[apdu_len],
apdu_size - apdu_len, entry->tag, &entry->type.Date);
if (len <= 0) {
return BACNET_STATUS_REJECT;
}
apdu_len += len;
break;
case BACNET_CALENDAR_DATE_RANGE:
len = bacnet_daterange_context_decode(&apdu[apdu_len],
apdu_size - apdu_len, entry->tag, &entry->type.DateRange);
if (len <= 0) {
return BACNET_STATUS_REJECT;
}
apdu_len += len;
break;
case BACNET_CALENDAR_WEEK_N_DAY:
len = bacnet_octet_string_context_decode(&apdu[apdu_len],
apdu_size - apdu_len, entry->tag, &octet_string);
if (len <= 0) {
return BACNET_STATUS_REJECT;
}
apdu_len += len;
/* additional checks for valid Week-n-Day */
if (octet_string.length != 3) {
return BACNET_STATUS_ERROR;
}
entry->type.WeekNDay.month = octet_string.value[0];
entry->type.WeekNDay.weekofmonth = octet_string.value[1];
entry->type.WeekNDay.dayofweek = octet_string.value[2];
break;
default:
/* none */
return BACNET_STATUS_REJECT;
}
return apdu_len;
}
/**
* @brief Decodes from bytes into the calendar-entry structure
* a context tagged chunk (opening and closing tag)
* @param apdu - buffer to hold the bytes
* @param apdu_size - number of bytes in the buffer to decode
* @param tag_number - tag number to encode this chunk
* @param value - calendar entry value to place the decoded values
*
* @return number of bytes decoded, or BACNET_STATUS_REJECT
*/
int bacnet_calendar_entry_context_decode(uint8_t *apdu,
uint32_t apdu_size,
uint8_t tag_number,
BACNET_CALENDAR_ENTRY *value)
{
int apdu_len = 0;
int len = 0;
if (bacnet_is_opening_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_REJECT;
}
len = bacnet_calendar_entry_decode(
&apdu[apdu_len], apdu_size - apdu_len, value);
if (len <= 0) {
return BACNET_STATUS_REJECT;
} else {
apdu_len += len;
}
if (bacnet_is_closing_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_REJECT;
}
return apdu_len;
}
/**
* @brief Compare a month to a BACnetDate value month
* @param date - BACnetDate with a month value to compare
* @param month - month to compare
* @return true if the same month including special values, else false
*/
static bool month_match(BACNET_DATE *date, uint8_t month)
{
if (month == 0xff) {
return true;
}
if (!date) {
return false;
}
return ((month == date->month) ||
((month == 13) && (date->month % 2 == 1)) ||
((month == 14) && (date->month % 2 == 0)));
}
/**
* @brief Compare a week of the month to a BACnetDate value
* @param date - BACnetDate value to compare
* @param weekofmonth - week of the month to compare
* @return true if the same week of the month including special values
*/
static bool weekofmonth_match(BACNET_DATE *date, uint8_t weekofmonth)
{
bool st = false;
uint8_t day_to_end_month;
switch (weekofmonth) {
case 1:
case 2:
case 3:
case 4:
case 5:
if (date) {
st = (weekofmonth == (date->day - 1) % 7 + 1);
}
break;
case 6:
case 7:
case 8:
case 9:
if (date) {
day_to_end_month =
days_per_month(date->year, date->month) - date->day;
st = ((weekofmonth - 6) == day_to_end_month % 7);
}
break;
case 0xff:
st = true;
break;
default:
break;
}
return st;
}
/**
* @brief Compare a day of the week to a BACnetDate value
* @param date - BACnetDate value to compare
* @param dayofweek - day of the week to compare
* @return true if the same day of the week including special values
*/
static bool dayofweek_match(BACNET_DATE *date, uint8_t dayofweek)
{
if (dayofweek == 0xff) {
return true;
}
if (!date) {
return false;
}
return (dayofweek == date->wday);
}
/**
* @brief Determine if a BACnetCalendarEntry includes a BACnetDate value
* @param date - BACnetDate value to compare
* @param entry - BACnetCalendarEntry value to compare
* @return true if a BACnetCalendarEntry includes the BACnetDate value
*/
bool bacapp_date_in_calendar_entry(
BACNET_DATE *date, BACNET_CALENDAR_ENTRY *entry)
{
if (!entry) {
return false;
}
switch (entry->tag) {
case BACNET_CALENDAR_DATE:
if (datetime_compare_date(date, &entry->type.Date) == 0) {
return true;
}
break;
case BACNET_CALENDAR_DATE_RANGE:
if ((datetime_compare_date(
&entry->type.DateRange.startdate, date) <= 0) &&
(datetime_compare_date(date, &entry->type.DateRange.enddate) <=
0)) {
return true;
}
break;
case BACNET_CALENDAR_WEEK_N_DAY:
if (month_match(date, entry->type.WeekNDay.month) &&
weekofmonth_match(date, entry->type.WeekNDay.weekofmonth) &&
dayofweek_match(date, entry->type.WeekNDay.dayofweek)) {
return true;
}
break;
default:
/* do nothing */
break;
}
return false;
}
/**
* @brief Determine if two BACnetCalendarEntry are the same
* @param value1 - BACnetCalendarEntry value to compare
* @param value2 - BACnetCalendarEntry value to compare
* @return true if both BACnetCalendarEntry are the same
*/
bool bacnet_calendar_entry_same(
BACNET_CALENDAR_ENTRY *value1, BACNET_CALENDAR_ENTRY *value2)
{
if (!value1 || !value2) {
return false;
}
if (value1->tag != value2->tag) {
return false;
}
switch (value1->tag) {
case BACNET_CALENDAR_DATE:
return datetime_compare_date(
&value1->type.Date, &value2->type.Date) == 0;
case BACNET_CALENDAR_DATE_RANGE:
return (datetime_compare_date(&value1->type.DateRange.startdate,
&value2->type.DateRange.startdate) == 0) &&
(datetime_compare_date(&value2->type.DateRange.enddate,
&value2->type.DateRange.enddate) == 0);
case BACNET_CALENDAR_WEEK_N_DAY:
return (value1->type.WeekNDay.month ==
value2->type.WeekNDay.month) &&
(value1->type.WeekNDay.weekofmonth ==
value2->type.WeekNDay.weekofmonth) &&
(value1->type.WeekNDay.dayofweek ==
value2->type.WeekNDay.dayofweek);
default:
/* should be unreachable */
return false;
}
}
+78
View File
@@ -0,0 +1,78 @@
/**
* @file
* @brief API for BACnetCalendarEntry complex data type encode and decode
* @author Ondřej Hruška <ondra@ondrovo.com>
* @author Steve Karg <skarg@users.sourceforge.net>
* @date August 2023
* @section LICENSE
*
* SPDX-License-Identifier: MIT
*/
#ifndef BACNET_CALENDAR_ENTRY_H
#define BACNET_CALENDAR_ENTRY_H
#include <stdint.h>
#include <stdbool.h>
#include "bacnet/bacnet_stack_exports.h"
#include "bacnet/bactimevalue.h"
#include "bacnet/datetime.h"
/*
BACnetCalendarEntry ::= CHOICE {
date [0] Date,
date-range [1] BACnetDateRange,
weekNDay [2] BACnetWeekNDay
}
*/
typedef enum BACnet_CalendarEntry_Tags {
BACNET_CALENDAR_DATE = 0,
BACNET_CALENDAR_DATE_RANGE = 1,
BACNET_CALENDAR_WEEK_N_DAY = 2
} BACNET_CALENDAR_ENTRY_TAGS;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct BACnetCalendarEntry_T {
uint8_t tag;
union {
BACNET_DATE Date;
BACNET_DATE_RANGE DateRange;
BACNET_WEEKNDAY WeekNDay;
} type;
/* simple linked list if needed */
struct BACnetCalendarEntry_T *next;
} BACNET_CALENDAR_ENTRY;
BACNET_STACK_EXPORT
int bacnet_calendar_entry_encode(uint8_t *apdu, BACNET_CALENDAR_ENTRY *value);
BACNET_STACK_EXPORT
int bacnet_calendar_entry_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_CALENDAR_ENTRY *value);
BACNET_STACK_EXPORT
int bacnet_calendar_entry_decode(
uint8_t *apdu, uint32_t apdu_max_len, BACNET_CALENDAR_ENTRY *entry);
BACNET_STACK_EXPORT
int bacnet_calendar_entry_context_decode(
uint8_t *apdu, uint32_t apdu_max_len, uint8_t tag_number,
BACNET_CALENDAR_ENTRY *value);
BACNET_STACK_EXPORT
bool bacapp_date_in_calendar_entry(BACNET_DATE *date,
BACNET_CALENDAR_ENTRY *entry);
BACNET_STACK_EXPORT
bool bacnet_calendar_entry_same(
BACNET_CALENDAR_ENTRY *value1, BACNET_CALENDAR_ENTRY *value2);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+9
View File
@@ -157,10 +157,13 @@
defined(BACAPP_TIME) || \
defined(BACAPP_OBJECT_ID) || \
defined(BACAPP_DATETIME) || \
defined(BACAPP_DATERANGE) || \
defined(BACAPP_LIGHTING_COMMAND) || \
defined(BACAPP_XY_COLOR) || \
defined(BACAPP_COLOR_COMMAND) || \
defined(BACAPP_WEEKLY_SCHEDULE) || \
defined(BACAPP_CALENDAR_ENTRY) || \
defined(BACAPP_SPECIAL_EVENT) || \
defined(BACAPP_HOST_N_PORT) || \
defined(BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE) || \
defined(BACAPP_DEVICE_OBJECT_REFERENCE) || \
@@ -194,10 +197,13 @@
#define BACAPP_DOUBLE
#define BACAPP_TIMESTAMP
#define BACAPP_DATETIME
#define BACAPP_DATERANGE
#define BACAPP_LIGHTING_COMMAND
#define BACAPP_XY_COLOR
#define BACAPP_COLOR_COMMAND
#define BACAPP_WEEKLY_SCHEDULE
#define BACAPP_CALENDAR_ENTRY
#define BACAPP_SPECIAL_EVENT
#define BACAPP_HOST_N_PORT
#define BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE
#define BACAPP_DEVICE_OBJECT_REFERENCE
@@ -207,10 +213,13 @@
#if defined(BACAPP_DOUBLE) || \
defined(BACAPP_DATETIME) || \
defined(BACAPP_DATERANGE) || \
defined(BACAPP_LIGHTING_COMMAND) || \
defined(BACAPP_XY_COLOR) || \
defined(BACAPP_COLOR_COMMAND) || \
defined(BACAPP_WEEKLY_SCHEDULE) || \
defined(BACAPP_CALENDAR_ENTRY) || \
defined(BACAPP_SPECIAL_EVENT) || \
defined(BACAPP_HOST_N_PORT) || \
defined(BACAPP_DEVICE_OBJECT_PROPERTY_REFERENCE) || \
defined(BACAPP_DEVICE_OBJECT_REFERENCE) || \
+9 -6
View File
@@ -36,18 +36,21 @@ License.
#include "bacnet/dailyschedule.h"
#include "bacnet/bactimevalue.h"
int bacnet_dailyschedule_decode(
uint8_t *apdu, int max_apdu_len, BACNET_DAILY_SCHEDULE *day)
int bacnet_dailyschedule_context_decode(uint8_t *apdu,
int max_apdu_len,
uint8_t tag_number,
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);
int retval = bacnet_time_values_context_decode(apdu, max_apdu_len,
tag_number, &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)
int bacnet_dailyschedule_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_DAILY_SCHEDULE *day)
{
return bacnet_time_values_context_encode(
apdu, 0, &day->Time_Values[0], day->TV_Count);
apdu, tag_number, &day->Time_Values[0], day->TV_Count);
}
+4 -2
View File
@@ -51,15 +51,17 @@ extern "C" {
/** Decode DailySchedule (sequence of times and values) */
BACNET_STACK_EXPORT
int bacnet_dailyschedule_decode(
int bacnet_dailyschedule_context_decode(
uint8_t * apdu,
int max_apdu_len,
uint8_t tag_number,
BACNET_DAILY_SCHEDULE * day);
/** Encode DailySchedule (sequence of times and values) */
BACNET_STACK_EXPORT
int bacnet_dailyschedule_encode(
int bacnet_dailyschedule_context_encode(
uint8_t * apdu,
uint8_t tag_number,
BACNET_DAILY_SCHEDULE * day);
#ifdef __cplusplus
+161 -33
View File
@@ -1,36 +1,15 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2007 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####*/
/**
* @file
* @brief BACnetDate, BACnetTime, BACnetDateTime, BACnetDateRange complex data
* type encode and decode functions
* @author Steve Karg <skarg@users.sourceforge.net>
* @author Greg Shue <greg.shue@outlook.com>
* @author Ondřej Hruška <ondra@ondrovo.com>
* @date 2012
* @section LICENSE
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
@@ -1182,12 +1161,161 @@ int bacnet_datetime_context_decode(uint8_t *apdu,
return apdu_len;
}
/**
* @brief Decodes a context tagged BACnetDateTime value from APDU buffer
* @param apdu - the APDU buffer
* @param tag_number - context tag number to be encoded
* @param value - parameter to store the value after decoding
* @return length of the APDU buffer decoded, or BACNET_STATUS_ERROR
* @deprecated - use bacnet_datetime_context_decode() instead
*/
int bacapp_decode_context_datetime(
uint8_t *apdu, uint8_t tag_number, BACNET_DATE_TIME *value)
{
return bacnet_datetime_context_decode(apdu, MAX_APDU, tag_number, value);
}
/**
* @brief Encode BACnetDateRange complex data type
*
* BACnetDateRange ::= SEQUENCE { -- see Clause 20.2.12 for restrictions
* start-date Date,
* end-date Date
* }
*
* @param apdu - apdu buffer; NULL to only measure capacity needed
* @param value - value to encode
* @return number of bytes emitted, BACNET_STATUS_ERROR on error
*/
int bacnet_daterange_encode(uint8_t *apdu, BACNET_DATE_RANGE *value)
{
int len = 0;
int apdu_len = 0;
len = encode_application_date(apdu, &value->startdate);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_application_date(apdu, &value->enddate);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
return apdu_len;
}
/**
* @brief Decode BACnetDateRange complex data type
* @param apdu - apdu buffer; NULL to only measure capacity needed
* @param apdu_size - apdu buffer size
* @param value - value to decode
* @return number of bytes emitted, BACNET_STATUS_ERROR on error
*/
int bacnet_daterange_decode(
uint8_t *apdu, uint32_t apdu_size, BACNET_DATE_RANGE *value)
{
int len = 0;
int apdu_len = 0;
if (!apdu || !value) {
return BACNET_STATUS_ERROR;
}
len = bacnet_date_application_decode(
&apdu[apdu_len], apdu_size - apdu_len, &value->startdate);
if (len <= 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
len = bacnet_date_application_decode(
&apdu[apdu_len], apdu_size - apdu_len, &value->enddate);
if (len <= 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
return apdu_len;
}
/**
* @brief Encode daterange with context tag
* @param apdu - apdu buffer; NULL to only measure capacity needed
* @param tag_number - context tag number
* @param value - value to encode
* @return number of bytes decoded, or BACNET_STATUS_ERROR on error
*/
int bacnet_daterange_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_DATE_RANGE *value)
{
int len = 0;
int apdu_len = 0;
if (value) {
len = encode_opening_tag(apdu, tag_number);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = bacnet_daterange_encode(apdu, value);
if (len <= 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_closing_tag(apdu, tag_number);
apdu_len += len;
}
return apdu_len;
}
/**
* @brief Decode BACnetDateRange complex data with context tag
* @param apdu - apdu buffer to decode
* @param apdu_size - apdu buffer size
* @param tag_number - context tag number
* @param value - value to encode
* @return number of bytes decoded, BACNET_STATUS_ERROR on error
*/
int bacnet_daterange_context_decode(uint8_t *apdu,
uint32_t apdu_size,
uint8_t tag_number,
BACNET_DATE_RANGE *value)
{
int apdu_len = 0;
int len = 0;
if (!apdu || !value) {
return -1;
}
if (bacnet_is_opening_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_ERROR;
}
len = bacnet_daterange_decode(&apdu[apdu_len], apdu_size - apdu_len, value);
if (len <= 0) {
return BACNET_STATUS_ERROR;
} else {
apdu_len += len;
}
if (bacnet_is_closing_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_ERROR;
}
return apdu_len;
}
/**
* @brief Parse an ascii string for the date 2021/12/31 or 2021/12/31:1
* @param bdate - #BACNET_DATE structure
+29 -25
View File
@@ -1,28 +1,17 @@
/**************************************************************************
/**
* @file
* @brief API for BACnetDate, BACnetTime, BACnetDateTime, BACnetDateRange
* complex data type encode and decode
* @author Steve Karg <skarg@users.sourceforge.net>
* @author Greg Shue <greg.shue@outlook.com>
* @author Ondřej Hruška <ondra@ondrovo.com>
* @date 2012
* @section LICENSE
*
* 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 DATE_TIME_H
#define DATE_TIME_H
* SPDX-License-Identifier: MIT
*/
#ifndef BACNET_DATE_TIME_H
#define BACNET_DATE_TIME_H
#include <stdint.h>
#include <stdbool.h>
@@ -288,6 +277,21 @@ int bacapp_decode_context_datetime(uint8_t *apdu,
uint8_t tag_number,
BACNET_DATE_TIME *value);
BACNET_STACK_EXPORT
int bacnet_daterange_encode(uint8_t *apdu, BACNET_DATE_RANGE *value);
BACNET_STACK_EXPORT
int bacnet_daterange_decode(uint8_t *apdu,
uint32_t apdu_size,
BACNET_DATE_RANGE *value);
BACNET_STACK_EXPORT
int bacnet_daterange_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_DATE_RANGE *value);
BACNET_STACK_EXPORT
int bacnet_daterange_context_decode(uint8_t *apdu,
uint32_t apdu_size,
uint8_t tag_number,
BACNET_DATE_RANGE *value);
/* implementation agnostic functions - create your own! */
BACNET_STACK_EXPORT
bool datetime_local(BACNET_DATE *bdate,
@@ -300,4 +304,4 @@ void datetime_init(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* DATE_TIME_H */
#endif
+266
View File
@@ -0,0 +1,266 @@
/**
* @file
* @brief BACnetSpecialEvent complex data type encode and decode
* @author Ondřej Hruška <ondra@ondrovo.com>
* @author Steve Karg <skarg@users.sourceforge.net>
* @date May 2022
* @section LICENSE
*
* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0
*/
#include <stdint.h>
#include "bacnet/special_event.h"
#include "bacnet/bacdcode.h"
#include "bacapp.h"
/**
* @brief Decode a BACnetSpecialEvent complex data type
*
* BACnetSpecialEvent ::= SEQUENCE {
* period CHOICE {
* calendar-entry [0] BACnetCalendarEntry,
* calendar-reference [1] BACnetObjectIdentifier
* },
* list-of-time-values [2] SEQUENCE OF BACnetTimeValue,
* event-priority [3] Unsigned (1..16)
* }
*
* @param apdu - the APDU buffer
* @param apdu_size - the size of the APDU buffer
* @param value - BACnetSpecialEvent structure
* @return length of the APDU buffer, or BACNET_STATUS_ERROR if unable to decode
*/
int bacnet_special_event_decode(
uint8_t *apdu, int apdu_size, BACNET_SPECIAL_EVENT *value)
{
int len = 0;
int apdu_len = 0;
BACNET_UNSIGNED_INTEGER priority = 0;
BACNET_TAG tag = { 0 };
if (!apdu || !value) {
return BACNET_STATUS_ERROR;
}
len = bacnet_tag_decode(&apdu[apdu_len], apdu_size - apdu_len, &tag);
if (len <= 0) {
return BACNET_STATUS_ERROR;
}
if (tag.opening &&
(tag.number == BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY)) {
value->periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY;
len = bacnet_calendar_entry_context_decode(&apdu[apdu_len],
apdu_size - apdu_len, BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY,
&value->period.calendarEntry);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
} else if (tag.context &&
(tag.number == BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE)) {
value->periodTag = BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE;
len = bacnet_object_id_context_decode(&apdu[apdu_len],
apdu_size - apdu_len,
BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE,
&value->period.calendarReference.type,
&value->period.calendarReference.instance);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
} else {
return BACNET_STATUS_ERROR;
}
/* Values [2] */
len = bacnet_dailyschedule_context_decode(
&apdu[apdu_len], apdu_size - apdu_len, 2, &value->timeValues);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
apdu_len += len;
/* Priority [3] */
len = bacnet_unsigned_context_decode(
&apdu[apdu_len], apdu_size - apdu_len, 3, &priority);
if (len < 0) {
return BACNET_STATUS_ERROR;
}
if (priority > BACNET_MAX_PRIORITY) {
return BACNET_STATUS_ERROR;
}
value->priority = (uint8_t)priority;
apdu_len += len;
return apdu_len;
}
/**
* @brief Encode a BACnetSpecialEvent complex data type
* @param apdu - the APDU buffer (NULL to determine the length)
* @param value - BACnetSpecialEvent structure
* @return length of the APDU buffer, or 0 if not able to encode
*/
int bacnet_special_event_encode(uint8_t *apdu, BACNET_SPECIAL_EVENT *value)
{
int apdu_len = 0;
int len;
if (value->periodTag == BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY) {
len = bacnet_calendar_entry_context_encode(apdu,
BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY,
&value->period.calendarEntry);
if (len < 0) {
return -1;
}
apdu_len += len;
if (apdu) {
apdu += len;
}
} else {
len = encode_context_object_id(apdu,
BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE,
value->period.calendarReference.type,
value->period.calendarReference.instance);
if (len < 0) {
return -1;
}
apdu_len += len;
if (apdu) {
apdu += len;
}
}
len = bacnet_dailyschedule_context_encode(apdu, 2, &value->timeValues);
if (len < 0) {
return -1;
}
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_context_unsigned(apdu, 3, value->priority);
if (len < 0) {
return -1;
}
apdu_len += len;
return apdu_len;
}
/**
* @brief Encode a context tagged BACnetSpecialEvent complex data type
* @param apdu - the APDU buffer (NULL to determine the length)
* @param tag_number - tag number to context encode
* @param value - BACnetSpecialEvent structure
* @return length of the APDU buffer, or 0 if not able to encode
*/
int bacnet_special_event_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_SPECIAL_EVENT *value)
{
int len = 0;
int apdu_len = 0;
if (value) {
len = encode_opening_tag(apdu, tag_number);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = bacnet_special_event_encode(apdu, value);
apdu_len += len;
if (apdu) {
apdu += len;
}
len = encode_closing_tag(apdu, tag_number);
apdu_len += len;
}
return apdu_len;
}
/**
* @brief Decode a context tagged BACnetSpecialEvent complex data type
* @param apdu - the APDU buffer
* @param apdu_size - the size of the APDU buffer
* @param tag_number - tag number to context decode
* @param value - BACnetSpecialEvent structure
* @return length of the APDU buffer, or BACNET_STATUS_ERROR if unable to decode
*/
int bacnet_special_event_context_decode(uint8_t *apdu,
int apdu_size,
uint8_t tag_number,
BACNET_SPECIAL_EVENT *value)
{
int apdu_len = 0;
int len = 0;
if (bacnet_is_opening_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_ERROR;
}
len = bacnet_special_event_decode(
&apdu[apdu_len], apdu_size - apdu_len, value);
if (len < 0) {
return BACNET_STATUS_ERROR;
} else {
apdu_len += len;
}
if (bacnet_is_closing_tag_number(
&apdu[apdu_len], apdu_size - apdu_len, tag_number, &len)) {
apdu_len += len;
} else {
return BACNET_STATUS_ERROR;
}
return apdu_len;
}
/**
* @brief Compare the BACnetSpecialEvent complex data
* @param value1 - BACNET_SPECIAL_EVENT structure
* @param value2 - BACNET_SPECIAL_EVENT structure
* @return true if the same
*/
bool bacnet_special_event_same(
BACNET_SPECIAL_EVENT *value1, BACNET_SPECIAL_EVENT *value2)
{
BACNET_APPLICATION_DATA_VALUE adv1, adv2;
BACNET_TIME_VALUE *tv1, *tv2;
int ti;
if (value1->periodTag != value2->periodTag ||
value1->priority != value2->priority) {
return false;
}
if (value1->periodTag == BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY) {
if (!bacnet_calendar_entry_same(
&value1->period.calendarEntry, &value2->period.calendarEntry)) {
return false;
}
}
/* TODO extract shared code with `bacnet_weeklyschedule_same` */
if (value1->timeValues.TV_Count != value2->timeValues.TV_Count) {
return false;
}
for (ti = 0; ti < value1->timeValues.TV_Count; ti++) {
tv1 = &value1->timeValues.Time_Values[ti];
tv2 = &value2->timeValues.Time_Values[ti];
if (0 != datetime_compare_time(&tv1->Time, &tv2->Time)) {
return false;
}
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;
}
+71
View File
@@ -0,0 +1,71 @@
/**
* @file
* @brief API for BACnetSpecialEvent complex data type encode and decode
* @author Ondřej Hruška <ondra@ondrovo.com>
* @author Steve Karg <skarg@users.sourceforge.net>
* @date August 2023
* @section LICENSE
*
* SPDX-License-Identifier: MIT
*/
#ifndef BACNET_SPECIAL_EVENT_H
#define BACNET_SPECIAL_EVENT_H
#include <stdint.h>
#include <stdbool.h>
#include "bacnet/bacnet_stack_exports.h"
#include "bacnet/bactimevalue.h"
#include "bacnet/calendar_entry.h"
#include "bacnet/dailyschedule.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef enum BACnet_SpecialEventPeriod_Tags {
BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_ENTRY = 0,
BACNET_SPECIAL_EVENT_PERIOD_CALENDAR_REFERENCE = 1
} BACNET_SPECIAL_EVENT_PERIOD_TAG;
typedef struct BACnet_Special_Event {
BACNET_SPECIAL_EVENT_PERIOD_TAG periodTag;
union {
BACNET_CALENDAR_ENTRY calendarEntry;
BACNET_OBJECT_ID calendarReference;
} period;
/* We reuse the daily schedule struct and its encoding/decoding - it's identical */
BACNET_DAILY_SCHEDULE timeValues;
uint8_t priority;
} BACNET_SPECIAL_EVENT;
/** Decode Special Event */
BACNET_STACK_EXPORT
int bacnet_special_event_decode(
uint8_t * apdu,
int max_apdu_len,
BACNET_SPECIAL_EVENT * value);
/** Encode Special Event */
BACNET_STACK_EXPORT
int bacnet_special_event_encode(
uint8_t * apdu,
BACNET_SPECIAL_EVENT * value);
BACNET_STACK_EXPORT
int bacnet_special_event_context_encode(
uint8_t *apdu, uint8_t tag_number, BACNET_SPECIAL_EVENT *value);
BACNET_STACK_EXPORT
int bacnet_special_event_context_decode(
uint8_t *apdu, int max_apdu_len, uint8_t tag_number,
BACNET_SPECIAL_EVENT *value);
BACNET_STACK_EXPORT
bool bacnet_special_event_same(
BACNET_SPECIAL_EVENT *value1, BACNET_SPECIAL_EVENT *value2);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* BACNET_SPECIAL_EVENT_H */
+4 -4
View File
@@ -59,8 +59,8 @@ int bacnet_weeklyschedule_decode(
}
value->singleDay = false;
for (wi = 0; wi < 7; wi++) {
len = bacnet_dailyschedule_decode(&apdu[apdu_len],
max_apdu_len - apdu_len, &value->weeklySchedule[wi]);
len = bacnet_dailyschedule_context_decode(&apdu[apdu_len],
max_apdu_len - apdu_len, 0, &value->weeklySchedule[wi]);
if (len < 0) {
if (wi == 1) {
value->singleDay = true;
@@ -96,8 +96,8 @@ int bacnet_weeklyschedule_encode(uint8_t *apdu, BACNET_WEEKLY_SCHEDULE *value)
if (apdu) {
apdu_offset = &apdu[apdu_len];
}
len = bacnet_dailyschedule_encode(
apdu_offset, &value->weeklySchedule[wi]);
len = bacnet_dailyschedule_context_encode(
apdu_offset, 0, &value->weeklySchedule[wi]);
if (len < 0) {
return BACNET_STATUS_ERROR;
}