2026-10-15 21:01:14 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
// The stopwatch of the dynamic pages, started and stopped in the web UI and Home Assistant.
|
2026-10-20 22:22:32 +02:00
|
|
|
// Times are the real time in ms since 1970 (UTC), so it counts from a date, keeps counting
|
|
|
|
|
// while the display is off or restarting (system/stopwatch_store keeps it in NVS) and can
|
|
|
|
|
// run for years. Pure logic, tested in test/test_esp32.
|
2026-10-15 21:01:14 +02:00
|
|
|
class Stopwatch
|
|
|
|
|
{
|
|
|
|
|
public:
|
2026-10-20 22:22:32 +02:00
|
|
|
// The state as it is stored
|
|
|
|
|
struct State
|
2026-10-15 21:01:14 +02:00
|
|
|
{
|
2026-10-20 22:22:32 +02:00
|
|
|
bool running = false;
|
|
|
|
|
int64_t started = 0; // when it was started (again)
|
|
|
|
|
int64_t before = 0; // ms counted before the last start
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void start(int64_t now)
|
|
|
|
|
{
|
|
|
|
|
if (_state.running)
|
2026-10-15 21:01:14 +02:00
|
|
|
return;
|
2026-10-20 22:22:32 +02:00
|
|
|
_state.running = true;
|
|
|
|
|
_state.started = now;
|
2026-10-15 21:01:14 +02:00
|
|
|
}
|
2026-10-20 22:22:32 +02:00
|
|
|
void stop(int64_t now)
|
2026-10-15 21:01:14 +02:00
|
|
|
{
|
2026-10-20 22:22:32 +02:00
|
|
|
if (!_state.running)
|
2026-10-15 21:01:14 +02:00
|
|
|
return;
|
2026-10-20 22:22:32 +02:00
|
|
|
_state.before = elapsed(now);
|
|
|
|
|
_state.running = false;
|
2026-10-15 21:01:14 +02:00
|
|
|
}
|
|
|
|
|
// Back to 0, stopped
|
2026-10-20 22:22:32 +02:00
|
|
|
void reset() { _state = State(); }
|
|
|
|
|
// Counts from this moment (in the past) on, running; false (nothing changed) when it is
|
|
|
|
|
// in the future
|
|
|
|
|
bool setStart(int64_t start, int64_t now)
|
2026-10-15 21:01:14 +02:00
|
|
|
{
|
2026-10-20 22:22:32 +02:00
|
|
|
if (start > now)
|
|
|
|
|
return false;
|
|
|
|
|
_state.running = true;
|
|
|
|
|
_state.started = start;
|
|
|
|
|
_state.before = 0;
|
|
|
|
|
return true;
|
2026-10-15 21:01:14 +02:00
|
|
|
}
|
2026-10-20 22:22:32 +02:00
|
|
|
bool running() const { return _state.running; }
|
|
|
|
|
// Never negative (the clock set back)
|
|
|
|
|
uint64_t elapsed(int64_t now) const
|
|
|
|
|
{
|
|
|
|
|
int64_t ms = _state.before;
|
|
|
|
|
if (_state.running && now > _state.started)
|
|
|
|
|
ms += now - _state.started;
|
|
|
|
|
return ms > 0 ? (uint64_t)ms : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const State &state() const { return _state; }
|
|
|
|
|
void restore(const State &state) { _state = state; }
|
2026-10-15 21:01:14 +02:00
|
|
|
|
|
|
|
|
private:
|
2026-10-20 22:22:32 +02:00
|
|
|
State _state;
|
2026-10-15 21:01:14 +02:00
|
|
|
};
|