Feature/date time mstimer clock (#861)

* Added daylight savings time calculation module with unit testing.

* Added datetime daylight savings time and clock API

* Added basic datetime_local() clock using mstimer as basis and time-sync option.  Integrated clock with ports/stm32f4xx example.
This commit is contained in:
Steve Karg
2024-11-24 11:20:25 -06:00
committed by GitHub
parent cdda524afc
commit fd3be47d86
19 changed files with 992 additions and 93 deletions
+76 -8
View File
@@ -18,6 +18,7 @@
#include "bacnet/bacstr.h"
#include "bacnet/bacenum.h"
#include "bacnet/apdu.h"
#include "bacnet/datetime.h"
#include "bacnet/dcc.h"
#include "bacnet/datalink/datalink.h"
#include "bacnet/version.h"
@@ -49,11 +50,12 @@ static struct my_object_functions {
read_property_function Object_Read_Property;
write_property_function Object_Write_Property;
rpm_property_lists_function Object_RPM_List;
} Object_Table[] = { { OBJECT_DEVICE, NULL, /* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
} Object_Table[] = { { OBJECT_DEVICE, NULL,
/* don't init - recursive! */
Device_Count, Device_Index_To_Instance,
Device_Valid_Object_Instance_Number,
Device_Object_Name, Device_Read_Property_Local,
Device_Write_Property_Local, Device_Property_Lists },
{ OBJECT_ANALOG_INPUT, Analog_Input_Init, Analog_Input_Count,
Analog_Input_Index_To_Instance, Analog_Input_Valid_Instance,
Analog_Input_Object_Name, Analog_Input_Read_Property,
@@ -116,7 +118,9 @@ static const char *BACnet_Version = BACNET_VERSION_TEXT;
static uint8_t Device_UUID[16];
/* These three arrays are used by the ReadPropertyMultiple handler */
static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
static const int Device_Properties_Required[] = {
/* required properties for this object */
PROP_OBJECT_IDENTIFIER,
PROP_OBJECT_NAME, PROP_OBJECT_TYPE, PROP_SYSTEM_STATUS, PROP_VENDOR_NAME,
PROP_VENDOR_IDENTIFIER, PROP_MODEL_NAME, PROP_FIRMWARE_REVISION,
PROP_APPLICATION_SOFTWARE_VERSION, PROP_PROTOCOL_VERSION,
@@ -126,8 +130,17 @@ static const int Device_Properties_Required[] = { PROP_OBJECT_IDENTIFIER,
PROP_APDU_TIMEOUT, PROP_NUMBER_OF_APDU_RETRIES, PROP_DEVICE_ADDRESS_BINDING,
PROP_DATABASE_REVISION, -1 };
static const int Device_Properties_Optional[] = { PROP_DESCRIPTION,
PROP_LOCATION, PROP_MAX_MASTER, PROP_MAX_INFO_FRAMES, PROP_DEVICE_UUID,
static const int Device_Properties_Optional[] = {
/* optional properties for this object */
PROP_DESCRIPTION,
PROP_LOCATION,
PROP_MAX_MASTER,
PROP_MAX_INFO_FRAMES,
PROP_DEVICE_UUID,
PROP_LOCAL_DATE,
PROP_LOCAL_TIME,
PROP_UTC_OFFSET,
PROP_DAYLIGHT_SAVINGS_STATUS,
-1 };
static const int Device_Properties_Proprietary[] = { -1 };
@@ -686,6 +699,10 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
BACNET_BIT_STRING bit_string = { 0 };
BACNET_CHARACTER_STRING char_string = { 0 };
BACNET_OCTET_STRING octet_string = { 0 };
BACNET_DATE bdate;
BACNET_TIME btime;
int16_t utc_offset_minutes;
bool dst_active;
uint32_t i = 0;
uint32_t count = 0;
uint8_t *apdu = NULL;
@@ -817,6 +834,23 @@ int Device_Read_Property_Local(BACNET_READ_PROPERTY_DATA *rpdata)
octetstring_init(&octet_string, Device_UUID, sizeof(Device_UUID));
apdu_len = encode_application_octet_string(&apdu[0], &octet_string);
break;
case PROP_LOCAL_TIME:
datetime_local(&bdate, &btime, &utc_offset_minutes, &dst_active);
apdu_len = encode_application_time(&apdu[0], &btime);
break;
case PROP_LOCAL_DATE:
datetime_local(&bdate, &btime, &utc_offset_minutes, &dst_active);
apdu_len = encode_application_date(&apdu[0], &bdate);
break;
case PROP_UTC_OFFSET:
datetime_local(&bdate, &btime, &utc_offset_minutes, &dst_active);
apdu_len = encode_application_signed(&apdu[0], utc_offset_minutes);
break;
case PROP_DAYLIGHT_SAVINGS_STATUS:
datetime_local(&bdate, &btime, &utc_offset_minutes, &dst_active);
apdu_len =
encode_application_boolean(&apdu[0], dst_active);
break;
default:
rpdata->error_class = ERROR_CLASS_PROPERTY;
rpdata->error_code = ERROR_CODE_UNKNOWN_PROPERTY;
@@ -1060,6 +1094,39 @@ bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE;
}
break;
case PROP_LOCAL_TIME:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_TIME);
if (status) {
status = datetime_time_is_valid(&value.type.Time);
if (status) {
datetime_timesync(NULL, &value.type.Time, false);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_LOCAL_DATE:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_DATE);
if (status) {
status = datetime_date_is_valid(&value.type.Date);
if (status) {
datetime_timesync(&value.type.Date, NULL, false);
} else {
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
}
break;
case PROP_UTC_OFFSET:
status = write_property_type_valid(
wp_data, &value, BACNET_APPLICATION_TAG_SIGNED_INT);
if (status) {
datetime_utc_offset_minutes_set(value.type.Signed_Int);
}
break;
case PROP_OBJECT_TYPE:
case PROP_VENDOR_NAME:
case PROP_VENDOR_IDENTIFIER:
@@ -1076,6 +1143,7 @@ bool Device_Write_Property_Local(BACNET_WRITE_PROPERTY_DATA *wp_data)
case PROP_DEVICE_ADDRESS_BINDING:
case PROP_ACTIVE_COV_SUBSCRIPTIONS:
case PROP_DATABASE_REVISION:
case PROP_DAYLIGHT_SAVINGS_STATUS:
wp_data->error_class = ERROR_CLASS_PROPERTY;
wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED;
break;