TinyCTS
Bluetooth Current Time Service client and server for Arduino
Loading...
Searching...
No Matches
TinyCTSTimeSource.h
Go to the documentation of this file.
1
7
8#pragma once
9#include <cstdint>
10
11// (the Renesas core of the Uno R4 has the header, but no usable timeval)
12// the system clock: gettimeofday() on the boards that have it (the Renesas core
13// of the Uno R4 has the header, but no usable timeval), std::chrono on the desktop
14#if !defined(ARDUINO)
15#define TINY_CTS_HAS_SYSTEM_TIME 1
16#include <chrono>
17#if !defined(_WIN32)
18#include <sys/time.h>
19#define TINY_CTS_HAS_SETTIMEOFDAY 1
20#endif
21#elif defined(__has_include) && !defined(ARDUINO_ARCH_RENESAS) && \
22 !defined(ARDUINO_ARCH_RENESAS_UNO) && !defined(ARDUINO_ARCH_RENESAS_PORTENTA)
23#if __has_include(<sys/time.h>)
24#include <sys/time.h>
25#define TINY_CTS_HAS_SYSTEM_TIME 1
26#define TINY_CTS_HAS_SETTIMEOFDAY 1
27#endif
28#endif
29
30// millis(): from Arduino.h, or the steady clock where there is no Arduino API
31// (the tests and the command line tool); override with your own macro if needed
32#ifndef TINY_CTS_MILLIS
33#if defined(ARDUINO)
34#define TINY_CTS_MILLIS() (::millis())
35#else
36#include <chrono>
37#define TINY_CTS_MILLIS() \
38 (static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::milliseconds>( \
39 std::chrono::steady_clock::now().time_since_epoch()) \
40 .count()))
41#endif
42#endif
43
44namespace tiny_cts {
45
52 public:
53 virtual ~TinyCTSTimeSource() = default;
54
60 virtual uint64_t getTimeMs() = 0;
61
67 virtual bool setTimeMs(uint64_t unixMs) {
68 (void)unixMs;
69 return false;
70 }
71};
72
80 public:
81 void setTime(uint32_t unixSeconds, uint16_t milliseconds = 0) {
82 setTimeMs(unixSeconds * 1000ULL + milliseconds);
83 }
84
85 bool setTimeMs(uint64_t unixMs) override {
86 _timeMs = unixMs;
87 _lastMillis = TINY_CTS_MILLIS();
88 return true;
89 }
90
91 void clear() { _timeMs = 0; }
92 bool isSet() const { return _timeMs != 0; }
93
94 uint64_t getTimeMs() override {
95 if (_timeMs == 0) return 0;
96 uint32_t now = TINY_CTS_MILLIS();
97 _timeMs += static_cast<uint32_t>(now - _lastMillis);
98 _lastMillis = now;
99 return _timeMs;
100 }
101
102 protected:
103 uint64_t _timeMs = 0;
104 uint32_t _lastMillis = 0;
105};
106
107#ifdef TINY_CTS_HAS_SYSTEM_TIME
114class TinyCTSSystemSource : public TinyCTSTimeSource {
115 public:
116 explicit TinyCTSSystemSource(uint32_t minValidSeconds = 1700000000UL)
117 : _minValid(minValidSeconds) {}
118
119 uint64_t getTimeMs() override {
120#if defined(ARDUINO)
121 timeval tv;
122 if (gettimeofday(&tv, nullptr) != 0) return 0;
123 uint64_t sec = static_cast<uint64_t>(tv.tv_sec);
124 uint64_t ms = sec * 1000ULL + tv.tv_usec / 1000;
125#else
126 uint64_t ms = static_cast<uint64_t>(
127 std::chrono::duration_cast<std::chrono::milliseconds>(
128 std::chrono::system_clock::now().time_since_epoch())
129 .count());
130 uint64_t sec = ms / 1000;
131#endif
132 return sec < _minValid ? 0 : ms;
133 }
134
136 bool setTimeMs(uint64_t unixMs) override {
137#if defined(TINY_CTS_HAS_SETTIMEOFDAY)
138 timeval tv;
139 tv.tv_sec = static_cast<time_t>(unixMs / 1000);
140 tv.tv_usec = static_cast<suseconds_t>(unixMs % 1000 * 1000);
141 return settimeofday(&tv, nullptr) == 0;
142#else
143 (void)unixMs;
144 return false;
145#endif
146 }
147
148 protected:
149 uint32_t _minValid;
150};
151#endif
152
162template <typename T>
163class TinyCTSSourceAdapter : public TinyCTSTimeSource {
164 public:
165 explicit TinyCTSSourceAdapter(T& source) : _source(source) {}
166 uint64_t getTimeMs() override { return _source.getTimeMs(); }
167
168 protected:
169 T& _source;
170};
171
172} // namespace tiny_cts
A software clock: you set the UTC time (from an RTC, a GPS, ...) and it keeps counting with millis()....
Definition TinyCTSTimeSource.h:79
bool setTimeMs(uint64_t unixMs) override
Set the current UTC time, e.g. when a client writes the Current Time characteristic....
Definition TinyCTSTimeSource.h:85
uint64_t getTimeMs() override
The current UTC time in milliseconds since 1970-01-01. It must not block.
Definition TinyCTSTimeSource.h:94
uint64_t getTimeMs() override
The current UTC time in milliseconds since 1970-01-01. It must not block.
Definition TinyCTSTimeSource.h:166
bool setTimeMs(uint64_t unixMs) override
Definition TinyCTSTimeSource.h:136
uint64_t getTimeMs() override
The current UTC time in milliseconds since 1970-01-01. It must not block.
Definition TinyCTSTimeSource.h:119
Abstract base class of the time sources: an object that knows the current UTC time.
Definition TinyCTSTimeSource.h:51
virtual bool setTimeMs(uint64_t unixMs)
Set the current UTC time, e.g. when a client writes the Current Time characteristic....
Definition TinyCTSTimeSource.h:67
virtual uint64_t getTimeMs()=0
The current UTC time in milliseconds since 1970-01-01. It must not block.