Skip to content

Commit c932c4e

Browse files
CMercsclaude
andcommitted
Disclose simulated data in System Health's Thermal and Sensors tabs
Both tabs rendered live-looking numbers with zero in-UI indication they were fake: SensorsTab's CPU temp/fan RPM/power draw graphs are random jitter with no EC read at all, and ThermalTab showed a hardcoded 42°C as "CPU TEMP" with nothing marking it as a placeholder. Both facts were already documented in code comments, but nowhere a user actually looking at the app would see them before trusting the numbers. Added a shared, non-dismissible SimulatedDataNotice banner (unlike LightingTab's confidence-caveat banner, this one shouldn't be dismissible — the values stay fake on every visit until real EC polling lands, not just the first time you see the warning) and relabeled the ThermalTab placeholder explicitly as "(placeholder)" in the UI itself, not just in a doc comment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent e23c6b5 commit c932c4e

3 files changed

Lines changed: 72 additions & 32 deletions

File tree

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
/**
3+
* Shared "this isn't real hardware data" banner for System Health tabs
4+
* that render live-looking numbers not actually wired to the EC yet.
5+
* Deliberately not dismissible, unlike LightingTab's confidence-caveat
6+
* banner: that one warns about label accuracy once; this one warns that
7+
* the values themselves are fabricated, which stays true every time the
8+
* tab renders until real EC polling replaces it — dismissing it once
9+
* shouldn't make it stop applying on a later visit.
10+
*/
11+
import type { ReactElement, ReactNode } from "react";
12+
import { AlertTriangle } from "lucide-react";
13+
14+
interface SimulatedDataNoticeProps {
15+
children: ReactNode;
16+
}
17+
18+
export function SimulatedDataNotice({ children }: SimulatedDataNoticeProps): ReactElement {
19+
return (
20+
<div className="flex items-start gap-2 mb-4 p-3 rounded-lg bg-yellow-500/10 border border-yellow-500/20 text-yellow-500 text-xs leading-relaxed">
21+
<AlertTriangle size={14} className="shrink-0 mt-0.5" />
22+
<span>{children}</span>
23+
</div>
24+
);
25+
}

MainFrame/src/pages/system/SensorsTab.tsx

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useEffect, useState } from "react";
88
import { useOutletContext } from "react-router-dom";
99
import { Thermometer, Fan, Zap } from "lucide-react";
1010
import { Card } from "../../components/ui/Card";
11+
import { SimulatedDataNotice } from "../../components/ui/SimulatedDataNotice";
1112
import { DriverGate } from "./DriverGate";
1213
import type { SystemHealthContext } from "./SystemHealth";
1314

