From f7724eea6abe3daac577b440370cdbfac113ee73 Mon Sep 17 00:00:00 2001 From: skarg Date: Sun, 19 Jan 2014 19:55:20 +0000 Subject: [PATCH] Fixed Send_TimeSyncUTC(). Fixes bug https://sourceforge.net/p/bacnet/bugs/28/ Added functions in s_ts.c that reference Device object Local_Time, UTC_Offset, and Daylight_Savings_Time properties. Implements feature request https://sourceforge.net/p/bacnet/bugs/27/ --- bacnet-stack/demo/handler/s_ts.c | 36 +++++++++- bacnet-stack/demo/object/device-client.c | 89 ++++++++++++++++++++++-- bacnet-stack/demo/object/device.c | 12 ++++ bacnet-stack/demo/object/device.h | 2 + bacnet-stack/include/client.h | 2 + 5 files changed, 134 insertions(+), 7 deletions(-) diff --git a/bacnet-stack/demo/handler/s_ts.c b/bacnet-stack/demo/handler/s_ts.c index baadc80b..2380a5ee 100644 --- a/bacnet-stack/demo/handler/s_ts.c +++ b/bacnet-stack/demo/handler/s_ts.c @@ -65,7 +65,6 @@ void Send_TimeSync_Remote( pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], dest, &my_address, &npdu_data); - /* encode the APDU portion of the packet */ len = timesync_encode_apdu(&Handler_Transmit_Buffer[pdu_len], bdate, btime); @@ -112,10 +111,9 @@ void Send_TimeSyncUTC( pdu_len = npdu_encode_pdu(&Handler_Transmit_Buffer[0], &dest, &my_address, &npdu_data); - /* encode the APDU portion of the packet */ pdu_len = - timesync_utc_encode_apdu(&Handler_Transmit_Buffer[0], bdate, btime); + timesync_utc_encode_apdu(&Handler_Transmit_Buffer[pdu_len], bdate, btime); bytes_sent = datalink_send_pdu(&dest, &npdu_data, &Handler_Transmit_Buffer[0], pdu_len); @@ -126,3 +124,35 @@ void Send_TimeSyncUTC( strerror(errno)); #endif } + +/** + * Sends a UTC TimeSync message using the local time from the device. + */ +void Send_TimeSyncUTC_Device(void) +{ + int32_t utc_offset_minutes = 0; + bool dst = false; + BACNET_DATE_TIME local_time; + BACNET_DATE_TIME utc_time; + + Device_getCurrentDateTime(&local_time); + dst = Device_Daylight_Savings_Status(); + utc_offset_minutes = Device_UTC_Offset(); + datetime_copy(&utc_time, &local_time); + datetime_add_minutes(&utc_time, utc_offset_minutes); + if (dst) { + datetime_add_minutes(&utc_time, -60); + } + Send_TimeSyncUTC(&utc_time.date, &utc_time.time); +} + +/** + * Sends a TimeSync message using the local time from the device. + */ +void Send_TimeSync_Device(void) +{ + BACNET_DATE_TIME local_time; + + Device_getCurrentDateTime(&local_time); + Send_TimeSync(&local_time.date, &local_time.time); +} diff --git a/bacnet-stack/demo/object/device-client.c b/bacnet-stack/demo/object/device-client.c index 962f6554..76ffcd92 100644 --- a/bacnet-stack/demo/object/device-client.c +++ b/bacnet-stack/demo/object/device-client.c @@ -32,6 +32,10 @@ #include #include /* for memmove */ #include /* for timezone, localtime */ +/* OS specific include*/ +#include "net.h" +#include "timer.h" +/* BACnet includes */ #include "bacdef.h" #include "bacdcode.h" #include "bacenum.h" @@ -69,14 +73,14 @@ static char *Description = "command line client"; /* static uint8_t Max_Segments_Accepted = 0; */ /* VT_Classes_Supported */ /* Active_VT_Sessions */ -/* static BACNET_TIME Local_Time; rely on OS, if there is one */ -/* static BACNET_DATE Local_Date; rely on OS, if there is one */ +static BACNET_TIME Local_Time; /* rely on OS, if there is one */ +static BACNET_DATE Local_Date; /* rely on OS, if there is one */ /* NOTE: BACnet UTC Offset is inverse of common practice. If your UTC offset is -5hours of GMT, then BACnet UTC offset is +5hours. BACnet UTC offset is expressed in minutes. */ -/* static int32_t UTC_Offset = 5 * 60; */ -/* static bool Daylight_Savings_Status = false; rely on OS */ +static int32_t UTC_Offset = 5 * 60; +static bool Daylight_Savings_Status = false; /* rely on OS */ /* List_Of_Session_Keys */ /* Time_Synchronization_Recipients */ /* Max_Master - rely on MS/TP subsystem, if there is one */ @@ -633,6 +637,83 @@ bool Device_Object_Name_Copy( return found; } +static void Update_Current_Time( + void) +{ + struct tm *tblock = NULL; +#if defined(_MSC_VER) + time_t tTemp; +#else + struct timeval tv; +#endif +/* +struct tm + +int tm_sec Seconds [0,60]. +int tm_min Minutes [0,59]. +int tm_hour Hour [0,23]. +int tm_mday Day of month [1,31]. +int tm_mon Month of year [0,11]. +int tm_year Years since 1900. +int tm_wday Day of week [0,6] (Sunday =0). +int tm_yday Day of year [0,365]. +int tm_isdst Daylight Savings flag. +*/ +#if defined(_MSC_VER) + time(&tTemp); + tblock = (struct tm *)localtime(&tTemp); +#else + if (gettimeofday(&tv, NULL) == 0) { + tblock = (struct tm *)localtime((const time_t *)&tv.tv_sec); + } +#endif + + if (tblock) { + datetime_set_date(&Local_Date, (uint16_t) tblock->tm_year + 1900, + (uint8_t) tblock->tm_mon + 1, (uint8_t) tblock->tm_mday); +#if !defined(_MSC_VER) + datetime_set_time(&Local_Time, (uint8_t) tblock->tm_hour, + (uint8_t) tblock->tm_min, (uint8_t) tblock->tm_sec, + (uint8_t) (tv.tv_usec / 10000)); +#else + datetime_set_time(&Local_Time, (uint8_t) tblock->tm_hour, + (uint8_t) tblock->tm_min, (uint8_t) tblock->tm_sec, 0); +#endif + if (tblock->tm_isdst) { + Daylight_Savings_Status = true; + } else { + Daylight_Savings_Status = false; + } + /* note: timezone is declared in stdlib. */ + UTC_Offset = timezone / 60; + } else { + datetime_date_wildcard_set(&Local_Date); + datetime_time_wildcard_set(&Local_Time); + Daylight_Savings_Status = false; + } +} + +void Device_getCurrentDateTime( + BACNET_DATE_TIME * DateTime) +{ + Update_Current_Time(); + + DateTime->date = Local_Date; + DateTime->time = Local_Time; +} + +int32_t Device_UTC_Offset(void) +{ + Update_Current_Time(); + + return UTC_Offset; +} + +bool Device_Daylight_Savings_Status(void) +{ + return Daylight_Savings_Status; +} + /* return the length of the apdu encoded or BACNET_STATUS_ERROR for error or BACNET_STATUS_ABORT for abort message */ int Device_Read_Property_Local( diff --git a/bacnet-stack/demo/object/device.c b/bacnet-stack/demo/object/device.c index d924b40c..33d234e0 100644 --- a/bacnet-stack/demo/object/device.c +++ b/bacnet-stack/demo/object/device.c @@ -1169,6 +1169,18 @@ void Device_getCurrentDateTime( DateTime->time = Local_Time; } +int32_t Device_UTC_Offset(void) +{ + Update_Current_Time(); + + return UTC_Offset; +} + +bool Device_Daylight_Savings_Status(void) +{ + return Daylight_Savings_Status; +} + /* return the length of the apdu encoded or BACNET_STATUS_ERROR for error or BACNET_STATUS_ABORT for abort message */ int Device_Read_Property_Local( diff --git a/bacnet-stack/demo/object/device.h b/bacnet-stack/demo/object/device.h index 8515855a..6dd0082c 100644 --- a/bacnet-stack/demo/object/device.h +++ b/bacnet-stack/demo/object/device.h @@ -235,6 +235,8 @@ extern "C" { void Device_getCurrentDateTime( BACNET_DATE_TIME * DateTime); + int32_t Device_UTC_Offset(void); + bool Device_Daylight_Savings_Status(void); void Device_Property_Lists( const int **pRequired, diff --git a/bacnet-stack/include/client.h b/bacnet-stack/include/client.h index 7c7c41a9..27a37579 100644 --- a/bacnet-stack/include/client.h +++ b/bacnet-stack/include/client.h @@ -179,6 +179,8 @@ extern "C" { void Send_TimeSyncUTC( BACNET_DATE * bdate, BACNET_TIME * btime); + void Send_TimeSyncUTC_Device(void); + void Send_TimeSync_Device(void); uint8_t Send_Atomic_Read_File_Stream( uint32_t device_id,