| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866 |
- class CommDebugger {
- constructor() {
- this.ws = null;
- this.isConnected = false;
- this.currentPort = 1;
- // 为每个端口维护监听状态
- this.portMonitoringStatus = {};
- this.initializeElements();
- this.bindEvents();
- // 设置默认端口显示
- this.portSelect.value = this.currentPort;
- this.connect();
- }
- initializeElements() {
- this.portSelect = document.getElementById('portSelect');
- this.portOptions = document.getElementById('portOptions');
- this.startBtn = document.getElementById('startBtn');
- this.stopBtn = document.getElementById('stopBtn');
- this.clearBtn = document.getElementById('clearBtn');
- this.readData = document.getElementById('readData');
- this.readSendBtn = document.getElementById('readSendBtn');
- this.writeData = document.getElementById('writeData');
- this.writeSendBtn = document.getElementById('writeSendBtn');
- this.logOutput = document.getElementById('logOutput');
- this.connectionStatus = document.getElementById('connectionStatus');
- // 新增的复选框元素
- this.writeToWriteSendCheckbox = document.getElementById('writeToWriteSend');
- this.readToReadSendCheckbox = document.getElementById('readToReadSend');
- this.readToModifyDataCheckbox = document.getElementById('readToModifyData');
- // 数据表格元素
- this.dataTable = document.getElementById('dataTable');
- }
- bindEvents() {
- // 端口选择框事件处理
- this.portSelect.addEventListener('focus', () => {
- this.portOptions.classList.add('show');
- });
- this.portSelect.addEventListener('click', () => {
- this.portOptions.classList.toggle('show');
- });
- this.portSelect.addEventListener('blur', () => {
- // 添加延迟以确保点击选项时不会立即隐藏
- setTimeout(() => {
- this.portOptions.classList.remove('show');
- }, 200);
- });
- this.portSelect.addEventListener('input', (e) => {
- this.currentPort = this.getPortNumber(e.target.value);
- });
- // 端口选项点击事件
- const portOptions = this.portOptions.querySelectorAll('.port-option');
- portOptions.forEach(option => {
- option.addEventListener('mousedown', (e) => {
- e.preventDefault(); // 防止blur事件触发
- this.portSelect.value = e.target.getAttribute('data-value');
- this.currentPort = this.getPortNumber(this.portSelect.value);
- this.portOptions.classList.remove('show');
- this.portSelect.focus();
- });
- });
- this.startBtn.addEventListener('click', () => {
- this.startMonitoring();
- });
- this.stopBtn.addEventListener('click', () => {
- this.stopMonitoring();
- });
- this.clearBtn.addEventListener('click', () => {
- this.clearLog();
- });
- this.readSendBtn.addEventListener('click', () => {
- this.sendReadData();
- });
- this.writeSendBtn.addEventListener('click', () => {
- this.sendWriteData();
- });
- // 复选框事件处理
- this.writeToWriteSendCheckbox.addEventListener('change', () => {
- this.handleWriteToWriteSendChange();
- });
- this.readToReadSendCheckbox.addEventListener('change', () => {
- this.handleReadToReadSendChange();
- });
- this.readToModifyDataCheckbox.addEventListener('change', () => {
- this.handleReadToModifyDataChange();
- });
- // 初始化WebSocket连接
- // this.connect(); // 移除重复调用,只在构造函数中调用一次
- }
- // 获取端口号(支持COMx格式或纯数字)
- getPortNumber(portStr) {
- if (!portStr) return 1;
- // 如果是COMx格式,提取数字部分
- const comMatch = portStr.match(/^COM(\d+)$/i);
- if (comMatch) {
- return parseInt(comMatch[1]);
- }
- // 如果是纯数字格式
- const num = parseInt(portStr);
- if (!isNaN(num) && num > 0) {
- return num;
- }
- // 默认返回1
- return 1;
- }
- connect() {
- try {
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
- const wsUrl = `${protocol}//${window.location.host}/ws`;
- this.ws = new WebSocket(wsUrl);
- this.ws.onopen = () => {
- this.isConnected = true;
- this.updateConnectionStatus(true);
- this.log('WebSocket连接已建立', 'success');
- };
- this.ws.onmessage = (event) => {
- this.handleMessage(event.data);
- };
- this.ws.onclose = () => {
- this.isConnected = false;
- this.updateConnectionStatus(false);
- this.log('WebSocket连接已断开', 'error');
- // 自动重连
- setTimeout(() => {
- if (!this.isConnected) {
- this.log('尝试重新连接...', 'info');
- this.connect();
- }
- }, 3000);
- };
- this.ws.onerror = (error) => {
- this.log('WebSocket连接错误: ' + error, 'error');
- };
- } catch (error) {
- this.log('连接失败: ' + error.message, 'error');
- }
- }
- handleMessage(data) {
- try {
- const message = JSON.parse(data);
- switch (message.cmd) {
- case 'InitMonitor':
- this.handleInitMonitorResponse(message);
- break;
- case 'StopPort':
- this.handleStopPortResponse(message);
- break;
- case 'ReadData':
- this.handleReadDataResponse(message);
- break;
- case 'WriteData':
- this.handleWriteDataResponse(message);
- break;
- case 'OP_READ':
- this.handleReadEvent(message);
- break;
- case 'OP_WRITE':
- this.handleWriteEvent(message);
- break;
- case 'OP_OPEN':
- this.handleOpenEvent(message);
- break;
- case 'OP_CLOSE':
- this.handleCloseEvent(message);
- break;
- default:
- this.log('未知消息类型: ' + message.cmd, 'warning');
- }
- } catch (error) {
- this.log('解析消息失败: ' + error.message, 'error');
- }
- }
- handleInitMonitorResponse(message) {
- if (message.result) {
- // 更新特定端口的监听状态
- this.portMonitoringStatus[message.port] = true;
- this.log(`${message.port} 开始监听成功`, 'success');
- } else {
- this.log(`${message.port} 开始监听失败`, 'error');
- }
- }
- handleStopPortResponse(message) {
- if (message.result) {
- // 更新特定端口的监听状态
- this.portMonitoringStatus[message.port] = false;
- this.log(`${message.port} 停止监听成功`, 'success');
- } else {
- this.log(`${message.port} 停止监听失败`, 'error');
- }
- }
- handleReadDataResponse(message) {
- if (message.result) {
- this.log(`${message.port} 读数据发送成功`, 'info');
- } else {
- this.log(`${message.port} 读数据发送失败`, 'error');
- }
- }
- handleWriteDataResponse(message) {
- if (message.result) {
- this.log(`${message.port} 写数据发送成功`, 'info');
- } else {
- this.log(`${message.port} 写数据发送失败`, 'error');
- }
- }
- handleReadEvent(message) {
- this.log(`${message.port} 读取数据: ${message.data}`, 'read');
- }
- handleWriteEvent(message) {
- this.log(`${message.port} 写入数据: ${message.data}`, 'write');
- }
- handleOpenEvent(message) {
- this.log(`${message.port} 端口已打开`, 'open');
- }
- handleCloseEvent(message) {
- this.log(`${message.port} 端口已关闭`, 'close');
- }
- startMonitoring() {
- if (!this.isConnected) {
- this.log('WebSocket未连接', 'error');
- return;
- }
- const message = {
- cmd: 'InitMonitor',
- port: this.currentPort
- };
- this.sendMessage(message);
- }
- stopMonitoring() {
- if (!this.isConnected) {
- this.log('WebSocket未连接', 'error');
- return;
- }
- const message = {
- cmd: 'StopPort',
- port: this.currentPort
- };
- this.sendMessage(message);
- }
- sendReadData() {
- if (!this.isConnected) {
- this.log('WebSocket未连接', 'error');
- return;
- }
- const data = this.readData.value.trim();
- if (!data) {
- this.log('请输入读数据内容', 'warning');
- return;
- }
- const message = {
- cmd: 'ReadData',
- port: this.currentPort,
- data: data
- };
- this.sendMessage(message);
- // 清除数据表格
- this.clearDataTable();
- }
- sendWriteData() {
- if (!this.isConnected) {
- this.log('WebSocket未连接', 'error');
- return;
- }
- const data = this.writeData.value.trim();
- if (!data) {
- this.log('请输入写数据内容', 'warning');
- return;
- }
- const message = {
- cmd: 'WriteData',
- port: this.currentPort,
- data: data
- };
- this.sendMessage(message);
- }
- sendMessage(message) {
- try {
- this.ws.send(JSON.stringify(message));
- } catch (error) {
- this.log('发送消息失败: ' + error.message, 'error');
- }
- }
- updateConnectionStatus(connected) {
- if (connected) {
- this.connectionStatus.textContent = '已连接';
- this.connectionStatus.className = 'status connected';
- } else {
- this.connectionStatus.textContent = '未连接';
- this.connectionStatus.className = 'status disconnected';
- }
- }
- log(message, type = 'info') {
- const timestamp = new Date().toLocaleTimeString();
- const logMessage = document.createElement('div');
- logMessage.className = `log-message ${type}`;
- logMessage.textContent = `[${timestamp}] ${message}`;
- this.logOutput.appendChild(logMessage);
- this.logOutput.scrollTop = this.logOutput.scrollHeight;
- }
- clearLog() {
- this.logOutput.innerHTML = '';
- this.log('日志已清空', 'info');
- }
- validateHexData(data) {
- // 验证十六进制数据格式
- const hexPattern = /^[0-9A-Fa-f\s]+$/;
- return hexPattern.test(data.trim());
- }
- // 处理"写入数据→写发送"复选框变化
- handleWriteToWriteSendChange() {
- // 功能已在handleWriteEvent中实现
- this.log(`"写入数据→写发送"选项已${this.writeToWriteSendCheckbox.checked ? '启用' : '禁用'}`, 'info');
- }
- // 处理"读取数据→读发送"复选框变化
- handleReadToReadSendChange() {
- // 功能已在handleReadEvent中实现
- this.log(`"读取数据→读发送"选项已${this.readToReadSendCheckbox.checked ? '启用' : '禁用'}`, 'info');
- }
- // 处理"读取数据→修改数据"复选框变化
- handleReadToModifyDataChange() {
- this.log(`"读取数据→修改数据"选项已${this.readToModifyDataCheckbox.checked ? '启用' : '禁用'}`, 'info');
- }
- // 重写handleReadEvent方法以添加复选框功能
- handleReadEvent(message) {
- // 调用原始的日志显示方法
- this.handleReadEventOriginal(message);
- // 如果勾选了"读取数据→修改数据",则解析数据
- let isParsed = false;
- if (this.readToModifyDataCheckbox.checked) {
- // 如果数据解析成功(满足特定条件),则不再执行"读取数据→读发送"的操作
- const isParsed = this.parseAndDisplayData(message.data);
- if (isParsed) {
- // 数据满足解析条件,不再执行"读取数据→读发送"的操作
- return;
- }
- }
- // 如果勾选了"读取数据→读发送",则将数据添加到读数据编辑框并执行读发送
- if (this.readToReadSendCheckbox.checked) {
- this.readData.value = message.data;
- // 自动执行读发送
- this.sendReadData();
- }
- }
- // 重写handleWriteEvent方法以添加复选框功能
- handleWriteEvent(message) {
- // 调用原始的日志显示方法
- this.handleWriteEventOriginal(message);
- // 如果勾选了"写入数据→写发送",则将数据添加到写数据编辑框并执行写发送
- if (this.writeToWriteSendCheckbox.checked) {
- this.writeData.value = message.data;
- // 自动执行写发送
- this.sendWriteData();
- }
- }
- // 原始的handleReadEvent方法
- handleReadEventOriginal(message) {
- this.log(`${message.port} 读取数据: ${message.data}`, 'read');
- }
- // 原始的handleWriteEvent方法
- handleWriteEventOriginal(message) {
- this.log(`${message.port} 写入数据: ${message.data}`, 'write');
- }
- // 解析数据并显示在表格中
- parseAndDisplayData(hexData) {
- // 将十六进制字符串转换为字节数组
- const bytes = this.hexStringToBytes(hexData);
- // 检查是否满足特定条件:ACK=06H, CMD=A3H, LB=17H
- if (bytes.length >= 3 && bytes[0] === 0x06 && bytes[1] === 0xA3 && bytes[2] === 0x17) {
- // 解析数据字段
- const parsedData = this.parseDataFields(bytes);
- // 更新表格并重新计算校验和
- this.updateDataTable(parsedData, bytes);
- // 解析成功
- return true;
- } else {
- this.log('数据不满足解析条件(ACK=06H, CMD=A3H, LB=17H)', 'warning');
- // 解析失败
- return false;
- }
- }
- // 将十六进制字符串转换为字节数组
- hexStringToBytes(hexString) {
- const bytes = [];
- const hexValues = hexString.trim().split(/\s+/);
- for (let i = 0; i < hexValues.length; i++) {
- const byte = parseInt(hexValues[i], 16);
- if (!isNaN(byte)) {
- bytes.push(byte);
- }
- }
- return bytes;
- }
- // 解析数据字段
- parseDataFields(bytes) {
- // 根据规范解析数据:
- // 06H-A3H-17H-CO₂高位-C0,低位-C0 高位-CO 低位-HC 高位-HC低位-NO 高位-NO
- // 低位-0,高位-0,低位-油温高位-油温低位-转速高位-转速低位-气路压力高位-气路压力低位-过量空气系数高位-过量空气系数低位-PEF 值高位-PEF 值低位-校验码
- const data = {};
- // 确保数据长度足够
- if (bytes.length < 27) { // 3(头部) + 2*11(参数) + 1(校验) = 26字节,索引从0开始所以需要27
- this.log('数据长度不足,无法解析', 'error');
- return data;
- }
- // 提取各参数(高位在前,低位在后)
- try {
- // CO₂ (索引3-4)
- data.CO2 = this.combineBytes(bytes[3], bytes[4]);
- // CO (索引5-6)
- data.CO = this.combineBytes(bytes[5], bytes[6]);
- // HC (索引7-8)
- data.HC = this.combineBytes(bytes[7], bytes[8]);
- // NO (索引9-10)
- data.NO = this.combineBytes(bytes[9], bytes[10]);
- // O2 (索引11-12)
- data.O2 = this.combineBytes(bytes[11], bytes[12]);
- // 油温 (索引13-14)
- data.油温 = this.combineBytes(bytes[13], bytes[14]);
- // 转速 (索引15-16)
- data.转速 = this.combineBytes(bytes[15], bytes[16]);
- // 气路压力 (索引17-18)
- data.气路压力 = this.combineBytes(bytes[17], bytes[18]);
- // 过量空气系数 (索引19-20)
- data.过量空气系数 = this.combineBytes(bytes[19], bytes[20]);
- // PEF值 (索引21-22)
- data.PEF值 = this.combineBytes(bytes[21], bytes[22]);
- return data;
- } catch (error) {
- this.log(`解析数据时出错: ${error.message}`, 'error');
- return {};
- }
- }
- // 合并高低字节为一个数值(高位在前)
- combineBytes(high, low) {
- return (high << 8) | low;
- }
- // 更新数据表格
- updateDataTable(parsedData) {
- const tbody = this.dataTable.querySelector('tbody');
- tbody.innerHTML = ''; // 清空现有数据
- // Table3.5 数据转换关系表
- const conversionTable = {
- 'HC': { range: [0, 9999], unit: '×10⁻⁶' },
- 'CO': { range: [0, 1500], unit: '%' },
- 'NO': { range: [0, 5000], unit: '×10⁻⁶' },
- 'CO2': { range: [0, 1800], unit: '%' },
- 'O2': { range: [0, 2500], unit: '%' },
- '油温': { range: [0, 1000], unit: '℃' },
- '转速': { range: [0, 9999], unit: 'r/min' },
- '气路压力': { range: [0, 1100], unit: 'kPa' },
- '过量空气系数': { range: [0, 2000], unit: '' },
- 'PEF值': { range: [470, 540], unit: '' }
- };
- // 参数映射(解析后的数据键名到显示名称)
- const parameterMapping = {
- 'HC': 'HC',
- 'CO': 'CO',
- 'NO': 'NO',
- 'CO2': 'CO₂',
- 'O2': 'O₂',
- '油温': '油温',
- '转速': '转速',
- '气路压力': '气路压力',
- '过量空气系数': '过量空气系数',
- 'PEF值': 'PEF 值'
- };
- // 遍历解析后的数据并添加到表格
- for (const [key, value] of Object.entries(parsedData)) {
- if (parameterMapping[key]) {
- const displayName = parameterMapping[key];
- const config = conversionTable[displayName];
- if (config) {
- // 原始值
- let rawValue = value;
- // 根据转换规则转换为实际值
- let convertedValue = this.convertValue(rawValue, config);
- // 最大值
- const maxValue = config.range[1];
- // 创建表格行
- const row = document.createElement('tr');
- row.dataset.parameter = key; // 保存参数名用于识别
- // 添加单元格
- row.innerHTML = `
- <td>${displayName}</td>
- <td contenteditable="true" data-raw-value="${rawValue}" data-parameter="${key}">${rawValue}</td>
- <td>${maxValue}${config.unit}</td>
- `;
- tbody.appendChild(row);
- // 为可编辑单元格添加事件监听器
- const editableCell = row.querySelector('[contenteditable]');
- editableCell.addEventListener('blur', (e) => {
- this.handleParameterEdit(e, key, config, bytes, validatedData);
- });
- editableCell.addEventListener('keydown', (e) => {
- if (e.key === 'Enter') {
- e.preventDefault();
- editableCell.blur();
- }
- });
- }
- }
- }
- }
- // 根据转换规则将原始值转换为实际值
- convertValue(rawValue, config) {
- const [min, max] = config.range;
- // 检查是否在有效范围内
- if (rawValue < min) {
- rawValue = min;
- } else if (rawValue > max) {
- rawValue = max;
- }
- // 根据参数类型进行转换
- switch (config.unit) {
- case '%':
- // 转换为百分比格式(保留两位小数)
- return (rawValue / 100).toFixed(2);
- case '℃':
- // 转换为温度格式(保留一位小数)
- return (rawValue / 10).toFixed(1);
- case 'kPa':
- // 转换为压力格式(保留一位小数)
- return (rawValue / 10).toFixed(1);
- case '':
- // 无单位参数的处理
- if (config.range[0] === 0 && config.range[1] === 2000) {
- // 过量空气系数,转换为三位小数
- const value = (rawValue / 1000).toFixed(3);
- // 超过2.000显示2.000
- return parseFloat(value) > 2.000 ? '2.000' : value;
- } else if (config.range[0] === 470 && config.range[1] === 540) {
- // PEF值,转换为三位小数
- return (rawValue / 1000).toFixed(3);
- }
- return rawValue;
- default:
- // 其他情况直接返回原始值
- return rawValue;
- }
- }
- // 更新数据表格并重新计算校验和
- updateDataTable(parsedData, bytes) {
- const tbody = this.dataTable.querySelector('tbody');
- tbody.innerHTML = ''; // 清空现有数据
- // Table3.5 数据转换关系表
- const conversionTable = {
- 'HC': { range: [0, 9999], unit: '×10⁻⁶' },
- 'CO': { range: [0, 1500], unit: '%' },
- 'NO': { range: [0, 5000], unit: '×10⁻⁶' },
- 'CO2': { range: [0, 1800], unit: '%' },
- 'O2': { range: [0, 2500], unit: '%' },
- '油温': { range: [0, 1000], unit: '℃' },
- '转速': { range: [0, 9999], unit: 'r/min' },
- '气路压力': { range: [0, 1100], unit: 'kPa' },
- '过量空气系数': { range: [0, 2000], unit: '' },
- 'PEF值': { range: [470, 540], unit: '' }
- };
- // 参数映射(解析后的数据键名到显示名称)
- const parameterMapping = {
- 'HC': 'HC',
- 'CO': 'CO',
- 'NO': 'NO',
- 'CO2': 'CO₂',
- 'O2': 'O₂',
- '油温': '油温',
- '转速': '转速',
- '气路压力': '气路压力',
- '过量空气系数': '过量空气系数',
- 'PEF值': 'PEF 值'
- };
- // 创建校验后的数据副本
- const validatedData = { ...parsedData };
- // 遍历解析后的数据并添加到表格
- for (const [key, value] of Object.entries(parsedData)) {
- if (parameterMapping[key]) {
- const displayName = parameterMapping[key];
- const config = conversionTable[displayName];
- if (config) {
- // 原始值
- let rawValue = value;
- // 根据转换规则转换为实际值
- let convertedValue = this.convertValue(rawValue, config);
- // 更新校验后的数据
- validatedData[key] = rawValue;
- // 最大值
- const maxValue = config.range[1];
- // 创建表格行
- const row = document.createElement('tr');
- row.dataset.parameter = key; // 保存参数名用于识别
- // 添加单元格
- row.innerHTML = `
- <td>${displayName}</td>
- <td contenteditable="true" data-raw-value="${rawValue}" data-parameter="${key}">${rawValue}</td>
- <td>${maxValue}${config.unit}</td>
- `;
- tbody.appendChild(row);
- // 为可编辑单元格添加事件监听器
- const editableCell = row.querySelector('[contenteditable]');
- editableCell.addEventListener('blur', (e) => {
- this.handleParameterEdit(e, key, config, bytes, validatedData);
- });
- editableCell.addEventListener('keydown', (e) => {
- if (e.key === 'Enter') {
- e.preventDefault();
- editableCell.blur();
- }
- });
- }
- }
- }
- // 重新计算校验和并将校验过的读数据添加至读数据编辑框
- this.recalculateChecksumAndApply(bytes, validatedData);
- }
- // 处理参数编辑事件
- handleParameterEdit(event, parameterKey, config, originalBytes, validatedData) {
- const cell = event.target;
- const newValue = parseInt(cell.textContent.trim());
- // 验证输入值
- if (isNaN(newValue)) {
- this.log('请输入有效的数字', 'error');
- // 恢复原始值
- cell.textContent = cell.dataset.rawValue;
- return;
- }
- // 检查值是否在有效范围内
- const [min, max] = config.range;
- let validatedValue = newValue;
- if (validatedValue < min) {
- validatedValue = min;
- this.log(`${parameterKey}值低于最小值,已自动调整为${min}`, 'warning');
- } else if (validatedValue > max) {
- validatedValue = max;
- this.log(`${parameterKey}值超过最大值,已自动调整为${max}`, 'warning');
- }
- // 更新显示值
- cell.textContent = validatedValue;
- cell.dataset.rawValue = validatedValue;
- // 更新校验后的数据
- validatedData[parameterKey] = validatedValue;
- // 重新计算校验和并更新到读数据编辑框
- this.recalculateChecksumAndApply(originalBytes, validatedData);
- }
- // 重新计算校验和并将校验过的数据更新到读数据编辑框
- recalculateChecksumAndApply(originalBytes, validatedData) {
- try {
- // 创建新的字节数组副本
- const newBytes = [...originalBytes];
- // 更新数据字段(根据validatedData)
- // CO₂ (索引3-4)
- if (validatedData.CO2 !== undefined) {
- newBytes[3] = (validatedData.CO2 >> 8) & 0xFF;
- newBytes[4] = validatedData.CO2 & 0xFF;
- }
- // CO (索引5-6)
- if (validatedData.CO !== undefined) {
- newBytes[5] = (validatedData.CO >> 8) & 0xFF;
- newBytes[6] = validatedData.CO & 0xFF;
- }
- // HC (索引7-8)
- if (validatedData.HC !== undefined) {
- newBytes[7] = (validatedData.HC >> 8) & 0xFF;
- newBytes[8] = validatedData.HC & 0xFF;
- }
- // NO (索引9-10)
- if (validatedData.NO !== undefined) {
- newBytes[9] = (validatedData.NO >> 8) & 0xFF;
- newBytes[10] = validatedData.NO & 0xFF;
- }
- // O₂ (索引11-12)
- if (validatedData.O2 !== undefined) {
- newBytes[11] = (validatedData.O2 >> 8) & 0xFF;
- newBytes[12] = validatedData.O2 & 0xFF;
- }
- // 油温 (索引13-14)
- if (validatedData.油温 !== undefined) {
- newBytes[13] = (validatedData.油温 >> 8) & 0xFF;
- newBytes[14] = validatedData.油温 & 0xFF;
- }
- // 转速 (索引15-16)
- if (validatedData.转速 !== undefined) {
- newBytes[15] = (validatedData.转速 >> 8) & 0xFF;
- newBytes[16] = validatedData.转速 & 0xFF;
- }
- // 气路压力 (索引17-18)
- if (validatedData.气路压力 !== undefined) {
- newBytes[17] = (validatedData.气路压力 >> 8) & 0xFF;
- newBytes[18] = validatedData.气路压力 & 0xFF;
- }
- // 过量空气系数 (索引19-20)
- if (validatedData.过量空气系数 !== undefined) {
- newBytes[19] = (validatedData.过量空气系数 >> 8) & 0xFF;
- newBytes[20] = validatedData.过量空气系数 & 0xFF;
- }
- // PEF值 (索引21-22)
- if (validatedData.PEF值 !== undefined) {
- newBytes[21] = (validatedData.PEF值 >> 8) & 0xFF;
- newBytes[22] = validatedData.PEF值 & 0xFF;
- }
- // 重新计算校验和 (CS=NOT(ACK+CMD+LB+[DF])+1)
- let checksum = 0x06 + 0xA3 + 0x17; // ACK + CMD + LB
- // 计算数据字段的和
- for (let i = 3; i < 23; i++) { // 从索引3到22的数据字段
- checksum += newBytes[i];
- }
- // 计算校验和: CS=NOT(ACK+CMD+LB+[DF])+1
- const newChecksum = (~checksum & 0xFF) + 1;
- newBytes[23] = newChecksum; // 更新校验和字段
- // 将校验过的数据转换为十六进制字符串并更新到读数据编辑框
- const validatedHexData = newBytes.map(byte => byte.toString(16).padStart(2, '0').toUpperCase()).join(' ');
- this.readData.value = validatedHexData;
- this.log('数据校验完成,校验和已重新计算并更新到读数据编辑框', 'success');
- } catch (error) {
- this.log(`重新计算校验和时出错: ${error.message}`, 'error');
- }
- }
- // 清除数据表格
- clearDataTable() {
- const tbody = this.dataTable.querySelector('tbody');
- tbody.innerHTML = ''; // 清空现有数据
- }
- }
- // 页面加载完成后初始化
- document.addEventListener('DOMContentLoaded', () => {
- new CommDebugger();
- });
|