diff --git a/templates/partials/slm_live_view.html b/templates/partials/slm_live_view.html
index e9d8a0f..70ceefb 100644
--- a/templates/partials/slm_live_view.html
+++ b/templates/partials/slm_live_view.html
@@ -513,7 +513,37 @@ if (typeof window.currentWebSocket === 'undefined') {
window.currentWebSocket = null;
}
-function initLiveDataStream(unitId) {
+// Backfill the chart with the recent DOD trail so it opens with context.
+async function backfillChart(unitId) {
+ try {
+ const r = await fetch(`/api/slmm/${encodeURIComponent(unitId)}/history?hours=2`);
+ if (!r.ok) return;
+ const d = await r.json();
+ const readings = d.readings || [];
+ if (!window.chartData) return;
+ for (const row of readings) {
+ // Trail timestamps are naive UTC; append 'Z' so they convert to local
+ // consistently with the live frames (which use local Date.now()).
+ window.chartData.timestamps.push(row.timestamp ? new Date(row.timestamp + 'Z').toLocaleTimeString() : '');
+ window.chartData.lp.push(parseFloat(row.lp || 0));
+ window.chartData.leq.push(parseFloat(row.leq || 0));
+ window.chartData.ln1.push(parseFloat(row.ln1 || 0));
+ window.chartData.ln2.push(parseFloat(row.ln2 || 0));
+ }
+ if (window.liveChart) {
+ window.liveChart.data.labels = window.chartData.timestamps;
+ window.liveChart.data.datasets[0].data = window.chartData.lp;
+ window.liveChart.data.datasets[1].data = window.chartData.leq;
+ window.liveChart.data.datasets[2].data = window.chartData.ln1;
+ window.liveChart.data.datasets[3].data = window.chartData.ln2;
+ window.liveChart.update('none');
+ }
+ } catch (e) {
+ console.warn('Chart backfill failed:', e);
+ }
+}
+
+async function initLiveDataStream(unitId) {
// Close existing connection if any
if (window.currentWebSocket) {
window.currentWebSocket.close();
@@ -533,6 +563,10 @@ function initLiveDataStream(unitId) {
window.liveChart.update();
}
+ // Seed the chart with recent history BEFORE opening the live socket, so live
+ // frames append after the backfill (right order) and the chart isn't blank.
+ await backfillChart(unitId);
+
// WebSocket URL for SLMM backend via proxy.
// /monitor = the shared fan-out DOD feed (many viewers, one device connection,
// and it carries L1/L10 which the DRD /stream cannot).
@@ -649,8 +683,9 @@ function updateLiveChart(data) {
window.chartData.ln1.push(parseFloat(data.ln1 || 0));
window.chartData.ln2.push(parseFloat(data.ln2 || 0));
- // Keep only last 60 data points
- if (window.chartData.timestamps.length > 60) {
+ // Keep a rolling window large enough to hold the ~2h backfill (one point/min)
+ // plus a good run of live points before the oldest scroll off.
+ if (window.chartData.timestamps.length > 600) {
window.chartData.timestamps.shift();
window.chartData.lp.shift();
window.chartData.leq.shift();