diff --git a/src/bacnet/basic/object/gateway/gw_device.c b/src/bacnet/basic/object/gateway/gw_device.c index 549fff1d..f7f2c461 100644 --- a/src/bacnet/basic/object/gateway/gw_device.c +++ b/src/bacnet/basic/object/gateway/gw_device.c @@ -29,12 +29,12 @@ #include #include #include /* for memmove */ -#include /* for timezone, localtime */ #include "bacnet/bacdef.h" #include "bacnet/bacdcode.h" #include "bacnet/bacenum.h" #include "bacnet/bacapp.h" #include "bacnet/config.h" /* the custom stuff */ +#include "bacnet/datetime.h" #include "bacnet/apdu.h" #include "bacnet/wp.h" /* write property handling */ #include "bacnet/rp.h" /* read property handling */ diff --git a/src/bacnet/basic/object/trendlog.c b/src/bacnet/basic/object/trendlog.c index 1633d17d..e42b33cd 100644 --- a/src/bacnet/basic/object/trendlog.c +++ b/src/bacnet/basic/object/trendlog.c @@ -40,6 +40,7 @@ #include "bacnet/basic/binding/address.h" #include "bacnet/bacdevobjpropref.h" #include "bacnet/basic/object/trendlog.h" +#include "bacnet/datetime.h" #if defined(BACFILE) #include "bacnet/basic/object/bacfile.h" /* object list dependency */ #endif @@ -138,6 +139,18 @@ unsigned Trend_Log_Instance_To_Index(uint32_t object_instance) return index; } +/** + * @brief Get the current time from the Device object + * @return current time in epoch seconds + */ +static bacnet_time_t Trend_Log_Epoch_Seconds_Now(void) +{ + BACNET_DATE_TIME bdatetime; + + Device_getCurrentDateTime(&bdatetime); + return datetime_seconds_since_epoch(&bdatetime); +} + /* * Things to do when starting up the stack for Trend Logs. * Should be called whenever we reset the device or power it up @@ -147,8 +160,9 @@ void Trend_Log_Init(void) static bool initialized = false; int iLog; int iEntry; - struct tm TempTime = {0}; - time_t tClock; + BACNET_DATE_TIME bdatetime = { 0 }; + bacnet_time_t tClock; + uint8_t month; if (!initialized) { initialized = true; @@ -171,14 +185,10 @@ void Trend_Log_Init(void) /* We will just fill the logs with some entries for testing * purposes. */ - TempTime.tm_year = 109; - TempTime.tm_mon = iLog + 1; /* Different month for each log */ - TempTime.tm_mday = 1; - TempTime.tm_hour = 0; - TempTime.tm_min = 0; - TempTime.tm_sec = 0; - tClock = mktime(&TempTime); - + /* Different month for each log */ + month = iLog + 1; + datetime_set_values(&bdatetime, 2009, month, 1, 0, 0, 0, 0); + tClock = datetime_seconds_since_epoch(&bdatetime); for (iEntry = 0; iEntry < TL_MAX_ENTRIES; iEntry++) { Logs[iLog][iEntry].tTimeStamp = tClock; Logs[iLog][iEntry].ucRecType = TL_TYPE_REAL; @@ -190,7 +200,8 @@ void Trend_Log_Init(void) } else { Logs[iLog][iEntry].ucStatus = 0; } - tClock += 900; /* advance 15 minutes */ + /* advance 15 minutes, in seconds */ + tClock += 900; } LogInfo[iLog].tLastDataTime = tClock - 900; @@ -419,7 +430,7 @@ bool Trend_Log_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) int len = 0; BACNET_APPLICATION_DATA_VALUE value; TL_LOG_INFO *CurrentLog; - BACNET_DATE start_date, stop_date; + BACNET_DATE start_date, stop_date; BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE TempSource; bool bEffectiveEnable; int log_index; @@ -588,7 +599,7 @@ bool Trend_Log_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) /* First record the current enable state of the log */ bEffectiveEnable = TL_Is_Enabled(log_index); /* Safe to copy the date now */ - CurrentLog->StartTime.date = start_date; + CurrentLog->StartTime.date = start_date; CurrentLog->StartTime.time = value.type.Time; if (datetime_wildcard_present(&CurrentLog->StartTime)) { @@ -639,15 +650,13 @@ bool Trend_Log_Write_Property(BACNET_WRITE_PROPERTY_DATA *wp_data) /* First record the current enable state of the log */ bEffectiveEnable = TL_Is_Enabled(log_index); /* Safe to copy the date now */ - CurrentLog->StopTime.date = stop_date; + CurrentLog->StopTime.date = stop_date; CurrentLog->StopTime.time = value.type.Time; if (datetime_wildcard_present(&CurrentLog->StopTime)) { /* Mark stop time as wild carded */ CurrentLog->ucTimeFlags |= TL_T_STOP_WILD; - CurrentLog->tStopTime = - 0xFFFFFFFF; /* Fixme: how do we set this to max for - time_t ? */ + CurrentLog->tStopTime = datetime_seconds_since_epoch_max(); } else { /* Clear wild card flag and set time in local format */ CurrentLog->ucTimeFlags &= ~TL_T_STOP_WILD; @@ -819,7 +828,7 @@ void TL_Insert_Status_Rec(int iLog, BACNET_LOG_STATUS eStatus, bool bState) CurrentLog = &LogInfo[iLog]; - TempRec.tTimeStamp = time(NULL); + TempRec.tTimeStamp = Trend_Log_Epoch_Seconds_Now(); TempRec.ucRecType = TL_TYPE_STATUS; TempRec.ucStatus = 0; TempRec.Datum.ucLogStatus = 0; @@ -863,7 +872,7 @@ void TL_Insert_Status_Rec(int iLog, BACNET_LOG_STATUS eStatus, bool bState) bool TL_Is_Enabled(int iLog) { TL_LOG_INFO *CurrentLog; - time_t tNow; + bacnet_time_t tNow; bool bStatus; bStatus = true; @@ -883,7 +892,7 @@ bool TL_Is_Enabled(int iLog) bStatus = false; } else if (CurrentLog->ucTimeFlags != (TL_T_START_WILD | TL_T_STOP_WILD)) { /* enabled and either 1 wild card or none */ - tNow = time(NULL); + tNow = Trend_Log_Epoch_Seconds_Now(); #if 0 printf("\nFlags - %u, Current - %u, Start - %u, Stop - %u\n", (unsigned int) CurrentLog->ucTimeFlags, (unsigned int) Now, @@ -921,59 +930,18 @@ bool TL_Is_Enabled(int iLog) * Convert a BACnet time into a local time in seconds since the local epoch * *****************************************************************************/ -time_t TL_BAC_Time_To_Local(BACNET_DATE_TIME *SourceTime) +bacnet_time_t TL_BAC_Time_To_Local(BACNET_DATE_TIME *bdatetime) { - struct tm LocalTime = {0}; - int iTemp; - - LocalTime.tm_year = - SourceTime->date.year - 1900; /* We store BACnet year in full format */ - /* Some clients send a date of all 0s to indicate start of epoch - * even though this is not a valid date. Pick this up here and - * correct the day and month for the local time functions. - */ - iTemp = - SourceTime->date.year + SourceTime->date.month + SourceTime->date.day; - if (iTemp == 1900) { - LocalTime.tm_mon = 0; - LocalTime.tm_mday = 1; - } else { - LocalTime.tm_mon = SourceTime->date.month - 1; - LocalTime.tm_mday = SourceTime->date.day; - } - - LocalTime.tm_hour = SourceTime->time.hour; - LocalTime.tm_min = SourceTime->time.min; - LocalTime.tm_sec = SourceTime->time.sec; - - return (mktime(&LocalTime)); + return datetime_seconds_since_epoch(bdatetime); } /***************************************************************************** * Convert a local time in seconds since the local epoch into a BACnet time * *****************************************************************************/ -void TL_Local_Time_To_BAC(BACNET_DATE_TIME *DestTime, time_t SourceTime) +void TL_Local_Time_To_BAC(BACNET_DATE_TIME *bdatetime, bacnet_time_t seconds) { - struct tm *TempTime; - - TempTime = localtime(&SourceTime); - - DestTime->date.year = (uint16_t)(TempTime->tm_year + 1900); - DestTime->date.month = (uint8_t)(TempTime->tm_mon + 1); - DestTime->date.day = (uint8_t)TempTime->tm_mday; - /* BACnet is 1 to 7 = Monday to Sunday - * Windows is days from Sunday 0 - 6 so we - * have to adjust */ - if (TempTime->tm_wday == 0) { - DestTime->date.wday = 7; - } else { - DestTime->date.wday = (uint8_t)TempTime->tm_wday; - } - DestTime->time.hour = (uint8_t)TempTime->tm_hour; - DestTime->time.min = (uint8_t)TempTime->tm_min; - DestTime->time.sec = (uint8_t)TempTime->tm_sec; - DestTime->time.hundredths = 0; + datetime_since_epoch_seconds(bdatetime, seconds); } /**************************************************************************** @@ -1304,7 +1272,7 @@ int TL_encode_by_time(uint8_t *apdu, BACNET_READ_RANGE_DATA *pRequest) uint32_t uiLast = 0; /* Entry number we finished encoding on */ uint32_t uiRemaining = 0; /* Amount of unused space in packet */ uint32_t uiFirstSeq = 0; /* Sequence number for 1st record in log */ - time_t tRefTime = 0; /* The time from the request in local format */ + bacnet_time_t tRefTime = 0; /* The time from the request in local format */ /* See how much space we have */ uiRemaining = MAX_APDU - pRequest->Overhead; @@ -1611,7 +1579,7 @@ static void TL_fetch_property(int iLog) /* Record the current time in the log entry and also in the info block * for the log so we can figure out when the next reading is due */ - TempRec.tTimeStamp = time(NULL); + TempRec.tTimeStamp = Trend_Log_Epoch_Seconds_Now(); CurrentLog->tLastDataTime = TempRec.tTimeStamp; TempRec.ucStatus = 0; @@ -1722,11 +1690,11 @@ void trend_log_timer(uint16_t uSeconds) { TL_LOG_INFO *CurrentLog = NULL; int iCount = 0; - time_t tNow = 0; + bacnet_time_t tNow = 0; (void)uSeconds; /* use OS to get the current time */ - tNow = time(NULL); + tNow = Trend_Log_Epoch_Seconds_Now(); for (iCount = 0; iCount < MAX_TREND_LOGS; iCount++) { CurrentLog = &LogInfo[iCount]; if (TL_Is_Enabled(iCount)) { diff --git a/src/bacnet/basic/object/trendlog.h b/src/bacnet/basic/object/trendlog.h index 2d99e7f9..a78ee904 100644 --- a/src/bacnet/basic/object/trendlog.h +++ b/src/bacnet/basic/object/trendlog.h @@ -27,10 +27,10 @@ #include #include -#include /* for time_t */ #include "bacnet/bacnet_stack_exports.h" #include "bacnet/bacdef.h" #include "bacnet/cov.h" +#include "bacnet/datetime.h" #include "bacnet/rp.h" #include "bacnet/wp.h" @@ -62,7 +62,7 @@ extern "C" { */ typedef struct tl_data_record { - time_t tTimeStamp; /* When the event occurred */ + bacnet_time_t tTimeStamp; /* When the event occurred */ uint8_t ucRecType; /* What type of Event */ uint8_t ucStatus; /* Optional Status for read value in b0-b2, b7 = 1 if status is used */ union { @@ -88,9 +88,9 @@ extern "C" { typedef struct tl_log_info { bool bEnable; /* Trend log is active when this is true */ BACNET_DATE_TIME StartTime; /* BACnet format start time */ - time_t tStartTime; /* Local time working copy of start time */ + bacnet_time_t tStartTime; /* Local time working copy of start time */ BACNET_DATE_TIME StopTime; /* BACnet format stop time */ - time_t tStopTime; /* Local time working copy of stop time */ + bacnet_time_t tStopTime; /* Local time working copy of stop time */ uint8_t ucTimeFlags; /* Shorthand info on times */ BACNET_DEVICE_OBJECT_PROPERTY_REFERENCE Source; /* Where the data comes from */ uint32_t ulLogInterval; /* Time between entries in seconds */ @@ -102,7 +102,7 @@ extern "C" { uint32_t ulIntervalOffset; /* Offset from start of period for taking reading in seconds */ bool bTrigger; /* Set to 1 to cause a reading to be taken */ int iIndex; /* Current insertion point */ - time_t tLastDataTime; + bacnet_time_t tLastDataTime; } TL_LOG_INFO; /* @@ -173,13 +173,13 @@ extern "C" { int iLog); BACNET_STACK_EXPORT - time_t TL_BAC_Time_To_Local( + bacnet_time_t TL_BAC_Time_To_Local( BACNET_DATE_TIME * SourceTime); BACNET_STACK_EXPORT void TL_Local_Time_To_BAC( BACNET_DATE_TIME * DestTime, - time_t SourceTime); + bacnet_time_t SourceTime); BACNET_STACK_EXPORT int TL_encode_entry( diff --git a/src/bacnet/datalink/bvlc6.h b/src/bacnet/datalink/bvlc6.h index 67e88e73..3a22d80d 100644 --- a/src/bacnet/datalink/bvlc6.h +++ b/src/bacnet/datalink/bvlc6.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "bacnet/bacnet_stack_exports.h" #include "bacnet/bacdef.h" #include "bacnet/npdu.h" diff --git a/src/bacnet/datetime.c b/src/bacnet/datetime.c index 2e317fd6..70642cfa 100644 --- a/src/bacnet/datetime.c +++ b/src/bacnet/datetime.c @@ -679,15 +679,14 @@ void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes) datetime_days_since_epoch_into_date(bdatetime_days, &bdatetime->date); } -#ifdef UINT64_MAX /** - * @brief Calculates the number of seconds since epoch + * @brief Calculates the number of seconds since epoch from datetime * @param bdatetime [in] the starting date and time - * @return seconds since midnight + * @return seconds since epoch */ -uint64_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime) +bacnet_time_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime) { - uint64_t seconds = 0; + bacnet_time_t seconds = 0; uint32_t days = 0; if (bdatetime) { @@ -699,15 +698,14 @@ uint64_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime) return seconds; } -#endif -#ifdef UINT64_MAX /** - * @brief Calculates the number of seconds since epoch - * @param bdatetime [in] the starting date and time - * @return seconds since midnight + * @brief Calculates the datetime from number of seconds since epoch + * @param bdatetime [out] the starting date and time + * @param seconds since epoch */ -void datetime_since_epoch_seconds(BACNET_DATE_TIME *bdatetime, uint64_t seconds) +void datetime_since_epoch_seconds(BACNET_DATE_TIME *bdatetime, + bacnet_time_t seconds) { uint32_t seconds_after_midnight = 0; uint32_t days = 0; @@ -722,7 +720,20 @@ void datetime_since_epoch_seconds(BACNET_DATE_TIME *bdatetime, uint64_t seconds) datetime_days_since_epoch_into_date(days, &bdatetime->date); } } + +/** + * @brief Calculates the number of seconds since epoch + * @param bdatetime [in] the starting date and time + * @return maximum number of seconds since epoch + */ +bacnet_time_t datetime_seconds_since_epoch_max(void) +{ +#ifdef UINT64_MAX + return UINT64_MAX; +#else + return UINT32_MAX; #endif +} /* Returns true if year is a wildcard */ bool datetime_wildcard_year(BACNET_DATE *bdate) diff --git a/src/bacnet/datetime.h b/src/bacnet/datetime.h index ab2b053f..7f8c14cb 100644 --- a/src/bacnet/datetime.h +++ b/src/bacnet/datetime.h @@ -78,6 +78,12 @@ typedef struct BACnet_Weeknday { uint8_t dayofweek; /* 1=Monday-7=Sunday, FF=any */ } BACNET_WEEKNDAY; +#ifdef UINT64_MAX +typedef uint64_t bacnet_time_t; +#else +typedef uint32_t bacnet_time_t; +#endif + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -189,10 +195,12 @@ BACNET_STACK_EXPORT void datetime_add_minutes(BACNET_DATE_TIME *bdatetime, int32_t minutes); BACNET_STACK_EXPORT -uint64_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime); +bacnet_time_t datetime_seconds_since_epoch(BACNET_DATE_TIME *bdatetime); BACNET_STACK_EXPORT void datetime_since_epoch_seconds( - BACNET_DATE_TIME *bdatetime, uint64_t seconds); + BACNET_DATE_TIME *bdatetime, bacnet_time_t seconds); +BACNET_STACK_EXPORT +bacnet_time_t datetime_seconds_since_epoch_max(void); /* date and time wildcards */ BACNET_STACK_EXPORT