Skip to content

Commit ac4c5f1

Browse files
committed
Refactor alert display and monitoring logic
- Updated AlertUIUpdate structure to separate critical and warning displays. - Modified alert handling in alert_display.cpp to manage independent lists for critical and warning alerts. - Adjusted threshold hysteresis values in monitor_config.h for improved temperature monitoring. - Enhanced UI update functions in lvgl_alerts.cpp to support new critical and warning text labels. - Implemented new functions to hide critical and warning text separately, improving display management.
1 parent 6731620 commit ac4c5f1

7 files changed

Lines changed: 215 additions & 117 deletions

File tree

inc/sp140/alert_display.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ struct AlertUIUpdate {
3232
// Counter data
3333
AlertCounts counts;
3434

35-
// Display message data
36-
SensorID displayId; // Valid sensor when showDisplay == true
37-
AlertLevel displayLevel; // Alert level for dynamic abbreviations
38-
bool displayCritical; // true = critical colouring
39-
bool showDisplay; // false = hide label
35+
// Warning display (bottom row)
36+
SensorID warningId; // Valid sensor when showWarning == true
37+
AlertLevel warningLevel; // Alert level for dynamic abbreviations
38+
bool showWarning; // false = hide warning label
39+
40+
// Critical display (top row, in altitude area)
41+
SensorID criticalId; // Valid sensor when showCritical == true
42+
AlertLevel criticalLevel; // Alert level for dynamic abbreviations
43+
bool showCritical; // false = hide critical label
4044

4145
// Critical alert state (for border/vibration control)
4246
bool criticalAlertsActive; // true = show red border + vibration

inc/sp140/lvgl/lvgl_alerts.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ extern lv_obj_t* critical_counter_circle;
1313
extern lv_obj_t* critical_counter_label;
1414

1515
// Alert text carousel objects
16-
extern lv_obj_t* alert_text_label;
16+
extern lv_obj_t* alert_text_label; // For warning text
17+
extern lv_obj_t* critical_text_label; // For critical text (separate so both can show)
1718
extern lv_timer_t* alert_cycle_timer;
1819

1920
// Snapshot state shared between timer and external updater
@@ -29,5 +30,7 @@ void loadAlertSnapshot(const AlertSnapshot& snap);
2930
void lv_showAlertText(SensorID id, bool critical);
3031
void lv_showAlertTextWithLevel(SensorID id, AlertLevel level, bool critical);
3132
void lv_hideAlertText();
33+
void lv_hideWarningText();
34+
void lv_hideCriticalText();
3235

3336
#endif // INC_SP140_LVGL_LVGL_ALERTS_H_

inc/sp140/monitor_config.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,24 @@
66
// This file serves as the single source of truth for all sensor monitoring thresholds.
77

88
// -- ESC Thresholds --
9-
static const Thresholds escMosTempThresholds = {.warnLow = -10, .warnHigh = 90, .critLow = -20, .critHigh = 110, .hysteresis = 2.0f};
10-
static const Thresholds escMcuTempThresholds = {.warnLow = -10, .warnHigh = 80, .critLow = -20, .critHigh = 95, .hysteresis = 2.0f};
11-
static const Thresholds escCapTempThresholds = {.warnLow = -10, .warnHigh = 85, .critLow = -20, .critHigh = 100, .hysteresis = 2.0f};
12-
static const Thresholds motorTempThresholds = {.warnLow = -20, .warnHigh = 105, .critLow = -25, .critHigh = 115, .hysteresis = 2.0f};
9+
static const Thresholds escMosTempThresholds = {.warnLow = -10, .warnHigh = 90, .critLow = -20, .critHigh = 110, .hysteresis = 1.0f};
10+
static const Thresholds escMcuTempThresholds = {.warnLow = -10, .warnHigh = 80, .critLow = -20, .critHigh = 95, .hysteresis = 1.0f};
11+
static const Thresholds escCapTempThresholds = {.warnLow = -10, .warnHigh = 85, .critLow = -20, .critHigh = 100, .hysteresis = 1.0f};
12+
static const Thresholds motorTempThresholds = {.warnLow = -20, .warnHigh = 105, .critLow = -25, .critHigh = 115, .hysteresis = 1.0f};
1313

1414
// -- BMS Thresholds --
15-
static const Thresholds bmsTempThresholds = {.warnLow = -10, .warnHigh = 50, .critLow = -15, .critHigh = 60, .hysteresis = 2.0f};
16-
static const Thresholds bmsCellTempThresholds = {.warnLow = -10, .warnHigh = 50, .critLow = -15, .critHigh = 56, .hysteresis = 2.0f};
15+
static const Thresholds bmsTempThresholds = {.warnLow = -10, .warnHigh = 50, .critLow = -15, .critHigh = 60, .hysteresis = 1.0f};
16+
static const Thresholds bmsCellTempThresholds = {.warnLow = -10, .warnHigh = 50, .critLow = -15, .critHigh = 56, .hysteresis = 1.0f};
1717
static const Thresholds bmsHighCellVoltageThresholds = {.warnLow = 0.0, .warnHigh = 4.19, .critLow = 0.0, .critHigh = 4.20};
1818
static const Thresholds bmsLowCellVoltageThresholds = {.warnLow = 3.2, .warnHigh = 4.5, .critLow = 3.0, .critHigh = 4.8};
1919
static const Thresholds bmsSOCThresholds = {.warnLow = 15.0, .warnHigh = 101.0, .critLow = 5.0, .critHigh = 110.0};
2020
static const Thresholds bmsTotalVoltageThresholds = {.warnLow = 79.2, .warnHigh = 100.4, .critLow = 69.6, .critHigh = 100.8};
2121
static const Thresholds bmsVoltageDifferentialThresholds = {.warnLow = -1.0, .warnHigh = 0.2, .critLow = -2.0, .critHigh = 0.4};
2222

2323
// -- Altimeter Thresholds --
24-
static const Thresholds baroTempThresholds = {.warnLow = 0, .warnHigh = 50, .critLow = -10, .critHigh = 80, .hysteresis = 2.0f};
24+
static const Thresholds baroTempThresholds = {.warnLow = 0, .warnHigh = 50, .critLow = -10, .critHigh = 80, .hysteresis = 1.0f};
2525

2626
// -- Internal Thresholds --
27-
static const Thresholds cpuTempThresholds = {.warnLow = 0, .warnHigh = 60, .critLow = -10, .critHigh = 80, .hysteresis = 2.0f};
27+
static const Thresholds cpuTempThresholds = {.warnLow = 0, .warnHigh = 60, .critLow = -10, .critHigh = 80, .hysteresis = 1.0f};
2828

2929
#endif // INC_SP140_MONITOR_CONFIG_H_

src/sp140/alert_display.cpp

Lines changed: 69 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@ static AlertCounts g_currentCounts = {0, 0};
1919
static AlertCounts g_previousCounts = {0, 0}; // Track previous counts for transitions
2020
static uint32_t g_epoch = 0;
2121

22-
// Rotation state for display
23-
static std::vector<SensorID> g_activeList;
24-
static bool g_showingCrit = false;
25-
static size_t g_rotateIdx = 0;
22+
// Rotation state for display - separate lists for warnings and criticals
23+
static std::vector<SensorID> g_critList;
24+
static std::vector<SensorID> g_warnList;
25+
static size_t g_critRotateIdx = 0;
26+
static size_t g_warnRotateIdx = 0;
2627
static unsigned long g_lastRotateMs = 0;
2728

2829
// Forward declarations
@@ -56,6 +57,36 @@ void sendAlertEvent(SensorID id, AlertLevel level) {
5657
xQueueSend(alertEventQueue, &ev, 0); // best-effort, drop if full
5758
}
5859

60+
// Helper to build and send UI update with current state
61+
static void sendUIUpdate() {
62+
AlertUIUpdate update;
63+
update.counts = g_currentCounts;
64+
update.criticalAlertsActive = (g_currentCounts.criticalCount > 0);
65+
update.updateEpoch = g_epoch;
66+
67+
// Critical display (shows on top, in altitude area)
68+
if (!g_critList.empty()) {
69+
update.showCritical = true;
70+
update.criticalId = g_critList[g_critRotateIdx];
71+
update.criticalLevel = g_currentLevels[g_critList[g_critRotateIdx]];
72+
} else {
73+
update.showCritical = false;
74+
}
75+
76+
// Warning display (shows below critical)
77+
if (!g_warnList.empty()) {
78+
update.showWarning = true;
79+
update.warningId = g_warnList[g_warnRotateIdx];
80+
update.warningLevel = g_currentLevels[g_warnList[g_warnRotateIdx]];
81+
} else {
82+
update.showWarning = false;
83+
}
84+
85+
if (alertUIQueue) {
86+
xQueueOverwrite(alertUIQueue, &update);
87+
}
88+
}
89+
5990
// ------------ Internal implementation -------------
6091
static void alertAggregationTask(void* parameter) {
6192
AlertEvent ev;
@@ -72,36 +103,28 @@ static void alertAggregationTask(void* parameter) {
72103
recalcCountsAndPublish();
73104
}
74105

75-
// Handle rotation every 2s if active list not empty
76-
if (!g_activeList.empty()) {
106+
// Handle rotation every 2s if either list not empty
107+
bool hasAlerts = !g_critList.empty() || !g_warnList.empty();
108+
if (hasAlerts) {
77109
unsigned long now = millis();
78110
if (now - g_lastRotateMs >= 2000) {
79111
g_lastRotateMs = now;
80-
g_rotateIdx = (g_rotateIdx + 1) % g_activeList.size();
81-
82-
// Send unified update with current counts and display info
83-
AlertUIUpdate update;
84-
update.counts = g_currentCounts;
85-
update.showDisplay = true;
86-
update.displayId = g_activeList[g_rotateIdx];
87-
update.displayLevel = g_currentLevels[g_activeList[g_rotateIdx]];
88-
update.displayCritical = g_showingCrit;
89-
update.criticalAlertsActive = (g_currentCounts.criticalCount > 0);
90-
update.updateEpoch = g_epoch;
91-
if (alertUIQueue) {
92-
xQueueOverwrite(alertUIQueue, &update);
112+
113+
// Rotate both lists independently
114+
if (!g_critList.empty()) {
115+
g_critRotateIdx = (g_critRotateIdx + 1) % g_critList.size();
93116
}
117+
if (!g_warnList.empty()) {
118+
g_warnRotateIdx = (g_warnRotateIdx + 1) % g_warnList.size();
119+
}
120+
121+
sendUIUpdate();
94122
}
95123
} else {
96-
// If list empty ensure label hidden once
124+
// If both lists empty, ensure labels hidden once
97125
static bool hideSent = false;
98126
if (!hideSent) {
99-
AlertUIUpdate update;
100-
update.counts = g_currentCounts;
101-
update.showDisplay = false;
102-
update.criticalAlertsActive = (g_currentCounts.criticalCount > 0);
103-
update.updateEpoch = g_epoch;
104-
if (alertUIQueue) xQueueOverwrite(alertUIQueue, &update);
127+
sendUIUpdate();
105128
hideSent = true;
106129
}
107130
}
@@ -110,18 +133,18 @@ static void alertAggregationTask(void* parameter) {
110133

111134
static void recalcCountsAndPublish() {
112135
AlertCounts counts{0, 0};
113-
std::vector<SensorID> critList;
114-
std::vector<SensorID> warnList;
136+
std::vector<SensorID> newCritList;
137+
std::vector<SensorID> newWarnList;
115138
for (const auto& kv : g_currentLevels) {
116139
switch (kv.second) {
117140
case AlertLevel::WARN_LOW:
118141
case AlertLevel::WARN_HIGH:
119-
warnList.push_back(kv.first);
142+
newWarnList.push_back(kv.first);
120143
counts.warningCount++;
121144
break;
122145
case AlertLevel::CRIT_LOW:
123146
case AlertLevel::CRIT_HIGH:
124-
critList.push_back(kv.first);
147+
newCritList.push_back(kv.first);
125148
counts.criticalCount++;
126149
break;
127150
default:
@@ -138,48 +161,33 @@ static void recalcCountsAndPublish() {
138161
counts.criticalCount != g_currentCounts.criticalCount);
139162
g_currentCounts = counts;
140163

141-
// Update active list for display rotation
142-
bool newShowingCrit = !critList.empty();
143-
const std::vector<SensorID>& newList = newShowingCrit ? critList : warnList;
164+
// Check if lists changed
165+
bool critListChanged = (newCritList != g_critList);
166+
bool warnListChanged = (newWarnList != g_warnList);
144167

145-
bool listChanged = (newShowingCrit != g_showingCrit) || (newList != g_activeList);
146-
147-
// Send unified update when counts change or display list changes
148-
if (countsChanged || listChanged) {
149-
if (listChanged) {
150-
g_activeList = newList;
151-
g_showingCrit = newShowingCrit;
152-
g_rotateIdx = 0;
153-
g_lastRotateMs = millis();
168+
// Send unified update when counts change or display lists change
169+
if (countsChanged || critListChanged || warnListChanged) {
170+
if (critListChanged) {
171+
g_critList = newCritList;
172+
g_critRotateIdx = 0;
154173
}
155-
156-
AlertUIUpdate update;
157-
update.counts = g_currentCounts;
158-
update.criticalAlertsActive = (g_currentCounts.criticalCount > 0);
159-
update.updateEpoch = g_epoch;
160-
161-
if (g_activeList.empty()) {
162-
update.showDisplay = false;
163-
} else {
164-
update.showDisplay = true;
165-
update.displayId = g_activeList[g_rotateIdx];
166-
update.displayLevel = g_currentLevels[g_activeList[g_rotateIdx]];
167-
update.displayCritical = g_showingCrit;
174+
if (warnListChanged) {
175+
g_warnList = newWarnList;
176+
g_warnRotateIdx = 0;
168177
}
178+
g_lastRotateMs = millis();
169179

170180
USBSerial.printf("[Alert] Sending UI update: crit=%d warn=%d critActive=%d\n",
171-
update.counts.criticalCount, update.counts.warningCount, update.criticalAlertsActive);
181+
counts.criticalCount, counts.warningCount, (counts.criticalCount > 0));
172182

173-
if (alertUIQueue) {
174-
xQueueOverwrite(alertUIQueue, &update);
175-
}
183+
sendUIUpdate();
176184
}
177185

178186
// Build snapshot for carousel (critical preferred)
179187
AlertSnapshot snap{};
180188
snap.epoch = ++g_epoch;
181-
snap.criticalMode = (!critList.empty()) ? 1 : 0;
182-
const std::vector<SensorID>& srcList = (!critList.empty()) ? critList : warnList;
189+
snap.criticalMode = (!newCritList.empty()) ? 1 : 0;
190+
const std::vector<SensorID>& srcList = (!newCritList.empty()) ? newCritList : newWarnList;
183191
snap.count = (uint8_t)std::min<size_t>(srcList.size(), MAX_ALERT_ITEMS);
184192
for (uint8_t i = 0; i < snap.count; ++i) {
185193
snap.ids[i] = srcList[i];

0 commit comments

Comments
 (0)