Werkzeug zur Echtzeit-Datenanalyse von BM6 pro Sekunde
Unterstützung für Echtzeit-Datenextraktion bei 1 Hz und CSV-Export
Dieses Tool sucht automatisch nach dem Paket d15507 in den Protokolldateien, wandelt die hexadezimalen Daten in eine pro Sekunde aktualisierte Aufzeichnung von Spannung und Temperatur um und bietet einen dynamischen Chart-Vorschau mit synchroner Skalierung sowie Funktionen zum Herunterladen der Daten.
Es liegen keine Textpassagen vor, die in Klammern ([alt](url) oder [](url)) enthalten sind und übersetzt werden müssen. Die angegebenen URLs wurden gemäß den Regeln unverändert belassen. Der Code bleibt wie folgt:
```html
```
```html
```
lassen Sie `vChart`, `tChart`;
lassen Sie `parsedData` = [];
lassen Sie `isResetting` = false;
// --- Konfiguration für die Initialisierung von 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]
};
}
// Erstellen Sie zwei Diagramm-Entitäten
vChart = new Chart(document.getElementById('voltageChart'), createChartConfig('Spannung (V)', '#58a6ff', 'Spannung (V)'));
tChart = new Chart(document.getElementById('tempChart'), createChartConfig('Temperatur (°C)', '#f85149', 'Temperatur (°C)'));
// --- Datei-Verarbeitung verarbeiten ---
uploadTrigger.onclick = () => fileInput.click();
fileInput.onchange = function(e) {
const datei = e.target.files[0];
if (!datei) return;
statusText.innerHTML = `Wird
${file.name} analysiert...`;
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;
// Logik zur Behandlung von nächtlichen Übergängen (z.B. von 23:59:59 auf 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;
// Abrufen des Timestamps für Chart.js
const timeVal = currentTimeObj.getTime();
vData.push({ x: timeVal, y: voltage });
tData.push({ x: timeVal, y: tempC });
// Speichert den ursprünglichen String für die CSV-Exportfunktion
parsedData.push([timeStr, voltage, tempC]);
});
if (parsedData.length > 0) {
statusText.innerHTML = `✅ Analyse erfolgreich! Es wurden
${parsedData.length} Echtzeitdaten extrahiert.`;
downloadBtn.style.display = 'inline-block';
isResetting = true;
[vChart, tChart].forEach(chart => {
if (chart.resetZoom) chart.resetZoom('keine');
});
// Daten aktualisieren
vChart.data.datasets[0].data = vData;
tChart.data.datasets[0].data = tData;
// Vorkalkulieren des Y-Achsenbereichs, um ein unvollständiges Diagramm zu verhindern
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.update('keine Werte anzeigen');
tChart.update('keine Werte anzeigen');
setInterval(() => { isResetting = false; }, 200);
} else {
statusText.innerHTML = `
❌ Keine gültigen Daten gefunden. Bitte überprüfen Sie, ob das Log die Paket-ID d15507 enthält.`;
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>
```