Herramienta de análisis en tiempo real de datos por segundo para BM6
Herramienta de análisis en tiempo real de datos por segundo para BM6
Soporte para extracción de datos en tiempo real a 1 Hz y exportación CSV
Esta herramienta busca automáticamente los paquetes d15507 dentro del registro, convierte los datos hexadecimales en registros de voltaje y temperatura actualizados por segundo, e incluye una vista previa dinámica con escala sincronizada así como la función para descargar los datos.
Esta herramienta busca automáticamente los paquetes d15507 dentro del registro, convierte los datos hexadecimales en registros de voltaje y temperatura actualizados por segundo, e incluye una vista previa dinámica con escala sincronizada así como la función para descargar los datos.
Seleccione un archivo que contenga datos de transmisión en tiempo real
`; solo la etiqueta vacía está presente. Si desea que traduzca algo, por favor proporcione el texto completo o el contenido específico que necesita convertir al español.
No se requiere traducción para este contenido, ya que los elementos proporcionados son etiquetas `
```
dejar que vChart y tChart sean variables globales;
dejar que parsedData sea un array vacío;
dejar que isResetting sea una variable booleana con valor falso.
// --- Configuración inicial de Chart.js ---
Chart.defaults.color = '#8b949e';
Chart.defaults.borderColor = '#30363d';
const crosshairPlugin = {
id: 'crosshair',
beforeDraw: chart => {
if (chart.tooltip._active && chart.tooltip._active.length) {
const ctx = chart.ctx;
const activePoint = chart.tooltip._active[0];
const x = activePoint.element.x;
const topY = chart.scales.y.top;
const bottomY = chart.scales.y.bottom;
ctx.save();
ctx.beginPath();
ctx.moveTo(x, topY);
ctx.lineTo(x, bottomY);
ctx.lineWidth = 1;
ctx.strokeStyle = 'rgba(139, 148, 158, 0.8)';
ctx.setLineDash([4, 4]);
ctx.stroke();
ctx.restore();
}
}
};
function autoScaleY(chart) {
const xScale = chart.scales.x, dataset = chart.data.datasets[0].data;
let minV = Infinity, maxV = -Infinity, found = false;
for (let i = 0; i < dataset.length; i++) {
const xVal = new Date(dataset[i].x).getTime();
if (xVal >= xScale.min && xVal <= xScale.max) {
if (dataset[i].y < minV) minV = dataset[i].y;
if (dataset[i].y > maxV) maxV = dataset[i].y;
found = true;
}
}
if (found) {
const padding = (maxV - minV) * 0.15 || 0.15;
charts.options.scales.y.min = minV - padding;
charts.options.scales.y.max = maxV + padding;
}
}
function syncCharts({chart}) {
if (isResetting) return;
const other = (chart === vChart) ? tChart : vChart;
other.options.scales.x.min = chart.scales.x.min;
other.options.scales.x.max = chart.scales.x.max;
autoScaleY(chart);
autoScaleY(other);
chart.update('none');
other.update('none');
}
function createChartConfig(label, color, yTitle) {
return {
type: 'line',
data: { datasets: [{ label: label, data: [], borderColor: color, backgroundColor: color + '20', borderWidth: 2, pointRadius: 0, tension: 0.2, fill: true }] },
options: {
responsive: true, maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false,
},
scales: {
x: {
type: 'time',
time: {
displayFormats: {
second: 'HH:mm:ss',
minute: 'HH:mm:ss',
hour: 'HH:mm:ss'
},
tooltipFormat: 'HH:mm:ss'
}
},
y: { title: { display: true, text: yTitle } }
},
plugins: {
tooltip: {
enabled: true,
backgroundColor: 'rgba(22, 27, 34, 0.9)',
titleColor: '#c9d1d9',
bodyColor: '#c9d1d9',
borderColor: '#30363d',
borderWidth: 1,
padding: 10,
displayColors: false
},
zoom: {
pan: { enabled: true, mode: 'x', onPan: syncCharts },
zoom: { wheel: { enabled: true }, mode: 'x', onZoom: syncCharts }
}
}
},
plugins: [crosshairPlugin]
};
}
// Crear dos entidades de gráfico
vChart = new Chart(document.getElementById('voltajeChart'), crearConfiguracionDeGráfico('Voltaje (V)', '#58a6ff', 'Voltaje (V)'));
tChart = new Chart(document.getElementById('temperaturaChart'), crearConfiguracionDeGráfico('Temperatura (°C)', '#f85149', 'Temperatura (°C)'));
// --- Manejo de análisis de archivos ---
uploadTrigger.onclick = () => fileInput.click();
fileInput.onchange = function(e) {
const archivo = e.target.files[0];
if (!archivo) return;
statusText.innerHTML = `Se está analizando ${file.name}...`;
const reader = new FileReader();
reader.onload = function(e) {
processData(e.target.result);
};
reader.readAsText(file);
function processData(text) {
const lines = text.split('\n');
// d15507 + TempHex(2) + Other(2) + SOCHex(2) + VolHex(4)
const pattern = /^(\d{2}:\d{2}:\d{2}):receive:d1550700([0-9a-fA-F]{2})[0-9a-fA-F]{2}([0-9a-fA-F]{2})([0-9a-fA-F]{4})/;
const vData = [];
const tData = [];
parsedData = [];
let currentDay = 1;
let lastTimeObj = null;
lines.forEach(line => {
const match = line.trim().match(pattern);
if (match) {
const timeStr = match[1]; // "HH:MM:SS"
const tempC = parseInt(match[2], 16);
const voltage = parseInt(match[4], 16) / 100.0;
// Manejo de lógica transnoche (por ejemplo, pasar de 23:59:59 a 00:00:00)
const [h, m, s] = timeStr.split(':').map(Number);
const currentTimeObj = new Date(2026, 0, currentDay, h, m, s);
if (lastTimeObj && currentTimeObj < lastTimeObj) {
currentDay++;
currentTimeObj.setDate(currentDay);
}
lastTimeObj = currentTimeObj;
// Obtener Timestamp para Chart.js
const timeVal = currentTimeObj.getTime();
vData.push({x: timeVal, y: voltage});
tData.push({x: timeVal, y: tempC});
// Guardar la cadena original para exportación CSV
parsedData.push([timeStr, voltage, tempC]);
})
if (parsedData.length > 0) {
statusText.innerHTML = `✅ ¡Éxito en el análisis! Se han extraído ${parsedData.length} registros de datos en tiempo real.`;
downloadBtn.style.display = 'inline-block';
isResetting = true;
[ vChart , tChart ].forEach(chart => {
si chart .resetZoom existe , chart .resetZoom ('no' );
} ) ;
// Actualizar datos
vChart.data.datasets[0].data = vData;
tChart.data.datasets[0].data = tData;
// Calcular con anticipación los límites del eje Y para evitar que el gráfico no se muestre completamente
const vValues = vData.map(d => d.y);
const tValues = tData.map(d => d.y);
const minV = Math.min(...vValues), maxV = Math.max(...vValues);
const minT = Math.min(...tValues), maxT = Math.max(...tValues);
const vPad = (maxV - minV) * 0.15 || 0.5;
const tPad = (maxT - minT) * 0.15 || 2;
vChart.options.scales.y.min = minV - vPad;
vChart.options.scales.y.max = maxV + vPad;
tChart.options.scales.y.min = minT - tPad;
tChart.options.scales.y.max = maxT + vPad;
vChart.actualizar('ninguno');
tChart.actualizar('ninguno');
No se ha proporcionado texto para traducir en español, ya que el contenido es un fragmento de código JavaScript (`setTimeout`), no una frase o párrafo lingüístico. Si desea que traduzca instrucciones relacionadas con este código (por ejemplo: "Configurar un temporizador para detener la reinicialización después de 200 milisegundos"), por favor proporcione el texto descriptivo correspondiente.
} else {
statusText.innerHTML = `❌ No se encontraron datos válidos. Verifique si el registro contiene paquetes d15507.`;
downloadBtn.style.display = 'none';
}
}
```javascript
downloadBtn.onclick = function() {
if (parsedData.length === 0) return;
let csvContent = "Time,Voltage(V),Temperature(°C)\n";
parsedData.forEach(row => { csvContent += row.join(",") + "\n"; });
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.setAttribute("href", url);
link.setAttribute("download", "bm6_per_second_data.csv");
link.click();
};
})();
</script>
```