Skip to content

Commit ac83492

Browse files
author
Scott Powell
committed
* simplified alertIf()
* refactored TimeSeriesData to top-level class
1 parent de3e4bc commit ac83492

File tree

5 files changed

+82
-91
lines changed

5 files changed

+82
-91
lines changed

examples/simple_sensor/SensorMesh.cpp

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,8 @@ void SensorMesh::sendAlert(const char* text) {
237237
}
238238
}
239239

240-
void SensorMesh::alertIfLow(Trigger& t, float value, float threshold, const char* text) {
241-
if (value < threshold) {
240+
void SensorMesh::alertIf(bool condition, Trigger& t, const char* text) {
241+
if (condition) {
242242
if (!t.triggered) {
243243
t.triggered = true;
244244
t.time = getRTCClock()->getCurrentTime();
@@ -252,65 +252,6 @@ void SensorMesh::alertIfLow(Trigger& t, float value, float threshold, const char
252252
}
253253
}
254254

255-
void SensorMesh::alertIfHigh(Trigger& t, float value, float threshold, const char* text) {
256-
if (value > threshold) {
257-
if (!t.triggered) {
258-
t.triggered = true;
259-
t.time = getRTCClock()->getCurrentTime();
260-
sendAlert(text);
261-
}
262-
} else {
263-
if (t.triggered) {
264-
t.triggered = false;
265-
// TODO: apply debounce logic
266-
}
267-
}
268-
}
269-
270-
void SensorMesh::recordData(TimeSeriesData& data, float value) {
271-
uint32_t now = getRTCClock()->getCurrentTime();
272-
if (now >= data.last_timestamp + data.interval_secs) {
273-
data.last_timestamp = now;
274-
275-
data.data[data.next] = value; // append to cycle table
276-
data.next = (data.next + 1) % data.num_slots;
277-
}
278-
}
279-
280-
void SensorMesh::calcDataMinMaxAvg(const TimeSeriesData& data, uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg* dest, uint8_t channel, uint8_t lpp_type) {
281-
int i = data.next, n = data.num_slots;
282-
uint32_t ago = data.interval_secs * data.num_slots;
283-
int num_values = 0;
284-
float total = 0.0f;
285-
286-
dest->_channel = channel;
287-
dest->_lpp_type = lpp_type;
288-
289-
// start at earliest recording, through to most recent
290-
while (n > 0) {
291-
n--;
292-
i = (i + 1) % data.num_slots;
293-
if (ago >= end_secs_ago && ago < start_secs_ago) {
294-
float v = data.data[i];
295-
num_values++;
296-
total += v;
297-
if (num_values == 1) {
298-
dest->_max = dest->_min = v;
299-
} else {
300-
if (v < dest->_min) dest->_min = v;
301-
if (v > dest->_max) dest->_max = v;
302-
}
303-
}
304-
ago -= data.interval_secs;
305-
}
306-
// calc average
307-
if (num_values > 0) {
308-
dest->_avg = total / num_values;
309-
} else {
310-
dest->_avg = NAN;
311-
}
312-
}
313-
314255
float SensorMesh::getAirtimeBudgetFactor() const {
315256
return _prefs.airtime_factor;
316257
}

examples/simple_sensor/SensorMesh.h

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#include <Arduino.h> // needed for PlatformIO
44
#include <Mesh.h>
55

6+
#include "TimeSeriesData.h"
7+
68
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
79
#include <InternalFileSystem.h>
810
#elif defined(RP2040_PLATFORM)
@@ -90,33 +92,7 @@ class SensorMesh : public mesh::Mesh, public CommonCLICallbacks {
9092
Trigger() { triggered = false; time = 0; }
9193
};
9294

93-
void alertIfLow(Trigger& t, float value, float threshold, const char* text);
94-
void alertIfHigh(Trigger& t, float value, float threshold, const char* text);
95-
96-
class TimeSeriesData {
97-
public:
98-
float* data;
99-
int num_slots, next;
100-
uint32_t last_timestamp;
101-
uint32_t interval_secs;
102-
103-
TimeSeriesData(float* array, int num, uint32_t secs) : num_slots(num), data(array), last_timestamp(0), next(0), interval_secs(secs) {
104-
memset(data, 0, sizeof(float)*num);
105-
}
106-
TimeSeriesData(int num, uint32_t secs) : num_slots(num), last_timestamp(0), next(0), interval_secs(secs) {
107-
data = new float[num];
108-
memset(data, 0, sizeof(float)*num);
109-
}
110-
};
111-
112-
void recordData(TimeSeriesData& data, float value);
113-
114-
struct MinMaxAvg {
115-
float _min, _max, _avg;
116-
uint8_t _lpp_type, _channel;
117-
};
118-
119-
void calcDataMinMaxAvg(const TimeSeriesData& data, uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg* dest, uint8_t channel, uint8_t lpp_type);
95+
void alertIf(bool condition, Trigger& t, const char* text);
12096

12197
virtual void onSensorDataRead() = 0; // for app to implement
12298
virtual int querySeriesData(uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg dest[], int max_num) = 0; // for app to implement
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "TimeSeriesData.h"
2+
3+
void TimeSeriesData::recordData(mesh::RTCClock* clock, float value) {
4+
uint32_t now = clock->getCurrentTime();
5+
if (now >= last_timestamp + interval_secs) {
6+
last_timestamp = now;
7+
8+
data[next] = value; // append to cycle table
9+
next = (next + 1) % num_slots;
10+
}
11+
}
12+
13+
void TimeSeriesData::calcDataMinMaxAvg(mesh::RTCClock* clock, uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg* dest, uint8_t channel, uint8_t lpp_type) const {
14+
int i = next, n = num_slots;
15+
uint32_t ago = clock->getCurrentTime() - last_timestamp;
16+
int num_values = 0;
17+
float total = 0.0f;
18+
19+
dest->_channel = channel;
20+
dest->_lpp_type = lpp_type;
21+
22+
// start at most recet recording, back-track through to oldest
23+
while (n > 0) {
24+
n--;
25+
i = (i + num_slots - 1) % num_slots; // go back by one
26+
if (ago >= end_secs_ago && ago < start_secs_ago) { // filter by the desired time range
27+
float v = data[i];
28+
num_values++;
29+
total += v;
30+
if (num_values == 1) {
31+
dest->_max = dest->_min = v;
32+
} else {
33+
if (v < dest->_min) dest->_min = v;
34+
if (v > dest->_max) dest->_max = v;
35+
}
36+
}
37+
ago += interval_secs;
38+
}
39+
// calc average
40+
if (num_values > 0) {
41+
dest->_avg = total / num_values;
42+
} else {
43+
dest->_avg = NAN;
44+
}
45+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#pragma once
2+
3+
#include <Arduino.h>
4+
#include <Mesh.h>
5+
6+
struct MinMaxAvg {
7+
float _min, _max, _avg;
8+
uint8_t _lpp_type, _channel;
9+
};
10+
11+
class TimeSeriesData {
12+
float* data;
13+
int num_slots, next;
14+
uint32_t last_timestamp;
15+
uint32_t interval_secs;
16+
17+
public:
18+
TimeSeriesData(float* array, int num, uint32_t secs) : num_slots(num), data(array), last_timestamp(0), next(0), interval_secs(secs) {
19+
memset(data, 0, sizeof(float)*num);
20+
}
21+
TimeSeriesData(int num, uint32_t secs) : num_slots(num), last_timestamp(0), next(0), interval_secs(secs) {
22+
data = new float[num];
23+
memset(data, 0, sizeof(float)*num);
24+
}
25+
26+
void recordData(mesh::RTCClock* clock, float value);
27+
void calcDataMinMaxAvg(mesh::RTCClock* clock, uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg* dest, uint8_t channel, uint8_t lpp_type) const;
28+
};
29+

examples/simple_sensor/main.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ class MyMesh : public SensorMesh {
2121
void onSensorDataRead() override {
2222
float batt_voltage = getVoltage(TELEM_CHANNEL_SELF);
2323

24-
recordData(battery_data, batt_voltage); // record battery
25-
alertIfLow(low_batt, batt_voltage, 3.4f, "Battery low!");
24+
battery_data.recordData(getRTCClock(), batt_voltage); // record battery
25+
alertIf(batt_voltage < 3.4f, low_batt, "Battery low!");
2626
}
2727

2828
int querySeriesData(uint32_t start_secs_ago, uint32_t end_secs_ago, MinMaxAvg dest[], int max_num) override {
29-
calcDataMinMaxAvg(battery_data, start_secs_ago, end_secs_ago, &dest[0], TELEM_CHANNEL_SELF, LPP_VOLTAGE);
29+
battery_data.calcDataMinMaxAvg(getRTCClock(), start_secs_ago, end_secs_ago, &dest[0], TELEM_CHANNEL_SELF, LPP_VOLTAGE);
3030
return 1;
3131
}
3232
/* ======================================================================= */

0 commit comments

Comments
 (0)