pyqt5通过CANoe COM Server来操作CANoe仿真工程

news/2024/4/25 20:52:45/文章来源:https://blog.csdn.net/jianxuezixuan/article/details/129204419

文章目录

  • 前言
  • 一、COM接口技术
  • 二、UI界面设计
  • 三、功能实现
  • 四、工程运行测试


前言

继续学习《CANoe开发从入门到精通》。
今天在《CANoe仿真工程开发》的基础上,开发实现pyqt5应用程序来操控CANoe工程。

一、COM接口技术

COM(Component Object Model,组件对象模型)是一种描述如何建立可动态互变组件的规范,此规范提供了为保证能够互相操作,客户端和组件应遵循的一些二进制和网络标准。通过这种标准将可以在任意两个组件之间进行通信,而不用考虑其所处的操作环境是否相同、使用的开发语言是否一致以及是否运行于同一台计算机。

从早期版本开始,CANoe就开始支持COM接口技术。通过COM Server可以实现以下功能:
(1)创建和修改CANoe的配置;
(2)实现测量的自动控制,如工程加载、开始或结束测量、开始测试模块等;
(3)与外部应用软件的数据交换,如读写信号、系统变量等;
(4)开发用户的自定义面板,实现自动化测试;
(5)远程控制CANoe进行测量;
(6)调用CANoe中自定义的CAPL函数。
CANoe COM Server对于大家熟悉的编程语言或脚本语言都有很好的支持,例如Visual Basic、Delphi、C/C++、C#、Python、LabVIEW、VBScript、JScript、Perl和VBA等。

在CANoe安装时,COM Server已经注册好了。如果安装文件夹有变,或者目前注册的CANoe版本不是用户所期望的。可以直接找到CANoe 的安装文件夹( 例 如 CANoe 16 SP4 64-bit 安 装 文 件 夹 D:\Program Files\Vector CANoe 16\Exec64 ) , 执 行RegisterComponents.exe。

二、UI界面设计

1、Pycharm新建工程;

2、右键,找到"External Tools",选择QT Designer,进入QT5的UI设计界面
在这里插入图片描述
3、添加相应的控件、设置好参数。最终的UI界面如下:
在这里插入图片描述
在这里插入图片描述

设计完成后,保存为CanoeDemo.ui。

