64 const uint64_t offset = (
static_cast<uint64_t
>(random) * 2 * jitter) / UINT32_MAX;
65 return static_cast<uint32_t
>(interval_ms - jitter + offset);
73 void set_interval(
const std::string &device_id, uint32_t interval_ms, uint32_t now, uint32_t random);
75 [[nodiscard]] uint32_t
get_interval(
const std::string &device_id)
const;
79 [[nodiscard]]
bool has_due(uint32_t now)
const;
85 [[nodiscard]] std::optional<std::string>
pop_due_device(uint32_t now, uint32_t random);
88 void defer(
const std::string &device_id, uint32_t delay_ms, uint32_t now);
92 void restart_interval(
const std::string &device_id, uint32_t now, uint32_t random);
106 [[nodiscard]]
bool retry_armed(
const std::string &device_id)
const;
113 [[nodiscard]] uint8_t
get_failures(
const std::string &device_id)
const;
115 [[nodiscard]] uint32_t
get_next_poll(
const std::string &device_id)
const;
120 uint32_t interval_ms{0};
121 uint32_t next_poll{0};
123 bool error_reported{
false};
125 bool polling_retry{
false};
128 std::map<std::string, Entry> entries_;
Per-device periodic poll schedule, miss retry and miss counter for one poll kind.
uint32_t get_next_poll(const std::string &device_id) const
Absolute millis() time of the device's next poll (0 for an unscheduled device).
void defer(const std::string &device_id, uint32_t delay_ms, uint32_t now)
Pull the device's next poll forward to delay_ms after now. Never pushes it later.
uint32_t get_interval(const std::string &device_id) const
Return the configured interval (0 when the device is not scheduled).
std::optional< std::string > pop_due_device(uint32_t now, uint32_t random)
Return one device whose poll is due and immediately schedule its next poll at periodic_poll_jittered_...
void restart_interval(const std::string &device_id, uint32_t now, uint32_t random)
The device has just given what the poll asks for without being polled: schedule its next poll periodi...
void on_poll_succeeded(const std::string &device_id)
Clear the unanswered-poll count.
bool on_poll_failed(const std::string &device_id)
Count one failed poll (saturating), with no retry: for a poll the device answered with something that...
bool first_error_reply(const std::string &device_id)
True the first time it is called for a device that answered the poll's request with an error reply,...
uint8_t get_failures(const std::string &device_id) const
Consecutive failed polls (0 for an unscheduled device).
bool has_due(uint32_t now) const
True when any device's poll is due at now.
bool retry_armed(const std::string &device_id) const
True while a retry armed by on_poll_unanswered() has not been popped yet.
bool on_poll_unanswered(const std::string &device_id, uint32_t now)
Handle a poll the device left unanswered.
void set_interval(const std::string &device_id, uint32_t interval_ms, uint32_t now, uint32_t random)
Set the poll interval and schedule the first poll at periodic_poll_first_delay_ms(random) after now.
static constexpr uint32_t PERIODIC_POLL_MOVING_RETRY_MS
Delay before asking again when the device is moving.
static constexpr uint32_t PERIODIC_POLL_MISS_RETRY_MS
Delay before asking once more after a poll the device left unanswered (silence, or a challenge with n...
static constexpr uint32_t PERIODIC_POLL_INITIAL_SPREAD_MS
Width of the random window added to PERIODIC_POLL_INITIAL_DELAY_MS, so devices do not start in step.
static constexpr uint32_t PERIODIC_POLL_JITTER_PERCENT
Per-poll offset, as a percentage of the interval, applied symmetrically around it.
uint32_t periodic_poll_jittered_interval_ms(uint32_t interval_ms, uint32_t random)
One poll interval moved by a uniform offset of up to PERIODIC_POLL_JITTER_PERCENT either way.
static constexpr uint8_t PERIODIC_POLL_MAX_TRIES
Tries per poll.
static constexpr uint32_t PERIODIC_POLL_INITIAL_DELAY_MS
Earliest first poll after boot.
static constexpr uint8_t PERIODIC_POLL_FAILURES_BEFORE_UNKNOWN
Consecutive unanswered polls after which the last reading is no longer usable.
uint32_t periodic_poll_first_delay_ms(uint32_t random)
Delay of a device's first poll after its interval is set.