Web: add MCU temperature sparkline with thermal threshold coloring
Add visual indicators for the mcu_temp trend series on the /stats page.
Values are stored as deci-°C (tenths of a degree), so all threshold
constants are in that unit (750 = 75 °C, 950 = 95 °C).
Threshold rationale (ESP32-S3 / Heltec V4, internal die temperature,
T_j max = 105 °C per datasheet):
- < 75 °C (< 750): normal, green — comfortable operating range
- 75–95 °C (750–950): elevated, amber — die is running hot,
30 °C below the junction temperature limit
- > 95 °C (> 950): critical, red — 10 °C below the 105 °C
junction limit; sensor accuracy is ±2 °C in this range
- Chart upper bound 125 °C (1250) covers the full sensor measurement
range with headroom
Changes:
- sparkStrokeColor: color the mcu_temp stroke dynamically based on
the most recent data point (green / amber / red)
- sparkGuideValues: draw horizontal guide lines at 75 °C and 95 °C
- sparkBands: shade three background bands (normal / high / critical)
- getTrendSeriesOrder: insert "mcu_temp" at position 2 (after battery
and memory, before RF metrics) when sensors.mcu_temp_c is present
in the summary payload
Этот коммит содержится в:
@@ -1798,6 +1798,16 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
}
|
||||
function sparkStrokeColor(key, points) {
|
||||
if (key === "packets") return "#d97706";
|
||||
if (key === "mcu_temp") {
|
||||
const values = Array.isArray(points)
|
||||
? points.map((item) => item && item[1]).filter((v) => Number.isFinite(v))
|
||||
: [];
|
||||
const recent = values.length ? values[values.length - 1] : NaN;
|
||||
if (!Number.isFinite(recent)) return "#2f8f4e";
|
||||
if (recent >= 950) return "#d14343"; // critical
|
||||
if (recent >= 750) return "#d7a531"; // high
|
||||
return "#2f8f4e"; // normal
|
||||
}
|
||||
if (key === "gps_satellites") return "#2f8f4e";
|
||||
if (key === "signal") return "#3b82f6";
|
||||
if (key === "noise_floor") return "#94a3b8";
|
||||
@@ -1835,6 +1845,9 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
return { min:minValue, max:maxValue };
|
||||
}
|
||||
function sparkGuideValues(key) {
|
||||
if (key === "mcu_temp") {
|
||||
return [750, 950]; // 75 °C, 95 °C
|
||||
}
|
||||
if (key === "signal") {
|
||||
return [-120, -110, -100, -90, -80, -70, -60, -50, -40].map((value) => value * 4);
|
||||
}
|
||||
@@ -1844,6 +1857,13 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
return [];
|
||||
}
|
||||
function sparkBands(key) {
|
||||
if (key === "mcu_temp") {
|
||||
return [
|
||||
{ from: 0, to: 750, color: "rgba(47,143,78,0.12)" }, // normal (< 75 °C)
|
||||
{ from: 750, to: 950, color: "rgba(215,165,49,0.14)" }, // high (75–95 °C)
|
||||
{ from: 950, to: 1250, color: "rgba(191,75,75,0.14)" } // critical (> 95 °C)
|
||||
];
|
||||
}
|
||||
if (key === "signal") {
|
||||
return [
|
||||
{ from:(-125 * 4), to:(-110 * 4), color:"rgba(191,75,75,0.14)" },
|
||||
@@ -2022,7 +2042,11 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
|
||||
function getTrendSeriesOrder(summaryPayload) {
|
||||
const sensors = summaryPayload && summaryPayload.sensors ? summaryPayload.sensors : null;
|
||||
const gpsEnabled = !!(sensors && sensors.gps_enabled === true);
|
||||
const mcuTempPresent = !!(sensors && Number.isFinite(sensors.mcu_temp_c));
|
||||
const order = ["battery", "memory", "signal", "noise_floor", "packets"];
|
||||
if (mcuTempPresent) {
|
||||
order.splice(2, 0, "mcu_temp");
|
||||
}
|
||||
if (gpsEnabled) {
|
||||
order.push("gps_satellites");
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user