feat: Enhance event logging for plot sessions, improve zoom functionality, and update dataset configurations

This commit is contained in:
Miguel 2025-08-15 11:01:20 +02:00
parent 438ebc1462
commit addd9fa6bc
5 changed files with 322 additions and 67 deletions

View File

@ -4357,8 +4357,183 @@
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:55:29.278884",
"level": "info",
"event_type": "plot_session_created",
"message": "Plot session 'Clock' created and started",
"details": {
"session_id": "Clock",
"variables": [
"AUX Blink_1.0S",
"AUX Blink_1.6S"
],
"time_window": 60,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:56:04.171748",
"level": "info",
"event_type": "plot_session_created",
"message": "Plot session 'Clock' created and started",
"details": {
"session_id": "Clock",
"variables": [
"AUX Blink_1.0S",
"AUX Blink_1.6S"
],
"time_window": 60,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:56:33.247778",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-15T00:56:33.360494",
"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:56:33.369004",
"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:56:33.375426",
"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:56:43.455835",
"level": "info",
"event_type": "plot_session_created",
"message": "Plot session 'Clock' created and started",
"details": {
"session_id": "Clock",
"variables": [
"AUX Blink_1.0S",
"AUX Blink_1.6S"
],
"time_window": 60,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:56:50.145968",
"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": 360,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:57:04.660061",
"level": "info",
"event_type": "plot_session_created",
"message": "Plot session 'Clock' created and started",
"details": {
"session_id": "Clock",
"variables": [
"AUX Blink_1.0S",
"AUX Blink_1.6S"
],
"time_window": 60,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T00:57:09.226184",
"level": "info",
"event_type": "plot_session_created",
"message": "Plot session 'Clock' created and started",
"details": {
"session_id": "Clock",
"variables": [
"AUX Blink_1.0S",
"AUX Blink_1.6S"
],
"time_window": 60,
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-08-15T10:44:49.036843",
"level": "info",
"event_type": "datasets_resumed_after_reconnection",
"message": "Automatically resumed streaming for 2 datasets after PLC reconnection",
"details": {
"resumed_datasets": 2,
"total_attempted": 2
}
},
{
"timestamp": "2025-08-15T10:45:35.434594",
"level": "info",
"event_type": "datasets_resumed_after_reconnection",
"message": "Automatically resumed streaming for 2 datasets after PLC reconnection",
"details": {
"resumed_datasets": 2,
"total_attempted": 2
}
},
{
"timestamp": "2025-08-15T10:47:54.448887",
"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": 36,
"trigger_variable": null,
"auto_started": true
}
}
],
"last_updated": "2025-08-15T00:53:37.664354",
"total_entries": 390
"last_updated": "2025-08-15T10:47:54.448887",
"total_entries": 403
}

View File

@ -7,12 +7,23 @@
"point_hover_radius": 4,
"point_radius": 0,
"stepped": true,
"time_window": 360,
"time_window": 36,
"trigger_enabled": false,
"trigger_on_true": true,
"trigger_variable": null,
"y_max": null,
"y_min": null
},
{
"id": "Clock",
"line_tension": 0,
"name": "Clock",
"point_hover_radius": 4,
"point_radius": 1,
"stepped": true,
"time_window": 60,
"trigger_enabled": false,
"trigger_on_true": true
}
]
}

View File