@@ -64,36 +65,42 @@ export default function SensorsTab(): ReactElement {
6465
if (!ecAvailable) return <DriverGate />;
6566

6667
return (
67-
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
68-
{SENSORS.map((sensor) => {
69-
const series = history[sensor.id];
70-
const min = Math.min(...series);
71-
const max = Math.max(...series) || 1;
72-
const points = series
73-
.map((v, i) => {
74-
const x = (i / (series.length - 1)) * 100;
75-
const y = 40 - ((v - min) / (max - min || 1)) * 36 - 2;
76-
return `${x},${y}`;
77-
})
78-
.join(" ");
79-
const latest = series[series.length - 1];
68+
<div>
69+
<SimulatedDataNotice>
70+
These readings are <span className="font-medium">simulated</span> — random jitter around a
71+
baseline, not real EC telemetry. Don't make cooling or workload decisions based on them.
72+
</SimulatedDataNotice>
73+
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
74+
{SENSORS.map((sensor) => {
75+
const series = history[sensor.id];
76+
const min = Math.min(...series);
77+
const max = Math.max(...series) || 1;
78+
const points = series
79+
.map((v, i) => {
80+
const x = (i / (series.length - 1)) * 100;
81+
const y = 40 - ((v - min) / (max - min || 1)) * 36 - 2;
82+
return `${x},${y}`;
83+
})
84+
.join(" ");
85+
const latest = series[series.length - 1];
8086

81-
return (
82-
<Card key={sensor.id} className="p-5">
83-
<div className="flex items-center gap-2 mb-3">
84-
<sensor.icon size={16} style={{ color: sensor.color }} />
85-
<span className="text-xs text-gray-400 uppercase tracking-wider">{sensor.label}</span>
86-
</div>
87-
<div className="text-2xl font-mono text-white mb-2">
88-
{latest.toFixed(sensor.id === "fan_rpm" ? 0 : 1)}
89-
<span className="text-sm text-gray-400">{sensor.unit}</span>
90-
</div>
91-
<svg viewBox="0 0 100 40" className="w-full h-10" preserveAspectRatio="none">
92-
<polyline points={points} fill="none" stroke={sensor.color} strokeWidth="1.5" vectorEffect="non-scaling-stroke" />
93-
</svg>
94-
</Card>
95-
);
96-
})}
87+
return (
88+
<Card key={sensor.id} className="p-5">
89+
<div className="flex items-center gap-2 mb-3">
90+
<sensor.icon size={16} style={{ color: sensor.color }} />
91+
<span className="text-xs text-gray-400 uppercase tracking-wider">{sensor.label}</span>
92+
</div>
93+
<div className="text-2xl font-mono text-white mb-2">
94+
{latest.toFixed(sensor.id === "fan_rpm" ? 0 : 1)}
95+
<span className="text-sm text-gray-400">{sensor.unit}</span>
96+
</div>
97+
<svg viewBox="0 0 100 40" className="w-full h-10" preserveAspectRatio="none">
98+
<polyline points={points} fill="none" stroke={sensor.color} strokeWidth="1.5" vectorEffect="non-scaling-stroke" />
99+
</svg>
100+
</Card>
101+
);
102+
})}
103+
</div>
97104
</div>
98105
);
99106
}

MainFrame/src/pages/system/ThermalTab.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { useRef, useState } from "react";
88
import { useOutletContext } from "react-router-dom";
99
import { Activity } from "lucide-react";
1010
import { Card } from "../../components/ui/Card";
11+
import { SimulatedDataNotice } from "../../components/ui/SimulatedDataNotice";
1112
import { DriverGate } from "./DriverGate";
1213
import type { SystemHealthContext } from "./SystemHealth";
1314

@@ -60,19 +61,26 @@ export default function ThermalTab(): ReactElement {
6061
setCurve((prev) => prev.map((p, i) => (i === dragIndex ? { ...p, dutyPct } : p)));
6162
};
6263

63-
const currentTemp = 42;
64-
const currentDuty = curve.reduce((acc, p) => (currentTemp >= p.tempC ? p.dutyPct : acc), curve[0].dutyPct);
64+
// Fixed placeholder, not a live reading — see the SimulatedDataNotice
65+
// rendered below. Only used to preview where the curve's current duty
66+
// point falls; not shown as CPU temp anywhere in the UI.
67+
const placeholderTemp = 42;
68+
const currentDuty = curve.reduce((acc, p) => (placeholderTemp >= p.tempC ? p.dutyPct : acc), curve[0].dutyPct);
6569

6670
return (
6771
<Card className="p-6 h-full flex flex-col">
72+
<SimulatedDataNotice>
73+
This curve isn't wired to the EC yet — dragging points previews the shape only. The temp
74+
and RPM readout on the right is a fixed placeholder, not a live reading.
75+
</SimulatedDataNotice>
6876
<div className="flex items-center justify-between mb-6">
6977
<div className="flex items-center gap-3">
7078
<div className="p-2 bg-blue-500/10 rounded-lg text-blue-400">
7179
<Activity size={20} />
7280
</div>
7381
<div>
7482
<h3 className="text-white font-bold">Fan Curve</h3>
75-
<div className="text-xs text-gray-400">CPU TEMP: {currentTemp}&deg;C</div>
83+
<div className="text-xs text-gray-400">CPU TEMP: {placeholderTemp}&deg;C (placeholder)</div>
7684
</div>
7785
</div>
7886
<div className="text-right">

0 commit comments

Comments
 (0)