diff --git a/application_events.json b/application_events.json
index ad23ecb..4eea360 100644
--- a/application_events.json
+++ b/application_events.json
@@ -3928,8 +3928,311 @@
"trigger_variable": null,
"auto_started": true
}
+ },
+ {
+ "timestamp": "2025-08-15T00:28:49.611975",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:29:11.885234",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:29:47.127915",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:33:00.587011",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:34:00.990295",
+ "level": "info",
+ "event_type": "application_started",
+ "message": "Application initialization completed successfully",
+ "details": {}
+ },
+ {
+ "timestamp": "2025-08-15T00:34:01.069801",
+ "level": "info",
+ "event_type": "dataset_activated",
+ "message": "Dataset activated: DAR",
+ "details": {
+ "dataset_id": "DAR",
+ "variables_count": 2,
+ "streaming_count": 2,
+ "prefix": "gateway_phoenix"
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:34:01.075470",
+ "level": "info",
+ "event_type": "dataset_activated",
+ "message": "Dataset activated: Fast",
+ "details": {
+ "dataset_id": "Fast",
+ "variables_count": 2,
+ "streaming_count": 1,
+ "prefix": "fast"
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:34:01.083475",
+ "level": "info",
+ "event_type": "csv_recording_started",
+ "message": "CSV recording started: 2 datasets activated",
+ "details": {
+ "activated_datasets": 2,
+ "total_datasets": 3
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:35:06.741557",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:35:28.675944",
+ "level": "info",
+ "event_type": "application_started",
+ "message": "Application initialization completed successfully",
+ "details": {}
+ },
+ {
+ "timestamp": "2025-08-15T00:35:28.758707",
+ "level": "info",
+ "event_type": "dataset_activated",
+ "message": "Dataset activated: DAR",
+ "details": {
+ "dataset_id": "DAR",
+ "variables_count": 2,
+ "streaming_count": 2,
+ "prefix": "gateway_phoenix"
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:35:28.764039",
+ "level": "info",
+ "event_type": "dataset_activated",
+ "message": "Dataset activated: Fast",
+ "details": {
+ "dataset_id": "Fast",
+ "variables_count": 2,
+ "streaming_count": 1,
+ "prefix": "fast"
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:35:28.768130",
+ "level": "info",
+ "event_type": "csv_recording_started",
+ "message": "CSV recording started: 2 datasets activated",
+ "details": {
+ "activated_datasets": 2,
+ "total_datasets": 3
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:35:39.619619",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:40:08.431291",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:40:14.468124",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:40:41.861858",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:40:45.084903",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:40:49.549459",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 500,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:41:19.890329",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 100,
+ "trigger_variable": null,
+ "auto_started": true
+ }
+ },
+ {
+ "timestamp": "2025-08-15T00:41:32.191310",
+ "level": "info",
+ "event_type": "plot_session_created",
+ "message": "Plot session 'UR29' created and started",
+ "details": {
+ "session_id": "plot_1",
+ "variables": [
+ "UR29_Brix",
+ "UR29_ma",
+ "AUX Blink_1.0S"
+ ],
+ "time_window": 3600,
+ "trigger_variable": null,
+ "auto_started": true
+ }
}
],
- "last_updated": "2025-08-15T00:27:40.211134",
- "total_entries": 360
+ "last_updated": "2025-08-15T00:41:32.191310",
+ "total_entries": 381
}
\ No newline at end of file
diff --git a/config/data/plot_definitions.json b/config/data/plot_definitions.json
index 65b829e..c0ada3e 100644
--- a/config/data/plot_definitions.json
+++ b/config/data/plot_definitions.json
@@ -2,12 +2,12 @@
"plots": [
{
"id": "plot_1",
- "line_tension": 0.1,
+ "line_tension": 0,
"name": "UR29",
"point_hover_radius": 4,
"point_radius": 0,
- "stepped": false,
- "time_window": 500,
+ "stepped": true,
+ "time_window": 3600,
"trigger_enabled": false,
"trigger_on_true": true,
"trigger_variable": null,
diff --git a/frontend/src/components/ChartjsPlot.jsx b/frontend/src/components/ChartjsPlot.jsx
index 390c943..d584638 100644
--- a/frontend/src/components/ChartjsPlot.jsx
+++ b/frontend/src/components/ChartjsPlot.jsx
@@ -67,6 +67,9 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
const [isRefreshing, setIsRefreshing] = useState(false);
const [isLoadingHistorical, setIsLoadingHistorical] = useState(false);
const resolvedConfigRef = useRef(null);
+
+ // Data preservation system for zoom operations
+ const dataBackupRef = useRef(new Map());
const bgColor = useColorModeValue('white', 'gray.800');
const textColor = useColorModeValue('gray.600', 'gray.300');
@@ -580,17 +583,55 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
},
...(zoomAvailable ? {
zoom: {
- // Solo habilitar zoom/pan en modo fullscreen
+ // Habilitar zoom/pan siempre, pero con configuraciΓ³n optimizada para streaming
pan: {
- enabled: !!session?.isFullscreen,
+ enabled: true,
mode: 'x',
- modifierKey: 'shift'
+ modifierKey: 'shift',
+ onPanComplete: function(context) {
+ // Preserve streaming state after pan
+ const chart = context.chart;
+ if (chart.options?.scales?.x?.realtime) {
+ const realtime = chart.options.scales.x.realtime;
+ // Ensure streaming continues after pan
+ if (!sessionDataRef.current.userPaused && !sessionDataRef.current.isPaused) {
+ realtime.pause = false;
+ }
+ }
+ }
},
zoom: {
- drag: { enabled: !!session?.isFullscreen },
- wheel: { enabled: !!session?.isFullscreen },
- pinch: { enabled: !!session?.isFullscreen },
- mode: 'x'
+ drag: {
+ enabled: true,
+ backgroundColor: 'rgba(128,128,128,0.3)'
+ },
+ wheel: {
+ enabled: true,
+ speed: 0.1
+ },
+ pinch: { enabled: true },
+ mode: 'x',
+ onZoomComplete: function(context) {
+ // Preserve streaming state and data after zoom
+ const chart = context.chart;
+ console.log('π Zoom completed, preserving streaming state...');
+
+ if (chart.options?.scales?.x?.realtime) {
+ const realtime = chart.options.scales.x.realtime;
+ // Don't auto-pause streaming after zoom
+ if (!sessionDataRef.current.userPaused && !sessionDataRef.current.isPaused) {
+ setTimeout(() => {
+ realtime.pause = false;
+ }, 10);
+ }
+ }
+ }
+ },
+ limits: {
+ x: {
+ min: 'original',
+ max: 'original'
+ }
}
}
} : {})
@@ -830,6 +871,18 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
// Update chart
if (pointsAdded > 0) {
chart.update('quiet');
+
+ // Backup data periodically when significant data is added
+ if (pointsAdded > 5 && dataBackupRef.current) {
+ const backup = chart.data.datasets.map(dataset => ({
+ label: dataset.label,
+ data: [...(dataset.data || [])],
+ timestamp: Date.now()
+ }));
+
+ dataBackupRef.current.set('current', backup);
+ console.log(`π¦ Data backed up: ${backup.reduce((total, ds) => total + ds.data.length, 0)} points`);
+ }
}
// Clear NaN insertion flag
@@ -982,17 +1035,78 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
if (!chartRef.current) return;
try {
+ console.log('π Resetting zoom...');
+
+ // Backup data before zoom reset
+ const backup = chartRef.current.data.datasets.map(dataset => ({
+ label: dataset.label,
+ data: [...(dataset.data || [])],
+ timestamp: Date.now()
+ }));
+
+ dataBackupRef.current.set('current', backup);
+ console.log(`π¦ Data backed up: ${backup.reduce((total, ds) => total + ds.data.length, 0)} points`);
+
+ // Store current streaming state
+ const realtimeOptions = chartRef.current.options?.scales?.x?.realtime;
+ const wasPaused = realtimeOptions?.pause || false;
+
// Try to reset zoom using the zoom plugin
if (chartRef.current.resetZoom) {
- chartRef.current.resetZoom();
+ chartRef.current.resetZoom('none'); // Use 'none' animation mode for faster reset
} else if (window.Chart?.helpers?.getRelativePosition) {
// Fallback: manually reset zoom by updating scale options
const chart = chartRef.current;
if (chart.options?.scales?.x?.realtime) {
- // For realtime charts, just trigger an update
+ // For realtime charts, reset the scale manually
+ const now = Date.now();
+ chart.options.scales.x.realtime.duration = chart.options.scales.x.realtime.duration || 60000;
+ chart.options.scales.x.min = now - chart.options.scales.x.realtime.duration;
+ chart.options.scales.x.max = now;
chart.update('none');
}
}
+
+ // Restore data if it was lost during zoom reset
+ setTimeout(() => {
+ if (chartRef.current && dataBackupRef.current.has('current')) {
+ const backupData = dataBackupRef.current.get('current');
+ const now = Date.now();
+
+ // Only restore if backup is recent (within 30 seconds)
+ if (now - backupData[0]?.timestamp <= 30000) {
+ let restored = false;
+ chartRef.current.data.datasets.forEach((dataset, index) => {
+ const backupDataset = backupData[index];
+ if (backupDataset && dataset.label === backupDataset.label) {
+ // Only restore if current data is significantly smaller
+ if (!dataset.data || dataset.data.length < backupDataset.data.length * 0.3) {
+ dataset.data = [...backupDataset.data];
+ restored = true;
+ }
+ }
+ });
+
+ if (restored) {
+ console.log('π Chart data restored from backup');
+ chartRef.current.update('none');
+
+ const totalPoints = chartRef.current.data.datasets.reduce((total, dataset) =>
+ total + (dataset.data?.length || 0), 0
+ );
+ setDataPointsCount(totalPoints);
+ }
+ }
+
+ // Restore streaming state
+ if (realtimeOptions && !wasPaused) {
+ realtimeOptions.pause = false;
+ }
+
+ console.log('β
Zoom reset with data preservation complete');
+ }
+ }, 100); // Small delay to ensure zoom reset is complete
+
} catch (error) {
console.warn('Failed to reset zoom:', error);
}
@@ -1339,6 +1453,35 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
)}
+ {/* Reset Zoom Button */}
+ {chartRef.current && (
+
+
+
+ )}
+