4、回到PyCharm工程,CanoeDemo.ui文件,然后右键,找到"External Tools",选择PyUIC,将UI设计文件转换为CanoeDemo.py文件。
在这里插入图片描述
CanoeDemo.py文件如下:

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'CanoeDemo.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# 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, QtWidgetsclass Ui_CanoeDemo(object):def setupUi(self, CanoeDemo):CanoeDemo.setObjectName("CanoeDemo")CanoeDemo.resize(633, 508)CanoeDemo.setMouseTracking(True)CanoeDemo.setTabletTracking(True)CanoeDemo.setAutoFillBackground(True)self.groupBox = QtWidgets.QGroupBox(CanoeDemo)self.groupBox.setGeometry(QtCore.QRect(10, 0, 531, 111))self.groupBox.setObjectName("groupBox")self.lineEdit = QtWidgets.QLineEdit(self.groupBox)self.lineEdit.setGeometry(QtCore.QRect(20, 20, 401, 20))self.lineEdit.setObjectName("lineEdit")self.OpenButton = QtWidgets.QPushButton(self.groupBox)self.OpenButton.setGeometry(QtCore.QRect(440, 20, 75, 23))self.OpenButton.setObjectName("OpenButton")self.StartButton = QtWidgets.QPushButton(self.groupBox)self.StartButton.setGeometry(QtCore.QRect(170, 60, 75, 23))self.StartButton.setObjectName("StartButton")self.AutoButton = QtWidgets.QPushButton(self.groupBox)self.AutoButton.setGeometry(QtCore.QRect(300, 60, 75, 23))self.AutoButton.setObjectName("AutoButton")self.groupBox_2 = QtWidgets.QGroupBox(CanoeDemo)self.groupBox_2.setGeometry(QtCore.QRect(10, 120, 531, 191))self.groupBox_2.setTabletTracking(True)self.groupBox_2.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)self.groupBox_2.setAcceptDrops(True)self.groupBox_2.setObjectName("groupBox_2")self.LockButton = QtWidgets.QPushButton(self.groupBox_2)self.LockButton.setGeometry(QtCore.QRect(10, 30, 75, 23))self.LockButton.setObjectName("LockButton")self.UnlockButton = QtWidgets.QPushButton(self.groupBox_2)self.UnlockButton.setGeometry(QtCore.QRect(90, 30, 75, 23))self.UnlockButton.setObjectName("UnlockButton")self.Driver1Button = QtWidgets.QPushButton(self.groupBox_2)self.Driver1Button.setGeometry(QtCore.QRect(10, 60, 75, 23))self.Driver1Button.setObjectName("Driver1Button")self.Driver2Button = QtWidgets.QPushButton(self.groupBox_2)self.Driver2Button.setGeometry(QtCore.QRect(90, 60, 75, 23))self.Driver2Button.setObjectName("Driver2Button")self.LeftButton = QtWidgets.QPushButton(self.groupBox_2)self.LeftButton.setGeometry(QtCore.QRect(10, 110, 75, 23))self.LeftButton.setObjectName("LeftButton")self.RightButton = QtWidgets.QPushButton(self.groupBox_2)self.RightButton.setGeometry(QtCore.QRect(90, 110, 75, 23))self.RightButton.setObjectName("RightButton")self.HazardButton = QtWidgets.QPushButton(self.groupBox_2)self.HazardButton.setGeometry(QtCore.QRect(50, 140, 75, 23))self.HazardButton.setObjectName("HazardButton")self.IgniSlider = QtWidgets.QSlider(self.groupBox_2)self.IgniSlider.setGeometry(QtCore.QRect(300, 20, 22, 160))self.IgniSlider.setMaximum(3)self.IgniSlider.setPageStep(1)self.IgniSlider.setOrientation(QtCore.Qt.Vertical)self.IgniSlider.setObjectName("IgniSlider")self.GearSlider = QtWidgets.QSlider(self.groupBox_2)self.GearSlider.setGeometry(QtCore.QRect(430, 20, 22, 160))self.GearSlider.setMouseTracking(False)self.GearSlider.setTabletTracking(True)self.GearSlider.setMaximum(3)self.GearSlider.setPageStep(1)self.GearSlider.setProperty("value", 0)self.GearSlider.setSliderPosition(0)self.GearSlider.setOrientation(QtCore.Qt.Vertical)self.GearSlider.setObjectName("GearSlider")self.label = QtWidgets.QLabel(self.groupBox_2)self.label.setGeometry(QtCore.QRect(460, 170, 54, 12))self.label.setObjectName("label")self.label_2 = QtWidgets.QLabel(self.groupBox_2)self.label_2.setGeometry(QtCore.QRect(460, 120, 54, 12))self.label_2.setObjectName("label_2")self.label_3 = QtWidgets.QLabel(self.groupBox_2)self.label_3.setGeometry(QtCore.QRect(460, 70, 54, 12))self.label_3.setObjectName("label_3")self.label_4 = QtWidgets.QLabel(self.groupBox_2)self.label_4.setGeometry(QtCore.QRect(460, 20, 54, 12))self.label_4.setObjectName("label_4")self.label_5 = QtWidgets.QLabel(self.groupBox_2)self.label_5.setGeometry(QtCore.QRect(400, 20, 31, 16))self.label_5.setObjectName("label_5")self.label_6 = QtWidgets.QLabel(self.groupBox_2)self.label_6.setGeometry(QtCore.QRect(330, 70, 54, 12))self.label_6.setObjectName("label_6")self.label_7 = QtWidgets.QLabel(self.groupBox_2)self.label_7.setGeometry(QtCore.QRect(250, 20, 54, 12))self.label_7.setObjectName("label_7")self.label_8 = QtWidgets.QLabel(self.groupBox_2)self.label_8.setGeometry(QtCore.QRect(330, 20, 54, 12))self.label_8.setObjectName("label_8")self.label_9 = QtWidgets.QLabel(self.groupBox_2)self.label_9.setGeometry(QtCore.QRect(330, 170, 54, 12))self.label_9.setObjectName("label_9")self.label_10 = QtWidgets.QLabel(self.groupBox_2)self.label_10.setGeometry(QtCore.QRect(330, 120, 54, 12))self.label_10.setObjectName("label_10")self.groupBox_3 = QtWidgets.QGroupBox(CanoeDemo)self.groupBox_3.setGeometry(QtCore.QRect(10, 320, 531, 121))self.groupBox_3.setObjectName("groupBox_3")self.label_11 = QtWidgets.QLabel(self.groupBox_3)self.label_11.setGeometry(QtCore.QRect(20, 30, 91, 16))self.label_11.setObjectName("label_11")self.label_12 = QtWidgets.QLabel(self.groupBox_3)self.label_12.setGeometry(QtCore.QRect(20, 80, 81, 16))self.label_12.setObjectName("label_12")self.VehSlider = QtWidgets.QSlider(self.groupBox_3)self.VehSlider.setGeometry(QtCore.QRect(110, 30, 160, 22))self.VehSlider.setMaximum(220)self.VehSlider.setSingleStep(5)self.VehSlider.setPageStep(10)self.VehSlider.setOrientation(QtCore.Qt.Horizontal)self.VehSlider.setObjectName("VehSlider")self.EngSlider = QtWidgets.QSlider(self.groupBox_3)self.EngSlider.setGeometry(QtCore.QRect(110, 80, 160, 22))self.EngSlider.setMaximum(5000)self.EngSlider.setSingleStep(10)self.EngSlider.setPageStep(40)self.EngSlider.setOrientation(QtCore.Qt.Horizontal)self.EngSlider.setObjectName("EngSlider")self.VehSpeedEdit = QtWidgets.QLineEdit(self.groupBox_3)self.VehSpeedEdit.setGeometry(QtCore.QRect(290, 30, 113, 20))self.VehSpeedEdit.setObjectName("VehSpeedEdit")self.EngSpeedEdit = QtWidgets.QLineEdit(self.groupBox_3)self.EngSpeedEdit.setGeometry(QtCore.QRect(290, 80, 113, 20))self.EngSpeedEdit.setObjectName("EngSpeedEdit")self.label_13 = QtWidgets.QLabel(self.groupBox_3)self.label_13.setGeometry(QtCore.QRect(420, 32, 54, 20))self.label_13.setObjectName("label_13")self.label_14 = QtWidgets.QLabel(self.groupBox_3)self.label_14.setGeometry(QtCore.QRect(420, 80, 54, 20))self.label_14.setObjectName("label_14")self.retranslateUi(CanoeDemo)QtCore.QMetaObject.connectSlotsByName(CanoeDemo)def retranslateUi(self, CanoeDemo):_translate = QtCore.QCoreApplication.translateCanoeDemo.setWindowTitle(_translate("CanoeDemo", "Form"))self.groupBox.setTitle(_translate("CanoeDemo", "应用控制"))self.OpenButton.setText(_translate("CanoeDemo", "打开CANoe"))self.StartButton.setText(_translate("CanoeDemo", "开始测量"))self.AutoButton.setText(_translate("CanoeDemo", "自动测量"))self.groupBox_2.setTitle(_translate("CanoeDemo", "系统变量"))self.LockButton.setText(_translate("CanoeDemo", "Lock"))self.UnlockButton.setText(_translate("CanoeDemo", "Unlock"))self.Driver1Button.setText(_translate("CanoeDemo", "Driver1"))self.Driver2Button.setText(_translate("CanoeDemo", "Driver2"))self.LeftButton.setText(_translate("CanoeDemo", "Leftturn"))self.RightButton.setText(_translate("CanoeDemo", "Rightturn"))self.HazardButton.setText(_translate("CanoeDemo", "Hazard"))self.label.setText(_translate("CanoeDemo", "P"))self.label_2.setText(_translate("CanoeDemo", "R"))self.label_3.setText(_translate("CanoeDemo", "N"))self.label_4.setText(_translate("CanoeDemo", "D"))self.label_5.setText(_translate("CanoeDemo", "Gear:"))self.label_6.setText(_translate("CanoeDemo", "RUN"))self.label_7.setText(_translate("CanoeDemo", "Ignition:"))self.label_8.setText(_translate("CanoeDemo", "CRANK"))self.label_9.setText(_translate("CanoeDemo", "OFF"))self.label_10.setText(_translate("CanoeDemo", "K15"))self.groupBox_3.setTitle(_translate("CanoeDemo", "GroupBox"))self.label_11.setText(_translate("CanoeDemo", "Vehicle Speed:"))self.label_12.setText(_translate("CanoeDemo", "Engine Speed:"))self.label_13.setText(_translate("CanoeDemo", "km/h"))self.label_14.setText(_translate("CanoeDemo", "rpm"))

