背景:开发一个can报文发送工具,上位机界面使用wxpython搭建,通过拉动slider滑块实现报文发送线程自动转换slider滑块的数值成报文发送给开发板;通过勾选checkbox控件确定发送某一对象的报文,不勾选checkbox控件视为不需要发送或暂停发送某一对象的报文,对象报文的发送与否需要能够在报文发送线程执行过程中实时更新,为实现这一需求,主要采用定义一个全局字典来实时更新某一时刻需要发送报文的对象。
(1)定义一个全局字典msg_send_flag_dict,字典中对象的取值为1表示需要发送该对象的报文,取值为0表示不需要发送或暂停发送该对象的报文。
msg_send_flag_dict = dict()
for i in range(len(item_list)):
msg_send_flag_dict[item_list[i]] = 1
(2)根据上位机界面checkbox控件的选择,更新字典msg_send_flag_dict
def check_item_choice(self):
choice_item_list = []
for i in range(len(item_list)):
if self.set_checkbox_dict(i).IsChecked():
choice_item_list.append(item_list[i])
msg_send_flag_dict[item_list[i]] = 1
else:
msg_send_flag_dict[item_list[i]] = 0
return choice_item_list
(3)根据得到的checkbox勾选结果确认哪些对象需要发送报文
def SendMsg(self, event):
# 根据用户勾选checkbox结果确认需要发送哪些对象报文哪些不需要发送报文
choice_item_list = self.check_item_choice()
if len(choice_item_list) == 0:
mes_info = "取消所有勾选,没有需要发送报文的对象"
toastone = wx.MessageDialog(None, mes_info, "信息提示",
wx.YES_DEFAULT | wx.ICON_QUESTION)
if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮
toastone.Destroy() # 则关闭提示框
else:
# 获取报文发送的设备索引和通道号
self.working_can_device = 4
self.working_can_channel = self.m_choice1.GetSelection()
# 获取报文发送周期
self.msg_cycle = self.get_msg_cycle()
# 解析获取到的故障信息表格
self.get_operation_info()
# 连接can通讯
if self.onLink():
# 禁用其他控件
self.m_choice1.Disable()
self.m_choice2.Disable()
self.m_textCtrl1.Disable()
self.working_thread = WorkingMsgThread(frame_config_10ms, self.working_can_device, self.working_can_channel,
self.set_slider_dict, self.msg_cycle, self.operation_dict)
self.working_thread.start()
self.m_button2.SetLabel("停止")
self.m_button2.Bind(wx.EVT_LEFT_DOWN, self.onClose)
(4)执行报文发送线程
class WorkingMsgThread(Thread):
def __init__(self, tick_10ms_func, working_can_device, working_can_channel,
set_slider_dict, msg_cycle, operation_dict):
Thread.__init__(self)
self.Flag = True # 停止标志位
self.tick_10ms_func = tick_10ms_func
self.working_can_device = working_can_device
self.working_can_channel = working_can_channel
self.set_slider_dict = set_slider_dict
self.msg_cycle = msg_cycle
self.operation_dict = operation_dict
def setFlag(self): # 外部停止线程的操作函数
self.Flag = False # boolean
def run(self):
# 每隔second秒执行func函数
while self.Flag:
if any(msg_send_flag_dict.values()):
timer = Timer(0.01, self.tick_10ms_func)
timer.start()
# 获取每个对象的实际物理值
self.get_item_value_dict()
# 根据对象的物理值和报文解析规则确认需要发送的报文数据
self.get_item_msg()
# 将报文ID、分辨率、偏移、报文数据等信息拼接组成报文发送字典
self.get_msg_send_dict()
self.send_working_msg(self.working_can_device, self.working_can_channel)
timer.join()
else:
mes_info = "取消所有勾选,没有需要发送报文的对象"
toastone = wx.MessageDialog(None, mes_info, "信息提示",
wx.YES_DEFAULT | wx.ICON_QUESTION)
if toastone.ShowModal() == wx.ID_YES: # 如果点击了提示框的确定按钮
toastone.Destroy() # 则关闭提示框
break