我的程序有接收can数据并显示在tab1上的功能,但它的刷新逻辑有一点冗余,每次都全部重新显示。Frame_analoy_process和CanOBDdatarefresh这两个函数是修改的关键所在,一个是刷新界面的函数,一个是解析报文的函数,负责canobditemlist的更新。我希望程序仅仅在已有的canid中的数据变化或是有新的canid加入时才会更新数据 ,因此需要在更新canobditemlist的程序,也就是Frame_analoy_process中加入两种标识,一种是已有的新数据变化的标志位,一种是新id加入的标志位, if Listpos is not None:
CanOBDItemList[Listpos[0]] = CanItemData
else:
CanOBDItemList.append(CanItemData)在这一段中添加。当CanOBDdatarefresh识别到两种标志位的时候,才会刷新表格的对应行。
下面是完整的文件:
canobd:
# -*- coding: utf-8 -*-
import threading
# Form implementation generated from reading ui file 'CanOBD.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal,QTimer
from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem
from SerialPro import SerialPort as SerialThread
from SerialPro import CanOBDItemList
import time
import serial
import serial.tools.list_ports
class Ui_MainWindow(object):
def __init__(self):
# ...其他初始化代码...
self.updated_ids = set() # 存储数据变化的CAN ID
self.new_ids = set() # 存储新增的CAN ID
self.can_id_to_row = {} # 映射CAN ID到表格行号
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1220, 940)
font = QtGui.QFont()
font.setPointSize(12)
MainWindow.setFont(font)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
self.tabWidget.setGeometry(QtCore.QRect(0, 0, 1041, 940))
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.tableWidget = QtWidgets.QTableWidget(self.tab)
self.tableWidget.setGeometry(QtCore.QRect(0, 0, 1031, 940))
self.tableWidget.setObjectName("tableWidget")
self.tableWidget.setColumnCount(5)
self.tableWidget.setRowCount(150)
for num in range(0,150,1):
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setVerticalHeaderItem(num, item)
item = QtWidgets.QTableWidgetItem()
font = QtGui.QFont()
font.setKerning(False)
item.setFont(font)
for line in range(0,5,1):
self.tableWidget.setHorizontalHeaderItem(line, item)
item = QtWidgets.QTableWidgetItem()
self.tabWidget.addTab(self.tab, "")
self.tab_2 = QtWidgets.QWidget()
self.tab_2.setObjectName("CanOBD Cfg Set")
self.tabWidget.addTab(self.tab_2, "")
self.mComCfgBox = QtWidgets.QGroupBox(self.centralwidget)
self.mComCfgBox.setGeometry(QtCore.QRect(1040, 10, 191, 231))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mComCfgBox.setFont(font)
self.mComCfgBox.setObjectName("mComCfgBox")
self.mPortName = QtWidgets.QLabel(self.mComCfgBox)
self.mPortName.setGeometry(QtCore.QRect(20, 30, 61, 21))
self.mPortName.setObjectName("mPortName")
self.mBpsName = QtWidgets.QLabel(self.mComCfgBox)
self.mBpsName.setGeometry(QtCore.QRect(20, 60, 61, 21))
self.mBpsName.setObjectName("mBpsName")
self.mDatabitName = QtWidgets.QLabel(self.mComCfgBox)
self.mDatabitName.setGeometry(QtCore.QRect(20, 90, 61, 21))
self.mDatabitName.setObjectName("mDatabitName")
self.mStopName = QtWidgets.QLabel(self.mComCfgBox)
self.mStopName.setGeometry(QtCore.QRect(20, 120, 61, 21))
self.mStopName.setObjectName("mStopName")
self.mOddName = QtWidgets.QLabel(self.mComCfgBox)
self.mOddName.setGeometry(QtCore.QRect(20, 150, 61, 21))
self.mOddName.setObjectName("mOddName")
self.mDatabitVal = QtWidgets.QLabel(self.mComCfgBox)
self.mDatabitVal.setGeometry(QtCore.QRect(100, 90, 54, 21))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mDatabitVal.setFont(font)
self.mDatabitVal.setLayoutDirection(QtCore.Qt.LeftToRight)
self.mDatabitVal.setAlignment(QtCore.Qt.AlignCenter)
self.mDatabitVal.setObjectName("mDatabitVal")
self.mStopBitVal = QtWidgets.QLabel(self.mComCfgBox)
self.mStopBitVal.setGeometry(QtCore.QRect(100, 120, 54, 21))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mStopBitVal.setFont(font)
self.mStopBitVal.setLayoutDirection(QtCore.Qt.LeftToRight)
self.mStopBitVal.setAlignment(QtCore.Qt.AlignCenter)
self.mStopBitVal.setObjectName("mStopBitVal")
self.mOddVal = QtWidgets.QLabel(self.mComCfgBox)
self.mOddVal.setGeometry(QtCore.QRect(100, 150, 54, 21))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mOddVal.setFont(font)
self.mOddVal.setLayoutDirection(QtCore.Qt.LeftToRight)
self.mOddVal.setAlignment(QtCore.Qt.AlignCenter)
self.mOddVal.setObjectName("mOddVal")
self.mPortVal = QtWidgets.QComboBox(self.mComCfgBox)
self.mPortVal.setGeometry(QtCore.QRect(90, 30, 81, 22))
self.mPortVal.setObjectName("mPortVal")
self.mPortVal.addItem("")
self.mPortVal.addItem("")
self.mPortVal.addItem("")
self.mPortVal.addItem("")
self.mPortVal.addItem("")
self.mPortVal.addItem("")
self.mBPSVal = QtWidgets.QComboBox(self.mComCfgBox)
self.mBPSVal.setGeometry(QtCore.QRect(90, 60, 81, 22))
self.mBPSVal.setObjectName("mBPSVal")
self.mBPSVal.addItem("")
self.mBPSVal.addItem("")
self.mBPSVal.addItem("")
self.mBPSVal.addItem("")
self.mBPSVal.addItem("")
self.mBPSVal.addItem("")
self.mOpenSerial = QtWidgets.QDialogButtonBox(self.mComCfgBox)
self.mOpenSerial.setGeometry(QtCore.QRect(20, 190, 156, 31))
self.mOpenSerial.setStandardButtons(QtWidgets.QDialogButtonBox.Close|QtWidgets.QDialogButtonBox.Open)
self.mOpenSerial.setObjectName("mOpenSerial")
self.mCycleCfgBox = QtWidgets.QGroupBox(self.centralwidget)
self.mCycleCfgBox.setGeometry(QtCore.QRect(1040, 260, 191, 221))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mCycleCfgBox.setFont(font)
self.mCycleCfgBox.setObjectName("mCycleCfgBox")
self.mcheck1000ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck1000ms.setGeometry(QtCore.QRect(20, 180, 141, 31))
self.mcheck1000ms.setObjectName("mcheck1000ms")
self.mcheck500ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck500ms.setGeometry(QtCore.QRect(20, 150, 141, 31))
self.mcheck500ms.setObjectName("mcheck500ms")
self.mcheck100ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck100ms.setGeometry(QtCore.QRect(20, 90, 141, 31))
self.mcheck100ms.setObjectName("mcheck100ms")
self.mcheck50ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck50ms.setGeometry(QtCore.QRect(20, 60, 141, 31))
self.mcheck50ms.setObjectName("mcheck50ms")
self.mcheck20ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck20ms.setGeometry(QtCore.QRect(20, 30, 141, 31))
self.mcheck20ms.setObjectName("mcheck20ms")
self.mcheck200ms = QtWidgets.QCheckBox(self.mCycleCfgBox)
self.mcheck200ms.setGeometry(QtCore.QRect(20, 120, 141, 31))
self.mcheck200ms.setObjectName("mcheck200ms")
self.mEventSigBox = QtWidgets.QGroupBox(self.centralwidget)
self.mEventSigBox.setGeometry(QtCore.QRect(1050, 490, 191, 151))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mEventSigBox.setFont(font)
self.mEventSigBox.setObjectName("mEventSigBox")
self.radioLeftREvent = QtWidgets.QRadioButton(self.mEventSigBox)
self.radioLeftREvent.setGeometry(QtCore.QRect(10, 30, 151, 16))
self.radioLeftREvent.setObjectName("radioLeftREvent")
self.radioKiilEvent = QtWidgets.QRadioButton(self.mEventSigBox)
self.radioKiilEvent.setGeometry(QtCore.QRect(10, 90, 151, 16))
self.radioKiilEvent.setObjectName("radioKiilEvent")
self.radioPEvent = QtWidgets.QRadioButton(self.mEventSigBox)
self.radioPEvent.setGeometry(QtCore.QRect(10, 120, 151, 16))
self.radioPEvent.setObjectName("radioPEvent")
self.radioOpenCloseEvent = QtWidgets.QRadioButton(self.mEventSigBox)
self.radioOpenCloseEvent.setGeometry(QtCore.QRect(10, 60, 151, 16))
self.radioOpenCloseEvent.setObjectName("radioOpenCloseEvent")
self.mReadOBDinfBox = QtWidgets.QGroupBox(self.centralwidget)
self.mReadOBDinfBox.setGeometry(QtCore.QRect(1050, 660, 191, 171))
font = QtGui.QFont()
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.mReadOBDinfBox.setFont(font)
self.mReadOBDinfBox.setObjectName("mReadOBDinfBox")
self.radioVinRead = QtWidgets.QRadioButton(self.mReadOBDinfBox)
self.radioVinRead.setGeometry(QtCore.QRect(10, 40, 141, 21))
self.radioVinRead.setObjectName("radioVinRead")
self.mVinInfShow = QtWidgets.QTextBrowser(self.mReadOBDinfBox)
self.mVinInfShow.setGeometry(QtCore.QRect(10, 70, 171, 91))
self.mVinInfShow.setObjectName("mVinInfShow")
MainWindow.setCentralWidget(self.centralwidget)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
self.tabWidget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
for num in range(0, 150, 1):
item = self.tableWidget.verticalHeaderItem(num)
item.setText(_translate("MainWindow", str(num +1)))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("MainWindow", "时间标识"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("MainWindow", "帧ID"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("MainWindow", "帧类型"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("MainWindow", "长度"))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("MainWindow", "数据 (BIT7--BIT0 大端模式)"))
self.tableWidget.setColumnWidth(0, 200)
self.tableWidget.setColumnWidth(1, 150)
self.tableWidget.setColumnWidth(4,450)
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "CanOBD Inf Show"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "CanOBD Cfg Set"))
self.mComCfgBox.setTitle(_translate("MainWindow", "串口配置"))
self.mPortName.setText(_translate("MainWindow", "端口号"))
self.mBpsName.setText(_translate("MainWindow", "波特率"))
self.mDatabitName.setText(_translate("MainWindow", "数据位"))
self.mStopName.setText(_translate("MainWindow", "停止位"))
self.mOddName.setText(_translate("MainWindow", "检验位"))
self.mDatabitVal.setText(_translate("MainWindow", "8"))
self.mStopBitVal.setText(_translate("MainWindow", "1"))
self.mOddVal.setText(_translate("MainWindow", "无"))
self.mBPSVal.setItemText(0, _translate("MainWindow", "9600"))
self.mBPSVal.setItemText(1, _translate("MainWindow", "19200"))
self.mBPSVal.setItemText(2, _translate("MainWindow", "115200"))
self.mBPSVal.setItemText(3, _translate("MainWindow", "230400"))
self.mBPSVal.setItemText(4, _translate("MainWindow", "256000"))
self.mBPSVal.setItemText(5, _translate("MainWindow", "460800"))
port_list = list(serial.tools.list_ports.comports())
if port_list.__len__() is not 0:
for num in range(port_list.__len__()):
self.mPortVal.setItemText(num, _translate("MainWindow", str(port_list[num].device)))
serialport = self.mPortVal.currentText()
serialbaudrate = self.mBPSVal.currentText()
self.LSerial = SerialThread(serialport, serialbaudrate)
self.mCycleCfgBox.setTitle(_translate("MainWindow", "过滤设置(周期)"))
self.mcheck1000ms.setText(_translate("MainWindow", "1000ms 周期"))
self.mcheck500ms.setText(_translate("MainWindow", "500ms 周期"))
self.mcheck100ms.setText(_translate("MainWindow", "100ms 周期"))
self.mcheck50ms.setText(_translate("MainWindow", "50ms 周期"))
self.mcheck20ms.setText(_translate("MainWindow", "20ms 周期"))
self.mcheck200ms.setText(_translate("MainWindow", "200ms 周期"))
self.mEventSigBox.setTitle(_translate("MainWindow", "事件信号策略"))
self.radioLeftREvent.setText(_translate("MainWindow", "左右转 事件"))
self.radioKiilEvent.setText(_translate("MainWindow", "刹车 事件"))
self.radioPEvent.setText(_translate("MainWindow", "档位 事件"))
self.radioOpenCloseEvent.setText(_translate("MainWindow", "开关门 事件"))
self.mReadOBDinfBox.setTitle(_translate("MainWindow", "主动读取信息"))
self.radioVinRead.setText(_translate("MainWindow", "VIN 信息"))
def OpenSerial(self):
if self.LSerial != None:
if self.LSerial.SerialIsOpen():
self.LSerial.__del__()
port_list = list(serial.tools.list_ports.comports())
if port_list.__len__() != 0:
serialport = self.mPortVal.currentText()
serialbaudrate = self.mBPSVal.currentText()
self.LSerial.__init__(serialport,serialbaudrate)
# 开启线程
self.thread = Worker() # 创建线程对象
self.thread.update_signal.connect(self.CanOBDdatarefresh) # 连接信号和槽
self.thread.update_signal.connect(self.LSerial.Com_read_frame) # 连接信号和槽
self.thread.start() # 启动线程
#self.LSerial.Com_read_frame()
def CloseSerial(self):
if self.LSerial.SerialIsOpen():
self.LSerial.close()
def Serialconnectslot(self):
self.mOpenSerial.accepted.connect(self.OpenSerial)
self.mOpenSerial.rejected.connect(self.CloseSerial)
def get_checked_cycles(self):
"""返回用户勾选的所有周期值(毫秒)"""
checked_cycles = []
if self.mcheck20ms.isChecked():
checked_cycles.append(10)
if self.mcheck50ms.isChecked():
checked_cycles.append(50)
if self.mcheck100ms.isChecked():
checked_cycles.append(100)
if self.mcheck200ms.isChecked():
checked_cycles.append(200)
if self.mcheck500ms.isChecked():
checked_cycles.append(500)
if self.mcheck1000ms.isChecked():
checked_cycles.append(1000)
return checked_cycles
def CanOBDdatarefresh(self):
# 检查数据接收是否超时(1秒阈值)
current_time = time.time()
if current_time - self.LSerial.last_data_time > 1.0:
# 清空缓冲区并跳过刷新
global frame_buffer
frame_buffer = bytearray()
return
filtered_cycles = self.get_checked_cycles()
# 清空表格旧数据(保留表头)
for row in range(self.tableWidget.rowCount()):
for col in range(self.tableWidget.columnCount()):
item = self.tableWidget.item(row, col)
if item:
item.setText("")
row_index = 0
for indexitem in CanOBDItemList:
can_id = indexitem[1]
# 周期过滤逻辑
if can_id in self.LSerial.cycle_dict:
cycle = self.LSerial.cycle_dict[can_id]
# 检查是否在过滤周期范围内(±10%容差)
skip = False
for filtered_cycle in filtered_cycles:
tolerance = filtered_cycle * 0.1 # 10%容差
if abs(cycle - filtered_cycle) <= tolerance:
skip = True
break
if skip:
continue # 跳过这个帧
# 显示数据
self.tableWidget.setItem(row_index, 0, QtWidgets.QTableWidgetItem(str(indexitem[0])))
self.tableWidget.setItem(row_index, 1, QtWidgets.QTableWidgetItem(str(indexitem[1])))
self.tableWidget.setItem(row_index, 2, QtWidgets.QTableWidgetItem(str(indexitem[2])))
self.tableWidget.setItem(row_index, 3, QtWidgets.QTableWidgetItem(str(indexitem[3])))
self.tableWidget.setItem(row_index, 4, QtWidgets.QTableWidgetItem(str(indexitem[4])))
row_index += 1
self.tableWidget.show()
class Worker(QThread):
update_signal = pyqtSignal(int) # 定义一个信号,用于传递更新信息到主线程
def run(self):
# 模拟耗时操作
while True:
time.sleep(0.01)
self.update_signal.emit(1) # 发射信号,传递更新信息
serialpro文件:
import serial
import time
import struct
from datetime import datetime
CanOBDItemList = [[0,0,0,0,0]]
Frame_start = b'\xFF'
Frame_end = b'\x55'
Frame_data_style_len = 6
Frame_Data_Len = 0
frame_buffer = bytearray()
class CanInfShow_Item:
def __int__(self,CanID,CanFramType,Len,CanDataInf):
self.SystemCycle = datetime.strftime("%Y-%m-%d %H:%M:%S.%f")[:-3],
self.CanID = CanID,
self.CanFrame = CanFramType,
self.CanDataLen = Len,
self.CanData = CanDataInf
class SerialPort:
def __init__(self, port, baudrate):
# 初始化串口参数
self.port = port
self.baudrate = baudrate
self.ser = serial.Serial(
port=self.port,
baudrate=self.baudrate,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE
)
# 等待串口连接稳定
self.last_data_time = time.time() # 新增:最后接收数据的时间戳
self.cycle_dict = {} # 存储{帧ID: [上次时间戳, 当前周期]}
self.last_frame_time = {} # 存储每个ID的最后出现时间
time.sleep(0.2)
if not self.ser.isOpen():
print("串口打开失败!")
def close(self):
# 关闭串口连接
if self.ser.isOpen():
self.ser.close()
def send(self, data):
# 发送数据
if self.ser.isOpen():
try:
self.ser.write(data.encode('utf-8'))
except serial.SerialException as e:
print(f"发送数据失败: {e}")
def recv(self):
# 接收数据
if self.ser.isOpen():
data = self.ser.read(self.ser.inWaiting())
if data: # 有数据时更新时间戳
self.last_data_time = time.time()
return data
def __del__(self):
self.close()
def SerialIsOpen(self):
if self.ser.isOpen():
return 1
else:
return 0
def Frame_check_sum(self,data,len):
checksum = b'0'
dataval = data[:len]
checksum = sum(dataval)
checksum %= 0x100
return checksum
# 发送数据并接收响应
def Com_read_frame(self):
global frame_buffer
global Frame_Data_Len
byte = self.recv()
if not byte: # 无新数据直接返回
return
if byte:
frame_buffer.extend(byte)
if len(frame_buffer) > Frame_data_style_len:
if Frame_start in frame_buffer and Frame_end in frame_buffer:
Frame_start_index = frame_buffer.find(Frame_start)
Frame_end_index = frame_buffer.find(Frame_end)
if Frame_start_index + 1 == Frame_end_index:
Frame_Data_Len = int(frame_buffer[Frame_start_index + 3] * 0x100) + int(frame_buffer[Frame_start_index + 2])
frame_buffer = frame_buffer[Frame_start_index: Frame_start_index + len(frame_buffer)]
Frame_start_index = 0
elif Frame_end_index < Frame_start_index:
frame_buffer = frame_buffer[Frame_start_index: Frame_start_index + len(frame_buffer)]
Frame_start_index = 0
if len(frame_buffer) >= Frame_Data_Len + 5:
checksum = self.Frame_check_sum(frame_buffer[Frame_start_index + 2:Frame_start_index + 2 + Frame_Data_Len + 2],Frame_Data_Len + 4)
if checksum == frame_buffer[Frame_start_index + Frame_Data_Len + 4]:
frame_procee = frame_buffer[Frame_start_index:Frame_start_index + Frame_Data_Len + 5]
#处理帧数据信息
self.Frame_analoy_process(frame_procee)
if (len(frame_buffer) == Frame_start_index + Frame_Data_Len + 5):
frame_buffer.clear()
else:
frame_buffer = frame_buffer[Frame_start_index + Frame_Data_Len + 6:len(frame_buffer) - 1]
Frame_Data_Len = 0
else:
frame_buffer = frame_buffer[Frame_start_index + Frame_Data_Len + 6:] # 移除已处理的数据,为下一帧做准备
Frame_Data_Len = 0
#报文解析
def Frame_analoy_process(self, Framedata):
# 检查帧类型 (0x0C 0x98)
if len(Framedata) < 8 or Framedata[4] != 0x0C or Framedata[5] != 0x98:
return
try:
FrameNum = int(Framedata[7])
except IndexError:
return
# 检查是否有足够数据
if len(Framedata) < 12 * FrameNum + 8:
return
current_time = time.time() # 获取当前精确时间戳
for index in range(FrameNum):
# 时间戳
Cantime = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
# 提取ID字节
try:
id_bytes = [
Framedata[12 * index + 11], # LSB
Framedata[12 * index + 10],
Framedata[12 * index + 9],
Framedata[12 * index + 8] # MSB
]
except IndexError:
continue
# 格式化为8位大写十六进制
CanID = ''.join(format(b, '02X') for b in id_bytes)
CanFramType = "Cycle"
Len = 8
# 提取数据部分
try:
CanDataSpace = ' '.join(
format(Framedata[12 * index + 12 + posindex], '02X')
for posindex in range(8)
)
except IndexError:
continue
CanItemData = [Cantime, CanID, CanFramType, Len, CanDataSpace]
if CanID in self.last_frame_time:
last_time = self.last_frame_time[CanID]
cycle = (current_time - last_time) * 1000 # 转换为毫秒
# 平滑处理:使用加权平均减少抖动
if CanID in self.cycle_dict:
old_cycle = self.cycle_dict[CanID]
self.cycle_dict[CanID] = 0.7 * old_cycle + 0.3 * cycle
else:
self.cycle_dict[CanID] = cycle
else:
self.cycle_dict[CanID] = 0 # 首次出现,周期设为0
self.last_frame_time[CanID] = current_time
# 更新列表
if not CanOBDItemList or CanOBDItemList[0][0] == 0:
if CanOBDItemList and CanOBDItemList[0][0] == 0:
CanOBDItemList.pop(0)
CanOBDItemList.insert(0, CanItemData)
else:
Listpos = self.find_in_2d_list(CanOBDItemList, CanID)
if Listpos is not None:
CanOBDItemList[Listpos[0]] = CanItemData
else:
CanOBDItemList.append(CanItemData)
self.last_data_time = time.time() # 解析到有效帧时更新时间
def find_in_2d_list(self,matrix, target):
for i, row in enumerate(matrix):
if any(x == target for x in row):
return (i, row.index(target)) # 使用row.index()找到具体列的索引
return None
最新发布