到此,界面设计完成。

三、功能实现

1、通过打开CANoe按钮实现CANoe文件的选择、打开、和关闭。代码如下:

    def open_cfg(self):if self.OpenButton.text() == "打开CANoe":openfile_name = QFileDialog.getOpenFileName(self,'选择文件','','(*.cfg)')file_name = openfile_name[0]if file_name:print(file_name)self.App.Open(file_name)self.lineEdit.setText(file_name)else:print("Open CANoe error")self.OpenButton.setText("退出CANoe")elif self.OpenButton.text() == "退出CANoe":if self.App != None:self.App.Quit()self.App = Noneself.OpenButton.setText("打开CANoe")

实现效果如下:
在这里插入图片描述
2、开始测量按钮,实现仿真测试的开始、关闭。代码如下:

    def start(self):if self.StartButton.text() == "开始测量":self.App.Measurement.Start()self.StartButton.setText("停止测量")elif self.StartButton.text() == "停止测量":self.App.Measurement.Stop()self.StartButton.setText("开始测量")

3、其他按钮,主要实现操作总线信号和系统变量来实现控制CANoe的信号和系统变量。比如Lock按钮,先读取系统变量Lock_Car的值,再来设置它的值。代码如下:

    def lock(self):if(self.get_SysVar("Vehicle_Key","Lock_Car")==0):self.set_SysVar("Vehicle_Key","Lock_Car",1)time.sleep(1)self.set_SysVar("Vehicle_Key", "Lock_Car", 0)else:time.sleep(1)self.set_SysVar("Vehicle_Key", "Lock_Car", 0)

