dot 수정 신호 sync

This commit is contained in:
2026-01-24 18:28:04 +00:00
parent b1ed03cf56
commit 9431a100c4

View File

@@ -290,6 +290,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
let rangeMode = '10s';
let totalMsgReceived = 0;
let lastCanCounts = {}; // ★ 각 CAN ID별 마지막 count 저장
let lastSignalTimes = {}; // ⭐ 각 신호별 마지막 시간 저장 (time-base 모드용)
const COLORS = [
{line: '#FF6384', fill: 'rgba(255, 99, 132, 0.2)'},
@@ -360,7 +361,14 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
this.labels.shift();
this.rawValues.shift();
}
}
// ⭐ 배치 데이터 추가 (500ms 동안 받은 모든 데이터)
addDataBatch(values, times) {
values.forEach((value, index) => {
this.addData(value, times[index]);
});
// 배치 추가 후 한 번만 그리기
this.draw();
}
@@ -379,16 +387,17 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
const graphWidth = this.width - padding * 2;
const graphHeight = this.height - padding * 2;
ctx.clearRect(0, 0, this.width, this.height);
ctx.fillStyle = '#1a1a1a';
ctx.fillRect(0, 0, this.width, this.height);
let displayData = [];
let displayTimes = [];
let displayLabels = [];
if (rangeMode === '10s') {
const currentTime = this.times[this.times.length - 1];
const currentTime = parseFloat(this.times[this.times.length - 1]);
for (let i = 0; i < this.times.length; i++) {
if (currentTime - this.times[i] <= 10) {
if (currentTime - parseFloat(this.times[i]) <= 10) {
displayData.push(this.data[i]);
displayTimes.push(this.times[i]);
displayLabels.push(this.labels[i]);
@@ -408,20 +417,20 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
let minTime, maxTime, timeRange;
if (scaleMode === 'time') {
minTime = displayTimes[0];
maxTime = displayTimes[displayTimes.length - 1];
minTime = parseFloat(displayTimes[0]);
maxTime = parseFloat(displayTimes[displayTimes.length - 1]);
timeRange = maxTime - minTime || 1;
}
ctx.strokeStyle = '#444';
ctx.lineWidth = 1;
ctx.strokeStyle = '#888';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(padding, padding);
ctx.lineTo(padding, this.height - padding);
ctx.lineTo(this.width - padding, this.height - padding);
ctx.stroke();
ctx.fillStyle = '#aaa';
ctx.fillStyle = '#ccc';
ctx.font = '11px Arial';
ctx.textAlign = 'right';
@@ -443,7 +452,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
}
ctx.textAlign = 'center';
ctx.fillStyle = '#aaa';
ctx.fillStyle = '#ccc';
ctx.font = '10px Arial';
if (displayLabels.length > 0) {
ctx.fillText(displayLabels[0] + 's', padding, this.height - padding + 15);
@@ -460,7 +469,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
}
ctx.fillText('Time (sec)', this.width / 2, this.height - 5);
ctx.strokeStyle = '#333';
ctx.strokeStyle = '#444';
ctx.lineWidth = 1;
for (let i = 1; i < 5; i++) {
const y = padding + (graphHeight / 5) * i;
@@ -477,7 +486,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
let x;
if (scaleMode === 'time') {
const timePos = (displayTimes[i] - minTime) / timeRange;
const timePos = (parseFloat(displayTimes[i]) - minTime) / timeRange;
x = padding + graphWidth * timePos;
} else {
x = padding + (graphWidth / (MAX_DATA_POINTS - 1)) * i;
@@ -675,11 +684,20 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
// ★★★ 새로운 함수: update 타입 메시지 처리
// 서버가 보내는 형식: {id: 숫자, dlc: 숫자, data: [배열], count: 숫자}
// ★★★ count가 증가한 경우에만 그래프에 데이터 추가
// ★★★ count 차이만큼 배치로 데이터 추가 (500ms 동안 받은 모든 신호)
function processCANDataFromUpdate(messages) {
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1);
const sortedSignals = sortSignalsForDisplay();
// ⭐ 신호별로 데이터를 모을 배치 객체
const signalBatches = {};
sortedSignals.forEach((signal, index) => {
signalBatches[index] = {
values: [],
times: []
};
});
let processedCount = 0;
messages.forEach(canMsg => {
@@ -694,18 +712,19 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
msgId = msgId & 0x1FFFFFFF;
}
// ★ count가 증가한 경우에만 처리 (새로운 CAN 메시지가 있을 때만)
// ★ count 차이 계산 (500ms 동안 몇 개의 메시지가 왔는지)
const prevCount = lastCanCounts[msgId] || 0;
const currentCount = canMsg.count || 0;
const countDiff = currentCount - prevCount;
if (currentCount <= prevCount) {
if (countDiff <= 0) {
// count가 증가하지 않았으면 스킵
return;
}
// count 업데이트
lastCanCounts[msgId] = currentCount;
totalMsgReceived++;
totalMsgReceived += countDiff;
// data가 배열로 오는 경우 HEX 문자열로 변환
let hexData = '';
@@ -720,7 +739,27 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
try {
const value = decodeSignalFromHex(signal, hexData);
charts[index].addData(value, elapsedTime);
// ⭐ 신호별 시간 간격 계산
const signalKey = `${msgId}_${signal.name}`;
const lastTime = lastSignalTimes[signalKey] || 0;
const currentTime = parseFloat(elapsedTime);
const timeDelta = currentTime - lastTime;
// ⭐ 배치에 데이터 추가 (count 차이만큼, 각각 고유한 시간)
// 예: 10ms 주기 신호가 500ms 동안 50개 왔으면
// countDiff = 50
// 각 데이터를 시간 간격에 맞춰 분산
for (let i = 0; i < countDiff; i++) {
signalBatches[index].values.push(value);
// ⭐ 시간 분산: 500ms 동안 50개면 10ms 간격
const timeOffset = (timeDelta / countDiff) * i;
const dataTime = (lastTime + timeOffset).toFixed(3);
signalBatches[index].times.push(dataTime);
}
// 마지막 시간 업데이트
lastSignalTimes[signalKey] = currentTime;
const valueDiv = document.getElementById('value-' + index);
if (valueDiv) {
@@ -731,7 +770,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
}
}
processedCount++;
processedCount += countDiff;
} catch(e) {
console.error('Error decoding signal ' + signal.name + ':', e);
}
@@ -739,8 +778,18 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
});
});
// ⭐ 배치 데이터를 차트에 한 번에 추가
sortedSignals.forEach((signal, index) => {
if (charts[index] && signalBatches[index].values.length > 0) {
charts[index].addDataBatch(
signalBatches[index].values,
signalBatches[index].times
);
}
});
if (processedCount > 0) {
console.log('Added', processedCount, 'new data points from update');
console.log('Added', processedCount, 'new data points from update (batch mode)');
}
updateStatistics();