7 return interval > 0U && interval <= INT32_MAX;
10static bool elapsed(uint32_t now, uint32_t then, uint32_t interval) {
11 return (uint32_t)(now - then) >= interval;
37 for (uint8_t j = 0; j < i; ++j) {
47 t->status.probes_complete =
true;
48 for (uint8_t i = 0; i < t->config.device_count; ++i) {
49 if (!t->status.devices[i].complete) {
50 t->status.probes_complete =
false;
53 bool required =
false;
56 for (uint8_t i = 0; i < t->config.device_count; ++i) {
75 if (!t || !t->initialized) {
78 memset(&t->status, 0,
sizeof(t->status));
79 memset(t->probes, 0,
sizeof(t->probes));
80 t->status.now_ms = now_ms;
81 t->status.device_count = t->config.device_count;
82 for (uint8_t i = 0; i < t->config.device_count; ++i) {
83 t->status.devices[i].device_id = t->config.devices[i].device_id;
84 t->status.devices[i].required = t->config.devices[i].required;
86 t->session_started_ms = now_ms;
88 t->last_heartbeat_ms = now_ms;
89 t->last_battery_ms = now_ms;
90 t->last_publication_ms = now_ms;
91 t->heartbeat_started =
false;
92 t->battery_started =
false;
93 t->publication_retry =
false;
104 memset(t, 0,
sizeof(*t));
109 if (t->config.session_timeout_ms == 0U) {
113 t->context = context;
114 t->initialized =
true;
123 d->
attempts < t->config.probe_max_attempts) {
124 p->retry_wait =
true;
125 p->retry_at_ms = now_ms;
132 for (uint8_t
n = 0;
n < t->config.device_count; ++
n) {
133 uint8_t i = t->next_probe;
134 t->next_probe = (uint8_t)((i + 1U) % t->config.device_count);
141 if (!
elapsed(now_ms,
p->retry_at_ms, t->config.retry_interval_ms)) {
144 p->retry_wait =
false;
149 p->started_at_ms = now_ms;
151 }
else if (
elapsed(now_ms,
p->started_at_ms,
152 t->config.probe_timeout_ms)) {
158 uint32_t remaining = t->config.probe_timeout_ms -
159 (uint32_t)(now_ms -
p->started_at_ms);
160 uint32_t session_remaining =
161 t->config.session_timeout_ms -
162 (uint32_t)(now_ms - t->session_started_ms);
163 if (session_remaining < remaining) {
164 remaining = session_remaining;
166 uint32_t budget = t->config.callback_budget_ms;
167 if (remaining < budget) {
183 if (!t->battery_started ||
184 elapsed(now_ms, t->last_battery_ms, t->config.battery_interval_ms)) {
185 t->battery_started =
true;
186 t->last_battery_ms = now_ms;
187 if (t->port.read_battery) {
188 t->status.battery = t->port.read_battery(
189 t->context, now_ms, t->config.callback_budget_ms);
190 t->status.battery.reply =
checked_reply(t->status.battery.reply);
192 !t->status.battery.valid) {
200 t->status.battery.valid =
201 t->status.battery.valid &&
204 if (t->status.battery.valid &&
205 elapsed(now_ms, t->status.battery.sampled_at_ms,
206 t->config.battery_max_age_ms)) {
207 t->status.battery.valid =
false;
211 if (!t->status.battery.valid) {
212 t->status.battery.raw_counts = 0;
217 if (!t->heartbeat_started ||
elapsed(now_ms, t->last_heartbeat_ms,
218 t->config.heartbeat_interval_ms)) {
219 t->heartbeat_started =
true;
220 t->last_heartbeat_ms = now_ms;
221 t->status.publication_attempts = 0;
222 t->publication_retry =
true;
223 }
else if (!t->publication_retry || !
elapsed(now_ms, t->last_publication_ms,
224 t->config.retry_interval_ms)) {
227 t->last_publication_ms = now_ms;
228 ++t->status.publication_attempts;
229 t->status.publication =
230 t->port.publish_status
232 t->context, &t->status, t->config.callback_budget_ms))
235 t->publication_retry =
238 t->status.publication_attempts < t->config.publication_max_attempts;
245 if (!t || !t->initialized) {
248 t->status.now_ms = now_ms;
249 if (!t->status.probes_complete) {
250 if (
elapsed(now_ms, t->session_started_ms,
251 t->config.session_timeout_ms)) {
252 t->status.deadline_expired =
true;
253 for (uint8_t i = 0; i < t->config.device_count; ++i) {
271 return t && t->initialized ? &t->status :
NULL;
static const emmc_port_t port
static const idle_config_t config
*brief user defined string literal for JSON values *sa std::size_t n
bool self_test_init(self_test_t *t, const self_test_config_t *config, const self_test_port_t *port, void *context, uint32_t now_ms)
static void aggregate(self_test_t *t)
void self_test_tick(self_test_t *t, uint32_t now_ms)
bool self_test_reset(self_test_t *t, uint32_t now_ms)
static self_test_reply_t checked_reply(self_test_reply_t reply)
static void publish(self_test_t *t, uint32_t now_ms)
static bool elapsed(uint32_t now, uint32_t then, uint32_t interval)
const self_test_status_t * self_test_status(const self_test_t *t)
static bool interval_valid(uint32_t interval)
static void probe_one(self_test_t *t, uint32_t now_ms)
static void finish_probe(self_test_t *t, uint8_t index, uint32_t now_ms)
static void sample_battery(self_test_t *t, uint32_t now_ms)
#define SELF_TEST_DEFAULT_SESSION_TIMEOUT_MS
static self_test_reply_t reply(self_test_result_t result, int32_t diagnostic)
#define SELF_TEST_DIAG_BAD_REPLY
#define SELF_TEST_MAX_DEVICES
#define SELF_TEST_DIAG_STALE_BATTERY
#define SELF_TEST_DIAG_SESSION_TIMEOUT
@ SELF_TEST_NOT_CONFIGURED
@ SELF_TEST_NOT_IMPLEMENTED
uint32_t heartbeat_interval_ms
uint32_t session_timeout_ms
self_test_device_t devices[SELF_TEST_MAX_DEVICES]
uint32_t callback_budget_ms
uint32_t retry_interval_ms
uint32_t battery_interval_ms
uint32_t probe_timeout_ms
uint8_t publication_max_attempts
uint32_t battery_max_age_ms
uint8_t probe_max_attempts
self_test_result_t result