实现了UI这边点击一下Lock按钮,CANoe的钥匙上Lock图标变红,一秒后恢复。

4、自动测量,这个通过一个按钮实现了CANoe的Automation Sequences功能。
在这里插入图片描述
可以看后面的演示视频,Vehicle(Automation Sequences)的RepeatSequence periodically图标和Start Sequence on measurement start图标(如上红框)并未选中,就依次实现了上面的功能。

5、获取和设置系统变量,代码如下:

    def get_SysVar(self, ns_name, sys_name):if self.App != None:systemCAN = self.App.System.Namespacessys_namespace = systemCAN(ns_name)sys_value = sys_namespace.Variables(sys_name)return sys_value.Valueelse:print("Unable to get EnvVar")def set_SysVar(self, ns_name, sys_name, value):if self.App != None:systemCAN = self.App.System.Namespacessys_namespace = systemCAN(ns_name)sys_value = sys_namespace.Variables(sys_name)sys_value.Value = valueelse:print("Unable to set EnvVar")

四、工程运行测试

编译运行工程,然后开始测试,演示结果如下:

Python调用CANoe

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73660.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue-cli引入wangEditor、Element,封装可上传附件的富文本编辑器组件(附源代码直接应用,菜单可调整)

关于Element安装引入,请参考我的另一篇文章:vue-cli引入Element Plus(element-ui),修改主题变量,定义全局样式_shawxlee的博客-CSDN博客_chalk variables 1、安装wangeditor npm i wangeditor --savewangE…

【OpenFOAM】-olaFlow-算例10-wavemakerTank

算例路径: olaFlow\tutorials\wavemakerTank 算例描述: 采用 Flap和Piston两种方式的动网格进行造波 学习目标: 了解 olaDyMFlow 的使用;理解动网格使用和参数设置,理解 dynamicMotionSolverFvMesh 参数设置&#xff1…

