|
9 | 9 | #include <stdint.h> |
10 | 10 | #include <stdio.h> |
11 | 11 | #include <stdlib.h> |
12 | | -#include <time.h> |
13 | | -#include <sys/time.h> |
14 | 12 | /* BACnet Stack defines - first */ |
15 | 13 | #include "bacnet/bacdef.h" |
| 14 | +#include "bacnet/basic/sys/mstimer.h" |
16 | 15 | /* BACnet Stack API */ |
17 | 16 | #include "bacnet/datetime.h" |
18 | 17 |
|
| 18 | +/* local time */ |
| 19 | +static BACNET_DATE_TIME BACnet_Date_Time; |
| 20 | +static struct mstimer Date_Timer; |
19 | 21 |
|
20 | | -/* HACK: |
21 | | - * - Zephyr does not declare timezone in any header file. |
22 | | - * - The gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi/lib/thumb/v7e-m/ |
23 | | - * libc_nano.a 'time' symbol does not resolve '_gettimeofday' |
24 | | - * |
25 | | - * TODO: figure out how to link in the real time() and timezone; |
| 22 | +/** |
| 23 | + * @brief Synchronize the local time from the millisecond timer |
26 | 24 | */ |
27 | | -long timezone; |
28 | | - |
29 | | -time_t time(time_t *tloc) |
| 25 | +void datetime_sync(void) |
30 | 26 | { |
31 | | - time_t time = { 0 }; |
| 27 | + bacnet_time_t seconds, elapsed_seconds; |
| 28 | + unsigned long milliseconds; |
32 | 29 |
|
33 | | - return time; |
| 30 | + milliseconds = mstimer_elapsed(&Date_Timer); |
| 31 | + elapsed_seconds = milliseconds/1000UL; |
| 32 | + if (elapsed_seconds) { |
| 33 | + mstimer_restart(&Date_Timer); |
| 34 | + seconds = datetime_seconds_since_epoch(&BACnet_Date_Time); |
| 35 | + seconds += elapsed_seconds; |
| 36 | + datetime_since_epoch_seconds(&BACnet_Date_Time, seconds); |
| 37 | + /* generate a hundredths value */ |
| 38 | + milliseconds -= (elapsed_seconds * 1000UL); |
| 39 | + BACnet_Date_Time.time.hundredths = milliseconds / 10; |
| 40 | + } |
34 | 41 | } |
35 | 42 |
|
36 | 43 | /** |
37 | | - * @brief Get the date, time, timezone, and UTC offset from system |
38 | | - * @param utc_time - the BACnet Date and Time structure to hold UTC time |
39 | | - * @param local_time - the BACnet Date and Time structure to hold local time |
40 | | - * @param utc_offset_minutes - number of minutes offset from UTC |
41 | | - * For example, -6*60 represents 6.00 hours behind UTC/GMT |
42 | | - * @param true if DST is enabled and active |
43 | | - * @return true if local time was retrieved |
| 44 | + * @brief Get the local date and time |
| 45 | + * @param bdate [out] The date to get |
| 46 | + * @param btime [out] The time to get |
| 47 | + * @param utc_offset_minutes [out] The UTC offset in minutes |
| 48 | + * @param dst_active [out] The DST flag |
| 49 | + * @return true if successful, false on error |
44 | 50 | */ |
45 | 51 | bool datetime_local( |
46 | | - BACNET_DATE * bdate, |
47 | | - BACNET_TIME * btime, |
48 | | - int16_t * utc_offset_minutes, |
49 | | - bool * dst_active) |
| 52 | + BACNET_DATE *bdate, |
| 53 | + BACNET_TIME *btime, |
| 54 | + int16_t *utc_offset_minutes, |
| 55 | + bool *dst_active) |
50 | 56 | { |
51 | | - bool status = false; |
52 | | - struct tm tblock_st = { 0 }; |
53 | | - struct tm *tblock = &tblock_st; |
54 | | - struct timeval tv; |
55 | | - |
56 | | - if (gettimeofday(&tv, NULL) == 0) |
57 | | - { |
58 | | - tblock = (struct tm *)localtime((const time_t *)&tv.tv_sec); |
| 57 | + datetime_sync(); |
| 58 | + if (bdate) { |
| 59 | + datetime_copy_date(bdate, &BACnet_Date_Time.date); |
59 | 60 | } |
60 | | - if (tblock) { |
61 | | - status = true; |
62 | | - /** struct tm |
63 | | - * int tm_sec Seconds [0,60]. |
64 | | - * int tm_min Minutes [0,59]. |
65 | | - * int tm_hour Hour [0,23]. |
66 | | - * int tm_mday Day of month [1,31]. |
67 | | - * int tm_mon Month of year [0,11]. |
68 | | - * int tm_year Years since 1900. |
69 | | - * int tm_wday Day of week [0,6] (Sunday =0). |
70 | | - * int tm_yday Day of year [0,365]. |
71 | | - * int tm_isdst Daylight Savings flag. |
72 | | - */ |
73 | | - datetime_set_date(bdate, (uint16_t)tblock->tm_year + 1900, |
74 | | - (uint8_t)tblock->tm_mon + 1, |
75 | | - (uint8_t)tblock->tm_mday); |
76 | | - datetime_set_time(btime, (uint8_t)tblock->tm_hour, |
77 | | - (uint8_t)tblock->tm_min, (uint8_t)tblock->tm_sec, |
78 | | - (uint8_t)(tv.tv_usec / 10000)); |
79 | | - if (dst_active) { |
80 | | - /* The value of tm_isdst is: |
81 | | - - positive if Daylight Saving Time is in effect, |
82 | | - - 0 if Daylight Saving Time is not in effect, and |
83 | | - - negative if the information is not available. */ |
84 | | - if (tblock->tm_isdst > 0) { |
85 | | - *dst_active = true; |
86 | | - } else { |
87 | | - *dst_active = false; |
88 | | - } |
89 | | - } |
90 | | - /* note: timezone is declared in <time.h> stdlib. */ |
91 | | - if (utc_offset_minutes) { |
92 | | - /* timezone is set to the difference, in seconds, |
93 | | - between Coordinated Universal Time (UTC) and |
94 | | - local standard time */ |
95 | | - *utc_offset_minutes = timezone / 60; |
96 | | - } |
| 61 | + if (btime) { |
| 62 | + datetime_copy_time(btime, &BACnet_Date_Time.time); |
97 | 63 | } |
| 64 | + (void)utc_offset_minutes; |
| 65 | + (void)dst_active; |
| 66 | + |
| 67 | + return true; |
| 68 | +} |
98 | 69 |
|
99 | | - return status; |
| 70 | +/** |
| 71 | + * @brief Set the local date and time from a BACnet TimeSynchronization request |
| 72 | + * @param bdate [in] The date to set |
| 73 | + * @param btime [in] The time to set |
| 74 | + * @param utc [in] true if originating from an UTCTimeSynchronization request |
| 75 | + */ |
| 76 | +void datetime_timesync(BACNET_DATE *bdate, BACNET_TIME *btime, bool utc) |
| 77 | +{ |
| 78 | + if (bdate) { |
| 79 | + datetime_copy_date(&BACnet_Date_Time.date, bdate); |
| 80 | + } |
| 81 | + if (btime) { |
| 82 | + datetime_copy_time(&BACnet_Date_Time.time, btime); |
| 83 | + } |
| 84 | + mstimer_restart(&Date_Timer); |
| 85 | + (void)utc; |
100 | 86 | } |
101 | 87 |
|
102 | 88 | /** |
103 | | - * initialize the date time |
| 89 | + * @brief Initialize the local date and time timer |
104 | 90 | */ |
105 | 91 | void datetime_init(void) |
106 | 92 | { |
107 | | - /* nothing to do */ |
| 93 | + mstimer_set(&Date_Timer, 0); |
108 | 94 | } |
0 commit comments