Actualización de eventos en application_events.json para mejorar la gestión de sesiones de plot y el sistema de streaming. Se ajustaron las fechas de última actualización en varios archivos de configuración. Se eliminaron scripts de depuración y pruebas para simplificar el código y mejorar la claridad del sistema. Además, se realizaron ajustes en la interfaz de usuario en index.html para reflejar estos cambios.

This commit is contained in:
Miguel 2025-08-03 10:28:26 +02:00
parent 55c4e67cf7
commit 8c6f3b5534
13 changed files with 166 additions and 926 deletions

View File

@ -4584,8 +4584,163 @@
"trigger_variable": null,
"auto_started": true
}
},
{
"timestamp": "2025-07-28T11:17:42.259176",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-07-28T11:17:42.298212",
"level": "info",
"event_type": "dataset_activated",
"message": "Dataset activated: DAR",
"details": {
"dataset_id": "dar",
"variables_count": 6,
"streaming_count": 4,
"prefix": "dar"
}
},
{
"timestamp": "2025-07-28T11:17:42.303189",
"level": "info",
"event_type": "csv_recording_started",
"message": "CSV recording started: 1 datasets activated",
"details": {
"activated_datasets": 1,
"total_datasets": 2
}
},
{
"timestamp": "2025-07-28T11:17:57.447529",
"level": "info",
"event_type": "csv_recording_stopped",
"message": "CSV recording stopped (dataset threads continue for UDP streaming)",
"details": {}
},
{
"timestamp": "2025-07-28T11:17:57.454697",
"level": "info",
"event_type": "udp_streaming_stopped",
"message": "UDP streaming to PlotJuggler stopped (CSV recording continues)",
"details": {}
},
{
"timestamp": "2025-07-28T11:17:57.540554",
"level": "info",
"event_type": "dataset_deactivated",
"message": "Dataset deactivated: DAR",
"details": {
"dataset_id": "dar"
}
},
{
"timestamp": "2025-07-28T11:17:57.548515",
"level": "info",
"event_type": "plc_disconnection",
"message": "Disconnected from PLC 10.1.33.11 (stopped recording and streaming)",
"details": {}
},
{
"timestamp": "2025-07-28T11:18:01.820757",
"level": "error",
"event_type": "udp_streaming_error",
"message": "Cannot start UDP streaming: PLC not connected",
"details": {}
},
{
"timestamp": "2025-07-28T11:18:07.200757",
"level": "info",
"event_type": "dataset_activated",
"message": "Dataset activated: DAR",
"details": {
"dataset_id": "dar",
"variables_count": 6,
"streaming_count": 4,
"prefix": "dar"
}
},
{
"timestamp": "2025-07-28T11:18:07.212573",
"level": "info",
"event_type": "csv_recording_started",
"message": "CSV recording started: 1 datasets activated",
"details": {
"activated_datasets": 1,
"total_datasets": 2
}
},
{
"timestamp": "2025-07-28T11:18:07.224850",
"level": "info",
"event_type": "plc_connection",
"message": "Successfully connected to PLC 10.1.33.11 and auto-started CSV recording for 1 datasets",
"details": {
"ip": "10.1.33.11",
"rack": 0,
"slot": 2,
"auto_started_recording": true,
"recording_datasets": 1,
"dataset_names": [
"DAR"
]
}
},
{
"timestamp": "2025-07-28T11:18:46.822611",
"level": "info",
"event_type": "udp_streaming_started",
"message": "UDP streaming to PlotJuggler started",
"details": {
"udp_host": "127.0.0.1",
"udp_port": 9870,
"datasets_available": 1
}
},
{
"timestamp": "2025-08-03T10:18:29.942128",
"level": "info",
"event_type": "application_started",
"message": "Application initialization completed successfully",
"details": {}
},
{
"timestamp": "2025-08-03T10:18:30.069067",
"level": "info",
"event_type": "dataset_activated",
"message": "Dataset activated: DAR",
"details": {
"dataset_id": "dar",
"variables_count": 6,
"streaming_count": 4,
"prefix": "dar"
}
},
{
"timestamp": "2025-08-03T10:18:30.076657",
"level": "info",
"event_type": "csv_recording_started",
"message": "CSV recording started: 1 datasets activated",
"details": {
"activated_datasets": 1,
"total_datasets": 2
}
},
{
"timestamp": "2025-08-03T10:18:30.085275",
"level": "info",
"event_type": "udp_streaming_started",
"message": "UDP streaming to PlotJuggler started",
"details": {
"udp_host": "127.0.0.1",
"udp_port": 9870,
"datasets_available": 1
}
}
],
"last_updated": "2025-07-21T18:38:00.731968",
"total_entries": 436
"last_updated": "2025-08-03T10:18:30.085275",
"total_entries": 452
}

View File

@ -16,6 +16,6 @@
"max_days": 30,
"max_hours": null,
"cleanup_interval_hours": 24,
"last_cleanup": "2025-07-20T23:49:17.540633"
"last_cleanup": "2025-08-03T10:18:30.271685"
}
}

View File

@ -70,5 +70,5 @@
],
"current_dataset_id": "dar",
"version": "1.0",
"last_update": "2025-07-21T18:34:08.728102"
"last_update": "2025-08-03T10:18:30.067100"
}

View File