【华为OD机试模拟题】用 C++ 实现 - 环中最长子串(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

【Linux修炼】14.磁盘结构/文件系统/软硬链接/动静态库

每一个不曾起舞的日子,都是对生命的辜负。 磁盘结构/文件系统/软硬链接/动静态库前言一.磁盘结构1.1 磁盘的物理结构1.2 磁盘的存储结构1.3 磁盘的逻辑结构二.理解文件系统2.1 对IO单位的优化2.2 磁盘分区与分组2.3 分组的管理方法2.4 文件操作三.软硬链接3.1理解硬…

vue手写日历

<template><div class"page">输入月份数字<input v-model"inputVal" type"text"><button click"change">点击</button><ul class"calendar"><li class"header">{{new …

记忆总掉线?这些行为太伤脑!

人体老化过程中&#xff0c;记忆力的衰退不可避免&#xff0c;这种属于“良性”的记忆衰退。但非“良性”的记忆衰退可要重视&#xff0c;很可能是痴呆症的早期征兆。由于各种原因&#xff0c;我们各种熬夜。作息的不规律扰乱大脑神经系统的调节。这种长期慢性损害大脑&#xf…

WebDAV之π-Disk派盘+Cloud Player

Cloud Player 支持WebDAV方式连接π-Disk派盘。 推荐一款云媒体播放器是存储在常见云平台中的内容的通用播放器。 Cloud Player云媒体播放器是存储在常见云平台中的内容的通用播放器,无需将其下载到设备。支持以下云平台:Google Drive、DropBox、One Drive、WebDav等。此外,…

超纯水制备,MB-106UP抛光树脂的技术解析

超纯水&#xff08;Ultrapure water&#xff09;又称UP水&#xff0c;是指电阻率达到18 MΩ*cm&#xff08;25℃&#xff09;的水。这种水中除了水分子外&#xff0c;几乎没有什么杂质&#xff0c;更没有细菌、病毒、含氯二噁英等有机物&#xff0c;当然也没有人体所需的矿物质…

【ArcGIS Pro二次开发】(7):地图(Map)的基本操作

地图是ArcGIS Pro中的基础起点&#xff0c;也是大多数工程的基础。主要用于显示表示空间数据的图层。 一、地图(Map)的基本操作示例 1、获取当前地图 var map MapView.Active.Map; 2、获取一级图层 var lys map.Layers; 用于获取地图中的单一图层&#xff0c;以及图层组…

深入了解Java线程锁(一)

在上一篇《如何保证线程的原子性》中&#xff0c;我们谈到了锁&#xff08;Synchronized&#xff09;&#xff0c; 这次我们就来深入探讨一下Java多线程中的锁。 互斥锁的本质是共享资源。 如上图所示&#xff0c; Thread1访问受保护资源&#xff0c;对其加锁&#xff0c;将…

【GO】k8s 管理系统项目16[前端部分–前端布局]

【GO】k8s 管理系统项目[前端部分–前端布局] 1. 前端布局 2. Layout 2.1 layout src/layout/Layout.vue <template><div class"common-layout"><el-container><el-side width"200">Aside</el-side><el-container>…

CAN总线开发一本全(3) - 微控制器集成的FlexCAN外设

CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设 苏勇&#xff0c;2023年2月 文章目录CAN总线开发一本全&#xff08;3&#xff09; - 微控制器集成的FlexCAN外设引言硬件外设模块系统概要总线接口单元 - 寄存器清单数据结构 - 消息缓冲区MB初始化过…

React(一):初识React、类组件、jsx的基础语法

React&#xff08;一&#xff09;一、初识React1.简单介绍2.React的三个依赖3.Hello React案例二、类组件1.定义类组件并渲染2.绑定事件函数&#xff08;奇怪的this问题&#xff09;3.数组形式数据的展示&#xff08;电影案例&#xff09;4.计数器案例三、jsx语法详解1.jsx的书…

利用InceptionV3实现图像分类

最近在做一个机审的项目&#xff0c;初步希望实现图像的四分类&#xff0c;即&#xff1a;正常&#xff08;neutral&#xff09;、涉政&#xff08;political&#xff09;、涉黄&#xff08;porn&#xff09;、涉恐&#xff08;terrorism&#xff09;。有朋友给推荐了个github上…

机器学习笔记之近似推断(一)从深度学习角度认识推断

机器学习笔记之近似推断——从深度学习角度认识推断引言推断——基本介绍精确推断难的原因虽然能够表示&#xff0c;但计算代价太大无法直接表示引言 本节是一篇关于推断总结的博客&#xff0c;侧重点在于深度学习模型中的推断任务。 推断——基本介绍 推断(Inference\text{…

Python中实现将内容进行base64编码与解码

一、需求说明需要使用Python实现将内容转为base64编码&#xff0c;解码&#xff0c;方便后续的数据操作。二、base64简介Base64是一种二进制到文本的编码方式【是一种基于 64 个可打印字符来表示二进制数据的表示方法&#xff08;由于 2^664&#xff0c;所以每 6 个比特为一个单…

国产音质好的蓝牙耳机有哪些?国产音质最好的耳机排行

随着时间的推移&#xff0c;真无线蓝牙耳机逐渐占据耳机市场的份额&#xff0c;成为人们日常生活中必备的数码产品之一。蓝牙耳机品牌也多得数不胜数&#xff0c;哪些国产蓝牙耳机音质好&#xff1f;下面&#xff0c;我们从音质出来&#xff0c;来给大家介绍几款国产蓝牙耳机&a…

硬件系统工程师宝典(11)-----去耦电容布局“有讲究”

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们说到在电源完整性分析的目标就是要做到电源的干净、稳定和快速响应&#xff0c;以及针对不同噪声处理的实现方法。今天我们来看看去耦电容…

父传子与子传父步骤

父传子&#xff1a; 问题&#xff1a;父页面中引入子组件 把想要传给子页面的值用在子组件中用 &#xff1a;值“值” (用同一个值好区分)来绑定。 在子页面中用props接收 子组件不能改变父组件传过来的值。&#xff08;传多个页面的时候是&#xff0c;比如父传孙的时候我会…

【2023】华为OD机试真题Java-题目0221-AI处理器组合

AI处理器组合 题目描述 某公司研发了一款高性能AI处理器。每台物理设备具备8颗AI处理器,编号分别为0、1、2、3、4、5、6、7。编号0-3的处理器处于同一个链路中,编号4-7的处理器处于另外一个链路中,不通链路中的处理器不能通信,如下图所示。现给定服务器可用的处理器编号数…