@ -4,26 +4,45 @@
"plot_id": "plot_1",
"variables": [
{
"variable_name": "UR29_Brix",
"label": "Brix",
"color": "#3498db",
"enabled": true,
"label": "Brix",
"line_width": 2,
"y_axis": "left",
"enabled": true
"variable_name": "UR29_Brix",
"y_axis": "left"
},
{
"variable_name": "UR29_ma",
"label": "ma",
"color": "#dce740",
"enabled": true,
"label": "ma",
"line_width": 2,
"y_axis": "left",
"enabled": true
"variable_name": "UR29_ma",
"y_axis": "left"
},
{
"color": "#3498db",
"enabled": true,
"line_width": 2,
"variable_name": "AUX Blink_1.0S",
"y_axis": "right"
}
]
},
{
"plot_id": "Clock",
"variables": [
{
"variable_name": "AUX Blink_1.0S",
"color": "#3498db",
"line_width": 2,
"y_axis": "right",
"y_axis": "left",
"enabled": true
},
{
"variable_name": "AUX Blink_1.6S",
"color": "#87db33",
"line_width": 2,
"y_axis": "left",
"enabled": true
}
]

View File

@ -1,5 +1,5 @@
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { Box, Text, useColorModeValue } from '@chakra-ui/react';
import { Box, Text, Switch, FormLabel, HStack, useColorModeValue } from '@chakra-ui/react';
// Global dependencies check - run once
let dependenciesChecked = false;
@ -66,11 +66,9 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
const [dataPointsCount, setDataPointsCount] = useState(0);
const [isRefreshing, setIsRefreshing] = useState(false);
const [isLoadingHistorical, setIsLoadingHistorical] = useState(false);
const [isZoomEnabled, setIsZoomEnabled] = useState(true);
const resolvedConfigRef = useRef(null);
// Data preservation system for zoom operations
const dataBackupRef = useRef(new Map());
// Chart health monitoring
const chartHealthRef = useRef({
lastDataTimestamp: 0,
@ -238,7 +236,6 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
sessionId: session?.session_id,
sessionActive: session?.is_active,
sessionPaused: session?.is_paused,
dataBackupSize: dataBackupRef.current.size,
health: chartHealthRef.current,
datasets: chartRef.current?.data?.datasets?.length || 0,
realtimeConfig: !!chartRef.current?.options?.scales?.x?.realtime
@ -615,7 +612,6 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
// Sort points by timestamp to ensure proper order
historicalPoints.sort((a, b) => a.x - b.x);
datasets[index].data = historicalPoints;
console.log(`📊 Added ${historicalPoints.length} historical points for ${variableInfo.name}`);
}
});
@ -698,9 +694,9 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
},
...(zoomAvailable ? {
zoom: {
// Habilitar zoom/pan siempre, pero con configuración optimizada para streaming
// Enable/disable zoom/pan based on switch state
pan: {
enabled: true,
enabled: isZoomEnabled,
mode: 'x',
modifierKey: 'shift',
onPanComplete: function(context) {
@ -717,14 +713,14 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
},
zoom: {
drag: {
enabled: true,
enabled: isZoomEnabled,
backgroundColor: 'rgba(128,128,128,0.3)'
},
wheel: {
enabled: true,
enabled: isZoomEnabled,
speed: 0.1
},
pinch: { enabled: true },
pinch: { enabled: isZoomEnabled },
mode: 'x',
onZoomComplete: function(context) {
// Preserve streaming state and data after zoom
@ -848,7 +844,7 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
setError(error.message);
setIsLoading(false);
}
}, []);
}, [isZoomEnabled]);
const onStreamingRefresh = useCallback(async (chart) => {
const sessionId = sessionDataRef.current.sessionId;
@ -875,10 +871,6 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
const pointsAdded = addNewDataToStreaming(plotData, now);
updatePointsCounter(plotData);
if (pointsAdded > 0) {
console.log(`📊 Plot ${sessionId}: Added ${pointsAdded} points to chart`);
}
// Auto-pause when no data arrives for several cycles; resume when data appears
if (pointsAdded > 0) {
sessionDataRef.current.noDataCycles = 0;
@ -990,18 +982,6 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
// Update health monitoring
chartHealthRef.current.lastDataTimestamp = Date.now();
chartHealthRef.current.consecutiveErrors = 0;
// 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`);
}
} else {
// No new data received - increment error counter
chartHealthRef.current.consecutiveErrors++;
@ -1113,7 +1093,6 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
// Sort points by timestamp to ensure proper order
historicalPoints.sort((a, b) => a.x - b.x);
chart.data.datasets[index].data = historicalPoints;
console.log(`📊 Added ${historicalPoints.length} historical points for ${variableInfo.name} on start`);
}
});
@ -1206,9 +1185,45 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
// Get current time window (use same as initial load)
const timeWindow = cfg.time_window || 3600; // Default 1 hour
const variableNames = enabledVariables.map(v => v.name);
// Load fresh historical data
await loadHistoricalData(enabledVariables, timeWindow);
const historicalData = await loadHistoricalData(variableNames, timeWindow);
if (historicalData.length > 0) {
console.log(`📊 Loaded ${historicalData.length} historical data points for reset`);
// Group data by variable and add to appropriate dataset
const dataByVariable = {};
historicalData.forEach(point => {
const { variable, timestamp, value } = point;
if (!dataByVariable[variable]) {
dataByVariable[variable] = [];
}
dataByVariable[variable].push({
x: new Date(timestamp),
y: value
});
});
// Add historical data to datasets
enabledVariables.forEach((variableInfo, index) => {
const historicalPoints = dataByVariable[variableInfo.name] || [];
if (historicalPoints.length > 0) {
// Sort points by timestamp to ensure proper order
historicalPoints.sort((a, b) => a.x - b.x);
chartRef.current.data.datasets[index].data = historicalPoints;
}
});
// Update chart with historical data
chartRef.current.update('quiet');
// Update data points counter
const totalHistoricalPoints = Object.values(dataByVariable).reduce((sum, points) => sum + points.length, 0);
setDataPointsCount(totalHistoricalPoints);
}
console.log('✅ Historical data reloaded');
}
@ -1348,6 +1363,27 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
}
}, [session?.isFullscreen, createStreamingChart]);
// Update zoom configuration when zoom enabled state changes
useEffect(() => {
if (!chartRef.current) return;
const chart = chartRef.current;
const zoomPlugin = chart.options?.plugins?.zoom;
if (zoomPlugin) {
// Update zoom configuration dynamically
zoomPlugin.pan.enabled = isZoomEnabled;
zoomPlugin.zoom.drag.enabled = isZoomEnabled;
zoomPlugin.zoom.wheel.enabled = isZoomEnabled;
zoomPlugin.zoom.pinch.enabled = isZoomEnabled;
// Update the chart to apply the new configuration
chart.update('none');
console.log(`🔍 Zoom/Pan ${isZoomEnabled ? 'enabled' : 'disabled'}`);
}
}, [isZoomEnabled]);
// Periodic health monitoring
useEffect(() => {
if (!session?.session_id || !chartRef.current) return;
@ -1569,24 +1605,35 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
📊 Loading historical data...
</Box>
)}
{/* Data points counter */}
{dataPointsCount > 0 && (
<Box
position="absolute"
top={2}
left={2}
bg="green.500"
color="white"
px={2}
py={1}
borderRadius="md"
fontSize="xs"
zIndex={10}
>
📈 {dataPointsCount} points
</Box>
)}
{/* Zoom/Pan Toggle Switch */}
<HStack
position="absolute"
top={2}
left={2}
bg="rgba(255, 255, 255, 0.95)"
backdropFilter="blur(8px)"
borderWidth="1px"
borderColor="gray.200"
px={3}
py={2}
borderRadius="lg"
fontSize="xs"
zIndex={10}
spacing={2}
shadow="sm"
>
<FormLabel htmlFor="zoom-switch" mb={0} fontSize="xs" color="gray.700" fontWeight="medium">
🔍 Zoom/Pan
</FormLabel>
<Switch
id="zoom-switch"
size="sm"
isChecked={isZoomEnabled}
onChange={(e) => setIsZoomEnabled(e.target.checked)}
colorScheme="blue"
/>
</HStack>
{/* Reset Zoom Button */}
{chartRef.current && (
@ -1676,16 +1723,19 @@ const ChartjsPlot = ({ session, height = '400px' }) => {
{/* Points counter */}
<Box
position="absolute"
top={2}
top={isLoadingHistorical ? 12 : 2}
right={2}
bg="rgba(0,0,0,0.7)"
bg="rgba(0,0,0,0.75)"
color="white"
px={2}
py={1}
borderRadius="sm"
borderRadius="md"
fontSize="xs"
fontWeight="medium"
shadow="sm"
zIndex={5}
>
Points: {dataPointsCount}
📊 {dataPointsCount} points
</Box>
</Box>
);

View File

@ -3,11 +3,11 @@
"should_connect": true,
"should_stream": false,
"active_datasets": [
"DAR",
"Fast",
"Test"
"Test",
"DAR"
]
},
"auto_recovery_enabled": true,
"last_update": "2025-08-15T00:46:30.361074"
"last_update": "2025-08-15T00:56:33.380433"
}