/* SPDX-License-Identifier: MIT Copyright (c) 2023 John Watts and the LuminaSensum contributors */ #include "Clock.h" #include "mbed.h" using namespace std::chrono; Mutex clock_lock; microseconds boot_start; struct timeval microseconds_to_timeval(microseconds val) { uint64_t microsecs = val.count(); struct timeval time; time.tv_sec = microsecs / 1000000; time.tv_usec = microsecs % 1000000; return time; } microseconds timeval_to_microseconds(struct timeval val) { microseconds time(0); time += seconds(val.tv_sec); time += microseconds(val.tv_usec); return time; } void clock_setup(void) { kernel_timepoint kernel_time = Kernel::Clock::now(); seconds real_time = seconds(time(NULL)); microseconds uptime = kernel_time.time_since_epoch(); clock_lock.lock(); boot_start = real_time - uptime; clock_lock.unlock(); } microseconds clock_time(kernel_timepoint kernel_time) { clock_lock.lock(); microseconds curr_offset = boot_start; clock_lock.unlock(); microseconds uptime = kernel_time.time_since_epoch(); return boot_start + uptime; } kernel_timepoint kernel_time(microseconds clock_time) { clock_lock.lock(); microseconds curr_offset = boot_start; clock_lock.unlock(); microseconds boot_offset = clock_time - curr_offset; milliseconds offset_ms = duration_cast<milliseconds>(boot_offset); return kernel_timepoint(offset_ms); } std::chrono::microseconds clock_now(void) { return clock_time(Kernel::Clock::now()); } SNTPError clock_sync(NetworkInterface &net) { struct timeval time; SNTPError err; err = sntp(net, "time.google.com", 123, &time); if (err != SNTPSuccess) { return err; } kernel_timepoint kernel_time = Kernel::Clock::now(); microseconds real_time = timeval_to_microseconds(time); microseconds uptime = kernel_time.time_since_epoch(); clock_lock.lock(); boot_start = real_time - uptime; clock_lock.unlock(); set_time(time.tv_sec); return SNTPSuccess; } const char *clock_timestring(struct timeval time, const char *format) { struct tm *local_time = localtime(&time.tv_sec); static char buffer[64]; size_t buffer_size = sizeof(buffer); size_t buffer_written; buffer_written = strftime(buffer, buffer_size, format, local_time); if (buffer_written == 0) { // It overflowed, so return something useful return "(time overflow)"; } else { return buffer; } } const char *clock_iso8601string(void) { microseconds time = clock_now(); struct timeval val = microseconds_to_timeval(time); const char *timestring = clock_timestring(val, "%Y-%m-%dT%H:%M:%S"); static char buffer[128]; int buffer_size = sizeof(buffer); int written; written = snprintf( buffer, buffer_size, "%s.%05li", timestring, val.tv_usec); if (written >= buffer_size) { // It overflowed, so return something useful return "(iso8601 overflow)"; } else { return buffer; } }