@ -1,387 +0,0 @@
/**
* 🔧 Script de Diagnóstico Detallado para Chart.js Streaming
* Ejecutar en consola del navegador para identificar el problema exacto
*/
// Función principal de diagnóstico
window.diagnoseStreamingIssue = async function () {
console.log('🔧 DIAGNÓSTICO DETALLADO DE STREAMING');
console.log('='.repeat(60));
const results = {
librariesLoaded: false,
plotManagerReady: false,
sessionExists: false,
backendData: null,
chartConfig: null,
streamingWorking: false,
errors: []
};
try {
// 1. Verificar librerías básicas
console.log('\n1⃣ VERIFICANDO LIBRERÍAS...');
results.librariesLoaded = {
chartjs: typeof Chart !== 'undefined',
chartStreaming: typeof window.ChartStreaming !== 'undefined',
plotManager: typeof plotManager !== 'undefined'
};
console.log('Chart.js:', results.librariesLoaded.chartjs ? '✅' : '❌');
console.log('ChartStreaming:', results.librariesLoaded.chartStreaming ? '✅' : '❌');
console.log('PlotManager:', results.librariesLoaded.plotManager ? '✅' : '❌');
if (!results.librariesLoaded.chartStreaming) {
results.errors.push('ChartStreaming plugin no está cargado');
console.error('❌ ChartStreaming plugin no está disponible');
return results;
}
// 2. Verificar PlotManager
console.log('\n2⃣ VERIFICANDO PLOT MANAGER...');
const pm = window.plotManager || plotManager;
if (pm && pm.sessions) {
results.plotManagerReady = true;
console.log('✅ PlotManager inicializado');
console.log('📊 Sesiones activas:', pm.sessions.size);
if (pm.sessions.size === 0) {
console.log('⚠️ No hay sesiones de plot activas');
console.log('💡 Crea un nuevo plot para continuar el diagnóstico');
return results;
}
} else {
results.errors.push('PlotManager no está inicializado');
console.error('❌ PlotManager no está disponible');
console.log('💡 Tip: Espera unos segundos e intenta de nuevo, plotManager podría estar inicializándose');
return results;
}
// 3. Verificar sesión específica
console.log('\n3⃣ ANALIZANDO SESIÓN DE PLOT...');
const sessionId = Array.from(pm.sessions.keys())[0];
const sessionData = pm.sessions.get(sessionId);
if (sessionData) {
results.sessionExists = true;
console.log(`📈 Sesión encontrada: ${sessionId}`);
// Verificar configuración del chart
results.chartConfig = {
hasChart: !!sessionData.chart,
chartType: sessionData.chart?.config?.type,
scaleType: sessionData.chart?.scales?.x?.type,
scaleConstructor: sessionData.chart?.scales?.x?.constructor?.name,
streamingEnabled: !!sessionData.chart?.$streaming?.enabled,
datasets: sessionData.chart?.data?.datasets?.length || 0,
dataPoints: sessionData.chart?.data?.datasets?.reduce((total, d) => total + (d.data?.length || 0), 0) || 0
};
console.log('Chart Config:', results.chartConfig);
// Verificar si la escala es realtime
if (results.chartConfig.scaleType !== 'realtime') {
results.errors.push('La escala X no es de tipo realtime');
console.error('❌ Escala X no es realtime:', results.chartConfig.scaleType);
} else {
console.log('✅ Escala realtime configurada correctamente');
}
// Verificar streaming
if (!results.chartConfig.streamingEnabled) {
results.errors.push('Streaming no está habilitado en el chart');
console.error('❌ Streaming no está habilitado');
} else {
console.log('✅ Streaming habilitado en el chart');
}
}
// 4. Verificar datos del backend
console.log('\n4⃣ VERIFICANDO DATOS DEL BACKEND...');
try {
const response = await fetch(`/api/plots/${sessionId}/data`);
results.backendData = await response.json();
console.log('📊 Respuesta del backend:', {
success: !!results.backendData.datasets,
datasets: results.backendData.datasets?.length || 0,
totalPoints: results.backendData.data_points_count || 0,
isActive: results.backendData.is_active,
isPaused: results.backendData.is_paused
});
if (results.backendData.datasets && results.backendData.datasets.length > 0) {
console.log('✅ Backend devuelve datos');
// Verificar estructura de datos
const firstDataset = results.backendData.datasets[0];
console.log('📈 Primer dataset:', {
label: firstDataset.label,
dataPoints: firstDataset.data?.length || 0,
samplePoint: firstDataset.data?.[0]
});
if (firstDataset.data && firstDataset.data.length > 0) {
console.log('✅ Dataset tiene puntos de datos');
// Verificar formato de timestamps
const firstPoint = firstDataset.data[0];
const currentTime = Date.now();
const timeDiff = Math.abs(currentTime - firstPoint.x);
console.log('⏰ Análisis de timestamps:', {
firstPointTime: firstPoint.x,
currentTime: currentTime,
differenceMs: timeDiff,
differenceSec: Math.round(timeDiff / 1000),
isRecent: timeDiff < 300000 // 5 minutos
});
if (timeDiff > 300000) {
results.errors.push('Los timestamps de los datos son muy antiguos');
console.warn('⚠️ Los datos parecen ser muy antiguos');
}
} else {
results.errors.push('El dataset no tiene puntos de datos');
console.error('❌ El dataset está vacío');
}
} else {
results.errors.push('Backend no devuelve datasets');
console.error('❌ Backend no devuelve datos válidos');
}
} catch (error) {
results.errors.push(`Error al obtener datos del backend: ${error.message}`);
console.error('❌ Error del backend:', error);
}
// 5. Test de funcionalidad streaming
console.log('\n5⃣ PROBANDO FUNCIONALIDAD STREAMING...');
if (sessionData && sessionData.chart && results.backendData) {
try {
// Intentar agregar un punto de prueba
const testResult = window.ChartStreaming.addStreamingData(sessionData.chart, 0, {
x: Date.now(),
y: Math.random() * 100
});
console.log('🧪 Test de addStreamingData:', testResult ? '✅' : '❌');
if (testResult) {
// Verificar si el punto se agregó
const currentDataPoints = sessionData.chart.data.datasets[0]?.data?.length || 0;
console.log('📊 Puntos después del test:', currentDataPoints);
results.streamingWorking = currentDataPoints > 0;
} else {
results.errors.push('addStreamingData falló');
}
} catch (error) {
results.errors.push(`Error en test de streaming: ${error.message}`);
console.error('❌ Error en test de streaming:', error);
}
}
// 6. Resumen final
console.log('\n6⃣ RESUMEN DEL DIAGNÓSTICO');
console.log('='.repeat(40));
if (results.errors.length === 0) {
console.log('🎉 No se encontraron errores graves');
if (!results.streamingWorking) {
console.log('⚠️ Sin embargo, el streaming no parece estar funcionando');
console.log('💡 Intenta: forceStreamingUpdate()');
}
} else {
console.log('❌ Errores encontrados:');
results.errors.forEach((error, index) => {
console.log(` ${index + 1}. ${error}`);
});
}
// 7. Recomendaciones
console.log('\n7⃣ PRÓXIMOS PASOS RECOMENDADOS:');
if (!results.librariesLoaded.chartStreaming) {
console.log('🔧 1. Recargar la página para asegurar que el plugin se carga');
}
if (results.errors.some(e => e.includes('timestamp'))) {
console.log('🔧 2. Ejecutar clearStreamingData() y reiniciar el plot');
}
if (results.backendData && !results.streamingWorking) {
console.log('🔧 3. Ejecutar enablePlotDebug() y forceStreamingUpdate()');
}
console.log('🔧 4. Si persiste: plotManager.controlPlot("' + sessionId + '", "stop") y luego "start"');
return results;
} catch (error) {
console.error('💥 Error durante el diagnóstico:', error);
results.errors.push(`Error fatal: ${error.message}`);
return results;
}
};
// Función para limpiar y reiniciar streaming
window.resetStreaming = function (sessionId = null) {
console.log('🔄 REINICIANDO STREAMING...');
const pm = window.plotManager || plotManager;
if (!pm || !pm.sessions) {
console.error('❌ PlotManager no disponible');
return false;
}
const targetSessionId = sessionId || Array.from(pm.sessions.keys())[0];
if (!targetSessionId) {
console.error('❌ No hay sesiones disponibles');
return false;
}
console.log(`🔄 Reiniciando sesión: ${targetSessionId}`);
try {
// 1. Limpiar datos existentes
if (pm.clearStreamingData) {
pm.clearStreamingData(targetSessionId);
console.log('✅ Datos de streaming limpiados');
}
// 2. Pausar y reiniciar
pm.controlPlot(targetSessionId, 'stop');
console.log('⏹️ Plot detenido');
setTimeout(() => {
pm.controlPlot(targetSessionId, 'start');
console.log('▶️ Plot reiniciado');
// 3. Forzar actualización después de un momento
setTimeout(() => {
if (pm.refreshStreamingData) {
const sessionData = pm.sessions.get(targetSessionId);
if (sessionData?.chart) {
pm.refreshStreamingData(targetSessionId, sessionData.chart);
console.log('🔄 Actualización forzada');
}
}
}, 1000);
}, 500);
return true;
} catch (error) {
console.error('❌ Error al reiniciar streaming:', error);
return false;
}
};
// Función de test rápido
window.quickStreamingTest = function () {
console.log('⚡ TEST RÁPIDO DE STREAMING');
console.log('-'.repeat(30));
const pm = window.plotManager || plotManager;
const checks = {
plotManager: !!pm,
sessions: pm?.sessions?.size || 0,
chartStreaming: !!window.ChartStreaming
};
Object.entries(checks).forEach(([key, value]) => {
console.log(`${key}: ${value ? '✅' : '❌'} ${value}`);
});
if (checks.sessions > 0) {
const sessionId = Array.from(pm.sessions.keys())[0];
console.log(`\n🧪 Probando sesión: ${sessionId}`);
// Ejecutar diagnóstico completo
return diagnoseStreamingIssue();
} else {
console.log('\n💡 Crea un plot primero, luego ejecuta: quickStreamingTest()');
return false;
}
};
// Función específica para diagnosticar el onRefresh callback
window.diagnoseOnRefreshIssue = function () {
console.log('🔧 DIAGNÓSTICO ESPECÍFICO DEL ONREFRESH CALLBACK');
console.log('='.repeat(50));
const pm = window.plotManager || plotManager;
if (!pm || !pm.sessions) {
console.error('❌ PlotManager no disponible');
console.log('💡 Tip: Espera unos segundos e intenta de nuevo');
return;
}
if (pm.sessions.size === 0) {
console.log('⚠️ No hay sesiones activas. Crea un plot primero.');
return;
}
const sessionId = Array.from(pm.sessions.keys())[0];
const sessionData = pm.sessions.get(sessionId);
if (!sessionData || !sessionData.chart) {
console.error('❌ No se encuentra el chart para la sesión');
return;
}
const chart = sessionData.chart;
const realTimeScale = chart.scales.x;
console.log('📊 Información del Chart:');
console.log('- Chart existe:', !!chart);
console.log('- Chart type:', chart.config.type);
console.log('- Chart scales:', Object.keys(chart.scales));
console.log('\n📈 Información de la Escala RealTime:');
console.log('- Scale type:', realTimeScale.type);
console.log('- Scale constructor:', realTimeScale.constructor.name);
console.log('- Scale options:', realTimeScale.options);
console.log('- Scale realtime options:', realTimeScale.options.realtime);
if (realTimeScale.realtime) {
console.log('\n⚙ Configuración RealTime:');
console.log('- Duration:', realTimeScale.realtime.duration);
console.log('- Refresh:', realTimeScale.realtime.refresh);
console.log('- Pause:', realTimeScale.realtime.pause);
console.log('- onRefresh type:', typeof realTimeScale.realtime.onRefresh);
console.log('- onRefresh value:', realTimeScale.realtime.onRefresh);
if (typeof realTimeScale.realtime.onRefresh === 'function') {
console.log('✅ onRefresh callback está configurado correctamente');
// Test manual del callback
console.log('\n🧪 Probando callback onRefresh manualmente...');
try {
realTimeScale.realtime.onRefresh(chart);
console.log('✅ Callback onRefresh ejecutado sin errores');
} catch (error) {
console.error('❌ Error al ejecutar callback onRefresh:', error);
}
} else {
console.error('❌ onRefresh callback NO está configurado como función');
}
} else {
console.error('❌ No se encontró configuración realtime en la escala');
}
// Verificar streaming en chart
if (chart.$streaming) {
console.log('\n🔄 Estado del Streaming:');
console.log('- Streaming enabled:', chart.$streaming.enabled);
console.log('- Interval ID:', chart.$streaming.intervalId);
console.log('- Interval activo:', !!chart.$streaming.intervalId);
} else {
console.error('❌ No se encontró objeto $streaming en el chart');
}
};
console.log('🔧 Scripts de diagnóstico cargados:');
console.log('- diagnoseStreamingIssue() - Diagnóstico completo');
console.log('- resetStreaming() - Reiniciar streaming');
console.log('- quickStreamingTest() - Test rápido');
console.log('- diagnoseOnRefreshIssue() - Diagnóstico específico del onRefresh');

