dot 수정 신호 sync
This commit is contained in:
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user