Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
status_poll_policy.cpp
Go to the documentation of this file.
1/// @file status_poll_policy.cpp
2/// @brief StatusPollPolicy implementation.
3/// @ingroup hioc_hub
4
6
7namespace esphome {
8namespace home_io_control {
9
10void StatusPollPolicy::set_interval(const std::string &device_id, uint32_t interval_ms) {
11 tracking_[device_id].interval_ms = interval_ms;
12}
13
14uint32_t StatusPollPolicy::get_interval(const std::string &device_id) const {
15 auto it = tracking_.find(device_id);
16 return (it != tracking_.end()) ? it->second.interval_ms : 0;
17}
18
19void StatusPollPolicy::begin_tracking(const std::string &device_id, uint32_t initial_delay_ms, uint32_t now) {
20 PollTracking &t = tracking_[device_id];
22 t.next_update = (initial_delay_ms == 0) ? 0 : (now + initial_delay_ms);
25}
26
27void StatusPollPolicy::clear(const std::string &device_id) {
28 auto it = tracking_.find(device_id);
29 if (it == tracking_.end())
30 return;
31 PollTracking &t = it->second;
32 t.next_update = 0;
33 t.poll_deadline = 0;
36 // interval_ms is configuration — NOT cleared; remains set for future tracking cycles.
37}
38
39void StatusPollPolicy::set_next_update(const std::string &device_id, uint32_t abs_time) {
40 tracking_[device_id].next_update = abs_time;
41}
42
43uint32_t StatusPollPolicy::get_next_update(const std::string &device_id) const {
44 auto it = tracking_.find(device_id);
45 return (it != tracking_.end()) ? it->second.next_update : 0;
46}
47
48uint32_t StatusPollPolicy::get_poll_deadline(const std::string &device_id) const {
49 auto it = tracking_.find(device_id);
50 return (it != tracking_.end()) ? it->second.poll_deadline : 0;
51}
52
53bool StatusPollPolicy::is_tracking_active(const std::string &device_id, uint32_t now) const {
54 auto it = tracking_.find(device_id);
55 if (it == tracking_.end())
56 return false;
57 const PollTracking &t = it->second;
58 return t.poll_deadline != 0 && now <= t.poll_deadline;
59}
60
61uint32_t StatusPollPolicy::on_exchange_failed(const std::string &device_id, bool auth_like, uint32_t now) {
62 auto it = tracking_.find(device_id);
63 if (it == tracking_.end())
64 return 0;
65 PollTracking &t = it->second;
66
67 uint32_t backoff_ms;
68 if (auth_like) {
70 if (t.auth_poll_failures < UINT8_MAX)
72 backoff_ms = retry_delay_ms(t.auth_poll_failures, true);
73 } else {
75 if (t.status_poll_failures < UINT8_MAX)
77 backoff_ms = retry_delay_ms(t.status_poll_failures, false);
78 }
79
80 if (is_tracking_active(device_id, now) && now + backoff_ms <= t.poll_deadline) {
81 t.next_update = now + backoff_ms;
82 return backoff_ms;
83 }
84
85 clear(device_id);
86 return 0;
87}
88
89void StatusPollPolicy::clear_failure_streaks(const std::string &device_id) {
90 auto it = tracking_.find(device_id);
91 if (it == tracking_.end())
92 return;
93 it->second.status_poll_failures = 0;
94 it->second.auth_poll_failures = 0;
95}
96
97uint8_t StatusPollPolicy::get_status_poll_failures(const std::string &device_id) const {
98 auto it = tracking_.find(device_id);
99 return (it != tracking_.end()) ? it->second.status_poll_failures : 0;
100}
101
102uint8_t StatusPollPolicy::get_auth_poll_failures(const std::string &device_id) const {
103 auto it = tracking_.find(device_id);
104 return (it != tracking_.end()) ? it->second.auth_poll_failures : 0;
105}
106
107std::optional<std::string> StatusPollPolicy::pop_due_device(uint32_t now) {
108 for (auto &pair : tracking_) {
109 PollTracking &t = pair.second;
110 if (t.next_update == 0 || now <= t.next_update)
111 continue;
112 if (!is_tracking_active(pair.first, now)) {
113 clear(pair.first);
114 continue;
115 }
116 t.next_update = 0;
117 return pair.first;
118 }
119 return std::nullopt;
120}
121
122uint32_t StatusPollPolicy::retry_delay_ms(uint8_t consecutive_failures, bool auth_like) {
123 if (auth_like) {
124 if (consecutive_failures <= 1)
126 if (consecutive_failures == 2)
129 }
130 if (consecutive_failures <= 1)
132 if (consecutive_failures == 2)
134 if (consecutive_failures == 3)
136 if (consecutive_failures == 4)
139}
140
141} // namespace home_io_control
142} // namespace esphome
void set_interval(const std::string &device_id, uint32_t interval_ms)
Set the configured follow-up poll interval (ms; 0 = legacy one-shot settle only).
bool is_tracking_active(const std::string &device_id, uint32_t now) const
True when the device has an active bounded polling window (deadline set and not expired).
uint32_t get_next_update(const std::string &device_id) const
uint32_t get_interval(const std::string &device_id) const
Return the configured interval (0 when not set or unconfigured).
void clear_failure_streaks(const std::string &device_id)
Reset failure streaks after a successful exchange response.
void set_next_update(const std::string &device_id, uint32_t abs_time)
Schedule the next poll at an absolute millis() timestamp.
uint32_t on_exchange_failed(const std::string &device_id, bool auth_like, uint32_t now)
Record a failed background poll; apply backoff or clear tracking if the window expired.
void begin_tracking(const std::string &device_id, uint32_t initial_delay_ms, uint32_t now)
Begin bounded follow-up polling after a command or remote activity.
uint8_t get_status_poll_failures(const std::string &device_id) const
uint8_t get_auth_poll_failures(const std::string &device_id) const
uint32_t get_poll_deadline(const std::string &device_id) const
void clear(const std::string &device_id)
Stop all polling for a device and reset failure counts. Preserves interval_ms.
std::optional< std::string > pop_due_device(uint32_t now)
Return and consume the first device whose next_update is overdue.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP4_MS
Fourth retry after a silent failure.
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MAX_MS
Steady-state after repeated auth failures.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP3_MS
Third retry after a silent failure.
static constexpr uint32_t MAX_TRACKED_STATUS_POLL_WINDOW_MS
Hard stop for bounded follow-up polling after a command or remote activity.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MS
First retry after a silent failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MAX_MS
Steady-state backoff after many silent failures.
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_STEP2_MS
Second retry.
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MS
First retry after a challenge-seen failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP2_MS
Second retry after a silent failure.
Per-device poll scheduling, failure backoff, and follow-up-poll state machine.
Per-device poll scheduling state.
uint8_t auth_poll_failures
Consecutive background poll failures that saw a 0x3C challenge.
uint8_t status_poll_failures
Consecutive background poll failures (silent — no reply).
uint32_t poll_deadline
Hard stop for bounded follow-up polling.
uint32_t next_update
Absolute millis() timestamp for the next poll; 0 = idle.