최종 ext ID 수신 확인

This commit is contained in:
2025-10-18 16:57:29 +00:00
parent ce4444df2e
commit 54230dd627
2 changed files with 136 additions and 16 deletions

View File

@@ -809,7 +809,7 @@ void webUpdateTask(void *pvParameters) {
uint32_t lastStatusUpdate = 0;
uint32_t lastCanUpdate = 0;
uint32_t lastTxStatusUpdate = 0;
const uint32_t CAN_UPDATE_INTERVAL = 500;
const uint32_t CAN_UPDATE_INTERVAL = 500; // 0.5초마다 전송
Serial.println("웹 업데이트 태스크 시작");
@@ -870,11 +870,13 @@ void webUpdateTask(void *pvParameters) {
lastStatusUpdate = now;
}
// CAN 메시지 일괄 업데이트
// CAN 메시지 일괄 업데이트 - 항상 전송 (데이터가 있으면)
if (now - lastCanUpdate >= CAN_UPDATE_INTERVAL) {
String canBatch = "{\"type\":\"canBatch\",\"messages\":[";
bool first = true;
int messageCount = 0;
// recentData 배열을 순회하면서 유효한 메시지만 전송
for (int i = 0; i < RECENT_MSG_COUNT; i++) {
if (recentData[i].msg.timestamp_us > 0) {
CANMessage* msg = &recentData[i].msg;
@@ -900,13 +902,19 @@ void webUpdateTask(void *pvParameters) {
uint64_t timestamp_ms = msg->timestamp_us / 1000;
canBatch += "\",\"timestamp\":" + String((uint32_t)timestamp_ms);
canBatch += ",\"count\":" + String(recentData[i].count) + "}";
messageCount++;
}
}
canBatch += "]}";
if (!first) {
// 메시지가 하나라도 있으면 전송
if (messageCount > 0) {
webSocket.broadcastTXT(canBatch);
// 디버깅: 전송된 메시지 수 로그 (필요시)
// Serial.printf("WebSocket: Sent %d CAN messages\n", messageCount);
}
lastCanUpdate = now;

View File

@@ -416,6 +416,7 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
dbcData.messages[sig.messageId].signals.push(sig);
});
console.log('Loaded', selectedSignals.length, 'signals');
return true;
} catch(e) {
console.error('Failed to load data:', e);
@@ -482,12 +483,14 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
startTime = Date.now();
lastTimestamps = {};
updateStatus('Graphing...', false);
console.log('Started graphing at', new Date().toISOString());
}
}
function stopGraphing() {
graphing = false;
updateStatus('Stopped', false);
console.log('Stopped graphing');
}
function setScaleMode(mode) {
@@ -516,33 +519,60 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
const elapsedTime = ((Date.now() - startTime) / 1000).toFixed(1);
const sortedSignals = sortSignalsForDisplay();
console.log('Processing', messages.length, 'messages at time', elapsedTime + 's');
let processedCount = 0;
messages.forEach(canMsg => {
const idStr = canMsg.id.replace(/\s/g, '').toUpperCase();
const msgId = parseInt(idStr, 16);
let msgId = parseInt(idStr, 16);
// Extended CAN ID 처리 (bit 31 제거)
if (msgId & 0x80000000) {
msgId = msgId & 0x1FFFFFFF;
}
const timestamp = canMsg.timestamp;
sortedSignals.forEach((signal, index) => {
if (signal.messageId === msgId && charts[index]) {
try {
const signalKey = msgId + '_' + signal.name;
const value = decodeSignal(signal, canMsg.data);
if (!lastTimestamps[signalKey] || lastTimestamps[signalKey] !== timestamp) {
const value = decodeSignal(signal, canMsg.data);
charts[index].addData(value, elapsedTime);
lastTimestamps[signalKey] = timestamp;
const valueDiv = document.getElementById('value-' + index);
if (valueDiv) {
valueDiv.textContent = value.toFixed(2) + (signal.unit ? ' ' + signal.unit : '');
}
// 항상 추가 (중복 체크 제거)
charts[index].addData(value, elapsedTime);
const valueDiv = document.getElementById('value-' + index);
if (valueDiv) {
valueDiv.textContent = value.toFixed(2) + (signal.unit ? ' ' + signal.unit : '');
}
processedCount++;
} catch(e) {
console.error('Error decoding signal:', e);
console.error('Error decoding signal ' + signal.name + ':', e);
}
}
});
});
if (processedCount > 0) {
console.log('Added', processedCount, 'new data points');
}
// 통계 업데이트
updateStatistics();
}
function updateStatistics() {
let totalDataPoints = 0;
Object.values(charts).forEach(chart => {
totalDataPoints += chart.data.length;
});
document.getElementById('data-point-count').textContent = totalDataPoints;
const recordingTime = ((Date.now() - startTime) / 1000).toFixed(1);
document.getElementById('recording-time').textContent = recordingTime + 's';
}
function decodeSignal(signal, hexData) {
@@ -590,6 +620,88 @@ const char graph_viewer_html[] PROGMEM = R"rawliteral(
return rawValue * signal.factor + signal.offset;
}
function downloadCSV() {
if (Object.keys(charts).length === 0) {
alert('No data to download!');
return;
}
let csvContent = 'Time(s)';
const sortedSignals = sortSignalsForDisplay();
// 헤더 생성
sortedSignals.forEach(signal => {
const unit = signal.unit ? ' [' + signal.unit + ']' : '';
csvContent += ',' + signal.name + unit;
});
csvContent += '\n';
// 데이터 생성
let maxLength = 0;
Object.values(charts).forEach(chart => {
if (chart.labels.length > maxLength) {
maxLength = chart.labels.length;
}
});
for (let i = 0; i < maxLength; i++) {
let row = '';
let timeValue = '';
sortedSignals.forEach((signal, index) => {
const chart = charts[index];
if (chart && chart.labels[i] !== undefined) {
if (timeValue === '') {
timeValue = chart.labels[i];
}
row += ',' + chart.data[i].toFixed(6);
} else {
row += ',';
}
});
if (timeValue !== '') {
csvContent += timeValue + row + '\n';
}
}
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
link.setAttribute('href', url);
link.setAttribute('download', 'can_signals_' + timestamp + '.csv');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.log('CSV downloaded with ' + maxLength + ' data points');
}
function clearData() {
if (!confirm('Clear all recorded data? This cannot be undone.')) {
return;
}
Object.values(charts).forEach(chart => {
chart.data = [];
chart.times = [];
chart.labels = [];
chart.currentValue = 0;
chart.draw();
});
lastTimestamps = {};
startTime = Date.now();
updateStatistics();
console.log('All data cleared');
}
if (loadData()) {
createGraphs();
initWebSocket();