View File

@ -27,7 +27,6 @@ document.addEventListener('DOMContentLoaded', function () {
// 🔑 NUEVO: Inicializar plotManager si existe
if (typeof PlotManager !== 'undefined' && !window.plotManager) {
window.plotManager = new PlotManager();
console.log('📈 PlotManager initialized from main.js');
}
// Configurar actualizaciones periódicas como respaldo

View File

@ -3,53 +3,14 @@
* Maneja sesiones de plotting con Chart.js y comunicación con el backend
*/
// 🔧 Global debugging para plots
window.enablePlotDebug = () => {
window.plotDebugEnabled = true;
console.log('📈 Plot debugging enabled. Check console for detailed logs.');
};
window.disablePlotDebug = () => {
window.plotDebugEnabled = false;
console.log('📈 Plot debugging disabled.');
};
// Helper function para logging condicional
// Helper function para logging condicional (solo errores graves)
function plotDebugLog(...args) {
if (window.plotDebugEnabled) {
console.debug(...args);
}
// Solo mantener para compatibilidad, no hacer nada
}
// 🔧 Test function para verificar que todo funciona
// Test function removida - solo mantener para compatibilidad
window.testPlotSystem = async () => {
console.log('📈 Testing plot system...');
try {
// Test 1: Verificar disponibilidad de variables
const varsResponse = await fetch('/api/plots/variables');
const varsData = await varsResponse.json();
console.log('✅ Available variables:', varsData.available_variables.length);
console.log('✅ Boolean variables for triggers:', varsData.boolean_variables.length);
// Test 2: Verificar plots existentes
const plotsResponse = await fetch('/api/plots');
const plotsData = await plotsResponse.json();
console.log('✅ Existing plot sessions:', plotsData.sessions.length);
// Test 3: Si hay plots, verificar datos
if (plotsData.sessions.length > 0) {
const sessionId = plotsData.sessions[0].session_id;
const dataResponse = await fetch(`/api/plots/${sessionId}/data`);
const dataResult = await dataResponse.json();
console.log(`✅ Plot ${sessionId} has ${dataResult.datasets?.length || 0} datasets with ${dataResult.data_points_count || 0} points`);
}
console.log('📈 Plot system test completed. Enable debug with enablePlotDebug() for detailed logs.');
} catch (error) {
console.error('❌ Plot system test failed:', error);
}
// Función removida para limpiar debug
};
class PlotManager {
@ -88,7 +49,6 @@ class PlotManager {
this.startAutoUpdate();
this.isInitialized = true;
console.log('📈 Plot Manager initialized');
}
async loadExistingSessions() {
@ -268,8 +228,6 @@ class PlotManager {
// Inicializar datasets para las variables del plot
this.initializeStreamingDatasets(sessionId, config);
console.log(`📈 Created streaming plot session: ${sessionId}`);
}
updateChart(sessionId, plotData) {
@ -693,8 +651,6 @@ class PlotManager {
// Actualizar estadísticas del plot
this.updatePlotStats(sessionId, sessionInfo);
console.log(`📈 Created streaming plot tab and chart for session: ${sessionId}`);
}
updatePlotStats(sessionId, sessionInfo) {
@ -757,7 +713,6 @@ class PlotManager {
}
// 🔑 NUEVO: Los plots se auto-inician en el backend, no necesitamos start manual aquí
console.log(`Plot session created and auto-started: ${result.session_id}`);
showNotification(result.message, 'success');
return result.session_id;
@ -875,11 +830,9 @@ class PlotManager {
}
showPlotForm(sessionId = null) {
console.log('showPlotForm called with sessionId:', sessionId);
// Asegurar que estemos en el tab de plotting
if (typeof tabManager !== 'undefined' && tabManager.getCurrentTab() !== 'plotting') {
console.log('Switching to plotting tab');
tabManager.switchTab('plotting');
}
@ -906,31 +859,25 @@ class PlotManager {
if (sessionId) {
// Modo edición
console.log('Setting up form for editing');
if (formTitle) formTitle.textContent = '✏️ Edit Plot';
if (submitBtn) submitBtn.textContent = 'Update Plot';
this.loadPlotConfigForEdit(sessionId);
} else {
// Modo creación
console.log('Setting up form for creation');
if (formTitle) formTitle.textContent = '🆕 Create New Plot';
if (submitBtn) submitBtn.textContent = 'Create Plot';
this.resetPlotForm();
}
console.log('Making form visible');
formContainer.style.display = 'block';
// Scroll hacia el formulario para que sea visible
setTimeout(() => {
formContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
console.log('Scrolled to form');
}, 100);
// Cargar variables disponibles para triggers
this.loadTriggerVariables();
console.log('showPlotForm completed');
}
hidePlotForm() {
@ -1320,7 +1267,6 @@ class PlotManager {
if (this.currentEditingSession) {
// Modo edición: ELIMINAR el plot existente y crear uno nuevo desde cero
console.log(`Deleting existing plot ${this.currentEditingSession} to recreate it from scratch`);
// 1. Eliminar el plot existente
const deleteResponse = await fetch(`/api/plots/${this.currentEditingSession}`, {
@ -1353,7 +1299,6 @@ class PlotManager {
});
const deleteResult = await deleteResponse.json();
console.log(`Old plot deleted: ${deleteResult.message || 'Success'}`);
} else {
// Modo creación normal
response = await fetch('/api/plots', {
@ -1414,85 +1359,10 @@ class PlotManager {
}
}
this.sessions.clear();
console.log('📈 Plot Manager destroyed');
}
}
// 🔧 NUEVAS FUNCIONES DE DEBUG Y VERIFICACIÓN
/**
* Verifica que chartjs-plugin-streaming esté cargado correctamente
*/
window.verifyStreamingIntegration = function () {
console.log('🧪 Verificando integración de Chart.js Streaming...');
const checks = {
chartjsLoaded: typeof Chart !== 'undefined',
streamingLoaded: typeof window.ChartStreaming !== 'undefined',
plotManagerLoaded: typeof plotManager !== 'undefined',
activeStreamingSessions: 0
};
console.log('✅ Chart.js cargado:', checks.chartjsLoaded);
console.log('✅ ChartStreaming cargado:', checks.streamingLoaded);
console.log('✅ PlotManager cargado:', checks.plotManagerLoaded);
if (checks.plotManagerLoaded && plotManager.sessions) {
checks.activeStreamingSessions = plotManager.sessions.size;
console.log('✅ Sesiones de streaming activas:', checks.activeStreamingSessions);
// Verificar cada sesión
for (const [sessionId, sessionData] of plotManager.sessions) {
console.log(`📈 Sesión ${sessionId}:`, {
hasChart: !!sessionData.chart,
chartType: sessionData.chart?.config?.type,
scaleType: sessionData.chart?.scales?.x?.type,
datasets: sessionData.chart?.data?.datasets?.length || 0,
lastTimestamps: sessionData.lastTimestamps,
streaming: !!sessionData.chart?.$streaming?.enabled
});
}
}
if (checks.streamingLoaded) {
console.log('✅ ChartStreaming functions:', Object.keys(window.ChartStreaming));
// Test de configuración
try {
const testConfig = window.ChartStreaming.createStreamingChartConfig({
duration: 10000,
refresh: 1000
});
console.log('✅ Test configuración streaming:', !!testConfig);
} catch (e) {
console.log('❌ Error en test configuración:', e.message);
}
}
return checks;
};
/**
* Fuerza una actualización de datos para todas las sesiones
*/
window.forceStreamingUpdate = function () {
if (!plotManager || !plotManager.sessions) {
console.log('❌ PlotManager no disponible');
return;
}
console.log('🔄 Forzando actualización de streaming...');
for (const [sessionId, sessionData] of plotManager.sessions) {
console.log(`🔄 Actualizando sesión ${sessionId}...`);
if (sessionData.chart) {
// Forzar refresh de datos
plotManager.refreshStreamingData(sessionId, sessionData.chart);
}
}
};
// Funciones de debug removidas para limpiar console.log
// Función global para toggle de trigger config
window.togglePlotFormTriggerConfig = function () {
@ -1506,10 +1376,6 @@ window.togglePlotFormTriggerConfig = function () {
// Función global corregida para editar plots
window.editPlotSession = function (sessionId) {
console.log('editPlotSession called with sessionId:', sessionId);
console.log('plotManager available:', !!plotManager);
console.log('tabManager available:', typeof tabManager !== 'undefined');
if (!sessionId || sessionId.trim() === '') {
console.error('Invalid or empty session ID provided to editPlotSession');
showNotification('Error: Invalid session ID', 'error');
@ -1522,12 +1388,7 @@ window.editPlotSession = function (sessionId) {
return;
}
console.log('Opening plot form for editing session:', sessionId);
console.log('Current tab:', typeof tabManager !== 'undefined' ? tabManager.getCurrentTab() : 'tabManager not available');
plotManager.showPlotForm(sessionId);
console.log('Plot form should now be visible');
}
// Función global para remover sesiones de plot
@ -1564,8 +1425,6 @@ window.removePlotSession = async function (sessionId) {
// Función de utilidad para notificaciones
window.showNotification = function (message, type = 'info') {
console.log(`${type.toUpperCase()}: ${message}`);
// Si tienes un sistema de notificaciones, úsalo aquí
if (typeof showAlert === 'function') {
showAlert(message, type);
@ -1578,15 +1437,9 @@ window.showNotification = function (message, type = 'info') {
let plotManager = null;
document.addEventListener('DOMContentLoaded', function () {
console.log('📈 Initializing Plot Manager with streaming support...');
// Verificar que chartjs-plugin-streaming esté cargado
if (typeof window.ChartStreaming === 'undefined') {
console.error('❌ ChartStreaming plugin not loaded! The streaming functionality will not work.');
console.log('💡 Make sure chartjs-plugin-streaming.js is loaded before plotting.js');
} else {
console.log('✅ ChartStreaming plugin loaded successfully');
console.log('Available functions:', Object.keys(window.ChartStreaming));
}
// Exportar clase PlotManager globalmente
@ -1598,19 +1451,6 @@ document.addEventListener('DOMContentLoaded', function () {
// Para compatibilidad
plotManager = window.plotManager;
// Auto-verificar integración después de un breve delay
setTimeout(() => {
window.verifyStreamingIntegration();
// Si hay plots activos, mostrar información de debugging
if (plotManager.sessions.size > 0) {
console.log('📈 Active plot sessions detected. To debug:');
console.log('- enablePlotDebug() - Enable detailed logging');
console.log('- forceStreamingUpdate() - Force data update');
console.log('- verifyStreamingIntegration() - Check system status');
}
}, 2000);
// Cerrar modales con Escape (pero prevenir cierre accidental)
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape' && !e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey) {

View File

@ -1,133 +0,0 @@
/**
* 🧪 Test Rápido de Verificación Post-Fix
* Ejecutar después de cargar la página para verificar que todo funciona
*/
window.quickFixTest = function () {
console.log('🧪 TEST RÁPIDO POST-FIX');
console.log('='.repeat(40));
const results = {
duplicatedElements: false,
plotManagerAvailable: false,
eventsWorking: false,
chartStreamingLoaded: false,
debugFunctionsLoaded: false
};
// 1. Verificar elementos duplicados
console.log('\n1⃣ VERIFICANDO ELEMENTOS DUPLICADOS...');
const eventsContainers = document.querySelectorAll('#events-container');
const refreshBtns = document.querySelectorAll('#refresh-events-btn');
console.log(`- events-container: ${eventsContainers.length} (esperado: 1)`);
console.log(`- refresh-events-btn: ${refreshBtns.length} (esperado: 1)`);
results.duplicatedElements = eventsContainers.length === 1 && refreshBtns.length === 1;
console.log(results.duplicatedElements ? '✅ Sin duplicados' : '❌ Hay elementos duplicados');
// 2. Verificar PlotManager
console.log('\n2⃣ VERIFICANDO PLOTMANAGER...');
const pm = window.plotManager || plotManager;
results.plotManagerAvailable = !!pm;
console.log(`- window.plotManager: ${!!window.plotManager}`);
console.log(`- plotManager global: ${!!plotManager}`);
console.log(`- PlotManager class: ${!!window.PlotManager}`);
console.log(results.plotManagerAvailable ? '✅ PlotManager disponible' : '❌ PlotManager no disponible');
// 3. Verificar Events
console.log('\n3⃣ VERIFICANDO EVENTS...');
const eventsContainer = document.getElementById('events-container');
const eventsCount = document.getElementById('events-count');
console.log(`- events-container existe: ${!!eventsContainer}`);
console.log(`- events-count existe: ${!!eventsCount}`);
results.eventsWorking = !!eventsContainer && !!eventsCount;
console.log(results.eventsWorking ? '✅ Elements de events OK' : '❌ Faltan elementos de events');
// 4. Verificar Chart.js Streaming
console.log('\n4⃣ VERIFICANDO CHART.JS STREAMING...');
results.chartStreamingLoaded = !!window.ChartStreaming;
if (results.chartStreamingLoaded) {
const functions = Object.keys(window.ChartStreaming);
console.log(`✅ ChartStreaming cargado con ${functions.length} funciones`);
console.log(`- Funciones: ${functions.join(', ')}`);
} else {
console.log('❌ ChartStreaming no cargado');
}
// 5. Verificar funciones de debug
console.log('\n5⃣ VERIFICANDO FUNCIONES DE DEBUG...');
const debugFunctions = [
'diagnoseStreamingIssue',
'resetStreaming',
'quickStreamingTest',
'diagnoseOnRefreshIssue'
];
const availableFunctions = debugFunctions.filter(fn => typeof window[fn] === 'function');
results.debugFunctionsLoaded = availableFunctions.length === debugFunctions.length;
console.log(`✅ Funciones cargadas: ${availableFunctions.join(', ')}`);
if (availableFunctions.length < debugFunctions.length) {
const missing = debugFunctions.filter(fn => typeof window[fn] !== 'function');
console.log(`❌ Funciones faltantes: ${missing.join(', ')}`);
}
// 6. Resumen
console.log('\n6⃣ RESUMEN FINAL');
console.log('='.repeat(30));
const allGood = Object.values(results).every(Boolean);
if (allGood) {
console.log('🎉 ¡TODOS LOS PROBLEMAS ARREGLADOS!');
console.log('✅ Ya puedes crear plots y usar el diagnóstico');
console.log('');
console.log('📋 Próximos pasos:');
console.log('1. Ve a la pestaña "Real-Time Plotting"');
console.log('2. Crea un nuevo plot');
console.log('3. Ejecuta diagnoseOnRefreshIssue() para verificar streaming');
} else {
console.log('⚠️ Algunos problemas persisten:');
Object.entries(results).forEach(([key, value]) => {
if (!value) {
console.log(`${key}`);
}
});
console.log('');
console.log('💡 Intenta recargar la página (F5) y ejecutar quickFixTest() de nuevo');
}
return results;
};
// Test básico de events
window.testEventsIntegration = function () {
console.log('🧪 PROBANDO INTEGRACIÓN DE EVENTS...');
try {
refreshEventLog();
console.log('✅ refreshEventLog() ejecutado sin errores');
// Test loadEvents
if (typeof window.loadEvents === 'function') {
window.loadEvents();
console.log('✅ loadEvents() ejecutado sin errores');
} else {
console.log('❌ loadEvents() no disponible');
}
return true;
} catch (error) {
console.error('❌ Error en events:', error);
return false;
}
};
console.log('🧪 Funciones de test cargadas:');
console.log('- quickFixTest() - Verificación completa post-fix');
console.log('- testEventsIntegration() - Test específico de events');

View File

@ -111,7 +111,6 @@ function startStatusStreaming() {
statusEventSource = new EventSource('/api/stream/status?interval=2.0');
statusEventSource.onopen = function (event) {
console.log('Status streaming connected');
isStreamingStatus = true;
};
@ -121,7 +120,6 @@ function startStatusStreaming() {
switch (data.type) {
case 'connected':
console.log('Status stream connected:', data.message);
break;
case 'status':

View File

@ -16,8 +16,6 @@ class TabManager {
// Inicializar con el tab activo por defecto
this.switchTab(this.currentTab);
console.log('📑 Tab Manager initialized');
}
bindStaticTabs() {
@ -51,8 +49,6 @@ class TabManager {
// Eventos específicos por tab
this.handleTabSpecificEvents(tabName);
console.log(`📑 Switched to tab: ${tabName}`);
}
}
@ -156,7 +152,6 @@ class TabManager {
this.plotTabs.add(sessionId);
console.log(`📑 Created plot sub-tab for session: ${sessionId}`);
return subTabBtn;
}
@ -180,8 +175,6 @@ class TabManager {
// Eventos específicos por sub-tab
this.handleSubTabSpecificEvents(subTabName);
console.log(`📑 Switched to sub-tab: ${subTabName}`);
}
}
@ -220,8 +213,6 @@ class TabManager {
plotSessionsContainer.style.display = 'block';
plotSubContent.style.display = 'none';
}
console.log(`📑 Removed plot sub-tab for session: ${sessionId}`);
}
updatePlotTabName(sessionId, newName) {

View File

@ -1,216 +0,0 @@
/**
* 🧪 Script de prueba para Chart.js Plugin Streaming
* Ejecutar en consola del navegador para verificar integración
*/
// Test básico de disponibilidad
function testStreamingAvailability() {
console.log('🧪 Testing Chart.js Streaming Plugin availability...');
let results = {
chartjsLoaded: typeof Chart !== 'undefined',
streamingLoaded: typeof window.ChartStreaming !== 'undefined',
realTimeScaleRegistered: false,
streamingPluginRegistered: false
};
// Verificar que Chart.js esté cargado
if (results.chartjsLoaded) {
console.log('✅ Chart.js is loaded');
// Verificar escala realtime
try {
Chart.register(window.ChartStreaming.RealTimeScale);
results.realTimeScaleRegistered = true;
console.log('✅ RealTime scale is available');
} catch (e) {
console.log('❌ RealTime scale registration failed:', e.message);
}
// Verificar plugin de streaming
try {
Chart.register(window.ChartStreaming.streamingPlugin);
results.streamingPluginRegistered = true;
console.log('✅ Streaming plugin is available');
} catch (e) {
console.log('❌ Streaming plugin registration failed:', e.message);
}
} else {
console.log('❌ Chart.js is not loaded');
}
// Verificar ChartStreaming global
if (results.streamingLoaded) {
console.log('✅ ChartStreaming global object is available');
console.log('Available functions:', Object.keys(window.ChartStreaming));
} else {
console.log('❌ ChartStreaming global object is not available');
}
return results;
}
// Test de creación de configuración
function testStreamingConfig() {
console.log('🧪 Testing streaming configuration creation...');
if (typeof window.ChartStreaming === 'undefined') {
console.log('❌ ChartStreaming not available');
return false;
}
try {
const config = window.ChartStreaming.createStreamingChartConfig({
duration: 30000,
refresh: 1000,
yMin: 0,
yMax: 100
});
console.log('✅ Streaming configuration created successfully');
console.log('Config structure:', {
type: config.type,
hasRealTimeScale: config.options.scales.x.type === 'realtime',
duration: config.options.scales.x.realtime.duration,
refresh: config.options.scales.x.realtime.refresh
});
return true;
} catch (e) {
console.log('❌ Failed to create streaming configuration:', e.message);
return false;
}
}
// Test de creación de chart (requiere canvas)
function testStreamingChart() {
console.log('🧪 Testing streaming chart creation...');
// Buscar un canvas existente o crear uno temporal
let canvas = document.querySelector('canvas');
let isTemporary = false;
if (!canvas) {
console.log('Creating temporary canvas for testing...');
canvas = document.createElement('canvas');
canvas.id = 'test-streaming-canvas';
canvas.style.display = 'none';
document.body.appendChild(canvas);
isTemporary = true;
}
try {
const ctx = canvas.getContext('2d');
const config = window.ChartStreaming.createStreamingChartConfig({
duration: 10000,
refresh: 2000
});
const chart = new Chart(ctx, config);
console.log('✅ Streaming chart created successfully');
console.log('Chart info:', {
id: chart.id,
type: chart.config.type,
hasStreamingPlugin: chart.config.plugins.includes('streaming'),
scaleType: chart.scales.x.type
});
// Cleanup
chart.destroy();
if (isTemporary) {
canvas.remove();
}
return true;
} catch (e) {
console.log('❌ Failed to create streaming chart:', e.message);
// Cleanup en caso de error
if (isTemporary && canvas.parentNode) {
canvas.remove();
}
return false;
}
}
// Test completo
function runStreamingTests() {
console.log('🚀 Starting Chart.js Streaming Plugin Integration Tests');
console.log('='.repeat(60));
const results = {
availability: testStreamingAvailability(),
config: testStreamingConfig(),
chart: testStreamingChart()
};
console.log('='.repeat(60));
console.log('📊 Test Results Summary:');
console.log('- Availability:', results.availability.chartjsLoaded && results.availability.streamingLoaded ? '✅' : '❌');
console.log('- Configuration:', results.config ? '✅' : '❌');
console.log('- Chart Creation:', results.chart ? '✅' : '❌');
const allPassed = results.availability.chartjsLoaded &&
results.availability.streamingLoaded &&
results.config &&
results.chart;
if (allPassed) {
console.log('🎉 All tests passed! Chart.js Streaming Plugin is ready to use.');
} else {
console.log('⚠️ Some tests failed. Check the logs above for details.');
}
return results;
}
// Test específico para la aplicación PLC
function testPlotManagerIntegration() {
console.log('🧪 Testing PlotManager integration...');
if (typeof plotManager === 'undefined') {
console.log('❌ PlotManager not available (might not be on plotting tab)');
return false;
}
console.log('✅ PlotManager is available');
console.log('PlotManager info:', {
isInitialized: plotManager.isInitialized,
sessionsCount: plotManager.sessions.size,
colorsAvailable: plotManager.colors.length
});
// Verificar métodos de streaming
const streamingMethods = [
'setStreamingPause',
'clearStreamingData',
'refreshStreamingData',
'initializeStreamingDatasets'
];
const availableMethods = streamingMethods.filter(method =>
typeof plotManager[method] === 'function'
);
console.log('Available streaming methods:', availableMethods);
return availableMethods.length === streamingMethods.length;
}
// Hacer funciones disponibles globalmente para testing manual
if (typeof window !== 'undefined') {
window.testStreamingAvailability = testStreamingAvailability;
window.testStreamingConfig = testStreamingConfig;
window.testStreamingChart = testStreamingChart;
window.runStreamingTests = runStreamingTests;
window.testPlotManagerIntegration = testPlotManagerIntegration;
console.log('🧪 Streaming test functions loaded. Available commands:');
console.log('- testStreamingAvailability()');
console.log('- testStreamingConfig()');
console.log('- testStreamingChart()');
console.log('- runStreamingTests()');
console.log('- testPlotManagerIntegration()');
}

View File

@ -146,7 +146,6 @@ function startVariableStreaming() {
variableEventSource = new EventSource(`/api/stream/variables?dataset_id=${currentDatasetId}&interval=1.0`);
variableEventSource.onopen = function (event) {
console.log('Variable streaming connected');
isStreamingVariables = true;
updateStreamingIndicator(true);
};
@ -157,7 +156,6 @@ function startVariableStreaming() {
switch (data.type) {
case 'connected':
console.log('Variable stream connected:', data.message);
break;
case 'values':
@ -198,7 +196,6 @@ function startVariableStreaming() {
break;
default:
console.warn('Unknown SSE message type:', data.type);
break;
}
} catch (error) {

View File

@ -1,11 +1,11 @@
{
"last_state": {
"should_connect": true,
"should_stream": false,
"should_stream": true,
"active_datasets": [
"dar"
]
},
"auto_recovery_enabled": true,
"last_update": "2025-07-21T18:34:08.746917"
"last_update": "2025-08-03T10:18:30.092426"
}

View File

@ -775,11 +775,7 @@
<script src="/static/js/plotting.js"></script>
<script src="/static/js/main.js"></script>
<!-- Debug Streaming Script - Debe cargarse al final -->
<script src="/static/js/debug-streaming.js"></script>
<!-- Quick Fix Test Script -->
<script src="/static/js/quick-fix-test.js"></script>
</body>
</html>