DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
telemetry.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file telemetry.cpp
6 * @brief Telemetry math helpers implementation (DETWS_ENABLE_TELEMETRY).
7 */
8
9#include "telemetry.h"
10
11#if DETWS_ENABLE_TELEMETRY
12
13#include <math.h>
14
15void detws_window_init(DetwsWindow *w, float *buf, uint16_t cap)
16{
17 w->buf = buf;
18 w->cap = cap;
19 w->count = 0;
20 w->head = 0;
21 w->sum = 0.0;
22 w->sum_sq = 0.0;
23}
24
25void detws_window_push(DetwsWindow *w, float sample)
26{
27 if (!w->buf || w->cap == 0)
28 return;
29 if (w->count == w->cap)
30 {
31 // Full: evict the oldest sample (at head) from the running sums.
32 float old = w->buf[w->head];
33 w->sum -= (double)old;
34 w->sum_sq -= (double)old * (double)old;
35 }
36 else
37 {
38 w->count++;
39 }
40 w->buf[w->head] = sample;
41 w->sum += (double)sample;
42 w->sum_sq += (double)sample * (double)sample;
43 w->head = (uint16_t)((w->head + 1) % w->cap);
44}
45
46uint16_t detws_window_count(const DetwsWindow *w)
47{
48 return w->count;
49}
50
51float detws_window_mean(const DetwsWindow *w)
52{
53 if (w->count == 0)
54 return 0.0f;
55 return (float)(w->sum / (double)w->count);
56}
57
58float detws_window_variance(const DetwsWindow *w)
59{
60 if (w->count == 0)
61 return 0.0f;
62 double mean = w->sum / (double)w->count;
63 double var = w->sum_sq / (double)w->count - mean * mean;
64 return var < 0.0 ? 0.0f : (float)var; // clamp tiny negatives from rounding
65}
66
67float detws_window_stddev(const DetwsWindow *w)
68{
69 return sqrtf(detws_window_variance(w));
70}
71
72float detws_window_min(const DetwsWindow *w)
73{
74 if (w->count == 0)
75 return 0.0f;
76 float m = w->buf[0];
77 for (uint16_t i = 1; i < w->count; i++)
78 if (w->buf[i] < m)
79 m = w->buf[i];
80 return m;
81}
82
83float detws_window_max(const DetwsWindow *w)
84{
85 if (w->count == 0)
86 return 0.0f;
87 float m = w->buf[0];
88 for (uint16_t i = 1; i < w->count; i++)
89 if (w->buf[i] > m)
90 m = w->buf[i];
91 return m;
92}
93
94void detws_rate_init(DetwsRate *r)
95{
96 r->last_value = 0.0f;
97 r->last_ms = 0;
98 r->primed = false;
99}
100
101float detws_rate_update(DetwsRate *r, float value, uint32_t now_ms)
102{
103 if (!r->primed)
104 {
105 r->last_value = value;
106 r->last_ms = now_ms;
107 r->primed = true;
108 return 0.0f;
109 }
110 uint32_t dt_ms = (uint32_t)(now_ms - r->last_ms); // wraps correctly
111 float rate = 0.0f;
112 if (dt_ms != 0)
113 rate = (value - r->last_value) * 1000.0f / (float)dt_ms;
114 r->last_value = value;
115 r->last_ms = now_ms;
116 return rate;
117}
118
119void detws_totalizer_init(DetwsTotalizer *t)
120{
121 t->total = 0.0;
122 t->last_rate = 0.0f;
123 t->last_ms = 0;
124 t->primed = false;
125}
126
127double detws_totalizer_add(DetwsTotalizer *t, float rate, uint32_t now_ms)
128{
129 if (!t->primed)
130 {
131 t->last_rate = rate;
132 t->last_ms = now_ms;
133 t->primed = true;
134 return t->total;
135 }
136 uint32_t dt_ms = (uint32_t)(now_ms - t->last_ms); // wraps correctly
137 double dt_s = (double)dt_ms / 1000.0;
138 // Trapezoidal: average of the two rate endpoints over the interval.
139 t->total += ((double)t->last_rate + (double)rate) * 0.5 * dt_s;
140 t->last_rate = rate;
141 t->last_ms = now_ms;
142 return t->total;
143}
144
145double detws_totalizer_total(const DetwsTotalizer *t)
146{
147 return t->total;
148}
149
150void detws_totalizer_reset(DetwsTotalizer *t)
151{
152 t->total = 0.0;
153 t->last_rate = 0.0f;
154 t->last_ms = 0;
155 t->primed = false;
156}
157
158#endif // DETWS_ENABLE_TELEMETRY
Zero-heap telemetry math helpers (DETWS_ENABLE_TELEMETRY).