From 802ccd8e9700daf08e025aed165c99f2cc6d8d79 Mon Sep 17 00:00:00 2001 From: gitea Date: Sat, 29 Jun 2024 07:48:54 +0800 Subject: [PATCH 1/2] =?UTF-8?q?v0.1.7.1(2024/06/29)=201.=20[APIs:=20aio.py?= =?UTF-8?q?]=20=20=20=20-=20=E5=AF=B9=E4=BA=8Eautomatic=20test=E5=88=A0?= =?UTF-8?q?=E9=99=A4=E4=BA=86=E8=BE=93=E5=85=A5=E6=A1=86=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8configs.xlsx=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E5=8F=82=E6=95=B0=E8=BE=93=E5=85=A5=20=20=20?= =?UTF-8?q?=20-=20=E5=AE=8C=E5=96=84initialization/param=5Fcheck/func=5Fst?= =?UTF-8?q?art=5Fcallback=E5=87=BD=E6=95=B0=E4=B8=AD=E5=AF=B9=E4=BA=8Eauto?= =?UTF-8?q?matic=20test=E7=9A=84=E5=A4=84=E7=90=86=20=20=20=20-=20?= =?UTF-8?q?=E5=B0=86textbox=E7=BB=84=E4=BB=B6=E4=B8=80=E7=9B=B4=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=BAnormal=E7=8A=B6=E6=80=81=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E9=A2=91=E7=B9=81=E5=88=87=E6=8D=A2disabled=20=20=20?= =?UTF-8?q?=20-=20=E5=B0=86=E6=89=80=E6=9C=89=E7=9A=84f=5Fh=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=AF=B9=E8=B1=A1=E4=BF=AE=E6=94=B9=E4=B8=BAf=5Fhb?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E5=B0=86connection=5Fstate=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E4=B8=BAc=5Fstate=20=20=20=20-=20=E5=9C=A8detect=5Fnetwork?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E4=B8=AD=EF=BC=8C=E5=AE=9E=E4=BE=8B=E5=8C=96?= =?UTF-8?q?HmiRequest=EF=BC=8C=E5=B9=B6=E5=9C=A8=E6=97=A0=E9=99=90?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E4=B8=AD=E6=A3=80=E6=B5=8B=E5=BF=83=E8=B7=B3?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E6=AD=A3=E5=B8=B8=EF=BC=8C=E5=A6=82=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=EF=BC=8C=E5=88=99=E9=94=80=E6=AF=81hr=EF=BC=8C?= =?UTF-8?q?=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90=20=20=20=20-=20=E5=8F=96?= =?UTF-8?q?=E6=B6=88=E5=9C=A8tabview=E5=88=87=E6=8D=A2=E6=97=B6=EF=BC=8C?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E5=BF=83=E8=B7=B3=E7=9A=84=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E8=BF=99=E6=A0=B7=E5=81=9A=E6=97=A0=E6=B3=95=E4=BF=9D?= =?UTF-8?q?=E8=AF=81=E5=AE=9E=E6=97=B6=E6=80=A7=202.=20[APIs:=20openapi.py?= =?UTF-8?q?]=20=20=20=20-=20=E5=B0=86sock=5Fconn=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E7=A7=BB=E5=87=BA=5F=5Finit=5F=5F=EF=BC=8C=E5=8D=95=E7=8B=AC?= =?UTF-8?q?=E4=BD=9C=E4=B8=BA=E8=BF=9E=E6=8E=A5=E5=87=BD=E6=95=B0=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=20=20=20=20-=20=E6=96=B0=E5=A2=9E=E5=85=A8=E5=B1=80?= =?UTF-8?q?=E5=8F=98=E9=87=8Fself.t=5Fbool=EF=BC=8C=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=9A=84=E7=BA=BF=E7=A8=8B=E4=B8=AD=E6=97=A0?= =?UTF-8?q?=E9=99=90=E5=BE=AA=E7=8E=AF=E7=9A=84=E5=90=AF=E5=81=9C=EF=BC=8C?= =?UTF-8?q?=E4=B9=9F=E5=B0=B1=E6=98=AF=E5=8F=AF=E4=BB=A5=E4=BA=BA=E4=B8=BA?= =?UTF-8?q?=E7=9A=84=E9=80=80=E5=87=BA=E7=BA=BF=E7=A8=8B=20=20=20=20-=20?= =?UTF-8?q?=E7=A7=BB=E9=99=A4close=5Fsock=E5=87=BD=E6=95=B0=20=20=20=20-?= =?UTF-8?q?=20heartbeat=E5=87=BD=E6=95=B0=E4=B8=AD=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=89=93=E5=8D=B0=E6=89=80=E6=9C=89=E6=B6=88=E6=81=AF=E7=9A=84?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=EF=BC=8C=E8=B0=83=E8=AF=95=E6=97=B6=E6=89=93?= =?UTF-8?q?=E5=BC=80=EF=BC=8C=E5=B9=B3=E5=B8=B8=E5=85=B3=E9=97=AD=20=20=20?= =?UTF-8?q?=20-=20execution=E5=87=BD=E6=95=B0=E4=B8=AD=EF=BC=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=AF=B9overview.set=5Fautoload=E5=92=8Coverview.relo?= =?UTF-8?q?ad=E7=9A=84=E6=94=AF=E6=8C=81=20=20=20=20-=20execution=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=B8=AD=EF=BC=8C=E5=AF=B9send=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=203.=20[APIs:=20do=5Fbrake.py]=20=20=20=20-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=96=87=E4=BB=B6=EF=BC=8C=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=88=B6=E5=8A=A8=E6=B5=8B=E8=AF=95=E6=B5=81=E7=A8=8B=EF=BC=8C?= =?UTF-8?q?=E5=BB=BA=E7=AB=8B=E8=BF=9E=E6=8E=A5=EF=BC=8C=E5=AF=BC=E5=85=A5?= =?UTF-8?q?project=EF=BC=8Cpp2main=EF=BC=8Crun=EF=BC=8C=E9=87=87=E9=9B=86?= =?UTF-8?q?=E5=B9=B6=E5=A4=84=E7=90=86=E6=9B=B2=E7=BA=BF=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=EF=BC=8C=E6=9C=AC=E5=9C=B0=E4=BF=AE=E6=94=B9RL=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=EF=BC=8C=E6=8E=A8=E9=80=81=E8=87=B3=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=99=A8=E7=AD=89=20=20=20=20-=20=E7=9B=AE=E5=89=8D=E5=AE=8C?= =?UTF-8?q?=E6=88=90=EF=BC=9A=20=20=20=20=20=20-=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=88=E8=A7=84=E6=80=A7=E6=A3=80=E6=9F=A5=20=20=20=20=20=20?= =?UTF-8?q?-=20=E5=AF=BC=E5=85=A5=E5=B7=A5=E7=A8=8B=E5=B9=B6=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E4=B8=BA=E8=BF=90=E8=A1=8C=E5=B7=A5=E7=A8=8B=204.=20[?= =?UTF-8?q?APIs:=20current.py]=20=E4=BF=AE=E6=94=B9scenario/single?= =?UTF-8?q?=E7=94=B5=E6=9C=BA=E7=94=B5=E6=B5=81=E6=9C=80=E5=A4=A7=E9=95=BF?= =?UTF-8?q?=E5=BA=A6=E4=B8=BA150s=205.=20=E5=9C=A8=E6=9C=AC=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E4=B8=AD=E6=9B=B4=E6=96=B0=E5=85=B3=E4=BA=8E=E5=88=B6?= =?UTF-8?q?=E5=8A=A8=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B=E8=AF=95=E7=9A=84?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio/README.md | 39 +++++- aio/assets/configs.xlsx | Bin 0 -> 14863 bytes .../templates/overview.get_autoload.json | 5 + .../templates/overview.get_cur_prj.json | 5 + aio/assets/templates/overview.reload.json | 9 ++ .../templates/overview.set_autoload.json | 8 ++ aio/code/aio.py | 127 ++++++++--------- aio/code/automatic_test/__init__.py | 2 +- aio/code/automatic_test/do_brake.py | 129 ++++++++++++++++++ aio/code/automatic_test/do_current.py | 0 aio/code/automatic_test/openapi.py | 91 ++++++------ aio/code/data_process/current.py | 4 +- 12 files changed, 302 insertions(+), 117 deletions(-) create mode 100644 aio/assets/configs.xlsx create mode 100644 aio/assets/templates/overview.get_autoload.json create mode 100644 aio/assets/templates/overview.get_cur_prj.json create mode 100644 aio/assets/templates/overview.reload.json create mode 100644 aio/assets/templates/overview.set_autoload.json create mode 100644 aio/code/automatic_test/do_brake.py create mode 100644 aio/code/automatic_test/do_current.py diff --git a/aio/README.md b/aio/README.md index d3f6ac9..f29c7ba 100644 --- a/aio/README.md +++ b/aio/README.md @@ -6,6 +6,8 @@ 2. 电机电流数据,全部轴数据处理 1min 以内 3. ISO 激光数据整理,1min 以内 4. wavelogger 波形处理,几乎不花费时间 +5. 制动自动化测试 + --- @@ -111,7 +113,15 @@ pyinstaller --noconfirm --onedir --windowed --add-data "C:/Users/Administrator/A 2. 组织目录下只允许有 .csv 文件,对文件夹无要求 3. 运行结束后,会生成 result.xlsx 文件,结果按照 .csv 文件名存放 4. 采集数据时,不同轮次数据时间间隔最好大于 2 倍的周期时间,否则会出现采集的轮数不正确的情况,但数据是完整的 - + +#### 5) 制动自动化测试 + +只需要提前将如下文件放在指定路径下即可: +1. zip 工程文件 +2. excel 制动结果处理文件 +3. excel configs.xlsx 配置文件 + + #### 其他 customtkinter的tabview组件不支持修改字体大小,可以参考 [Changing Font of a Tabview](https://github.com/TomSchimansky/CustomTkinter/issues/2296) 进行手动修改源码实现: a. 运行 `pip show customtkinter`,获取到库的路径 @@ -125,7 +135,7 @@ RELEASE CHANGES 已知问题: -1. office套件下运行好像有问题,WPS无问题,集中在just_open函数的实现上 +1. - v0.0.1(2024/05/18) Draft @@ -301,9 +311,32 @@ v0.1.7.0(2024/06/26)-初步可用 3. [openapi.py] 新增sock_conn函数,并做连接时的异常处理,新增类参数w2t 4. [aio.py] 修改customtkinter库中C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages\customtkinter\windows\widgets\ctk_tabview.py文件,参考https://github.com/TomSchimansky/CustomTkinter/issues/2296,实现修改tabview组件的字体大小,使用原生字体,同时将segmented button字体修改为原生,为了解决segmented button在禁用和启用时,屏幕抖动的问题,并将大小修改为16 5. [aio.py] 修改了segmented_button_callback的实现逻辑,使代码更简洁 -6. [aio.py] 修改了在tabview_click函数中对于实例化openapi的动作,使每次切换标签都会重新实例化,也就是每次都会重新连接,修复显示不正确的问题 +6. [aio.py] 修改了在tabview_click函数中对于实例化HmiRequest的动作,使每次切换标签都会重新实例化,也就是每次都会重新连接,修复显示不正确的问题 7. [openapi.py] 新增了socket关闭的函数,并增加msg_id为None的处理逻辑 8. [btn_functions.py] 完善了状态获取的功能,新增告警获取以及功能切换的逻辑 9. [aio.py] 修改了版本 10. [current.py] max/avg功能结束之前会将结果数据追加写入源文件,avg算法更改为average+3×std 11. [wavelogger.py] 算法更改为 average+3×std + +v0.1.7.1(2024/06/29) +1. [APIs: aio.py] + - 对于automatic test删除了输入框,使用configs.xlsx配置文件作为参数输入 + - 完善initialization/param_check/func_start_callback函数中对于automatic test的处理 + - 将textbox组件一直设置为normal状态,不再频繁切换disabled + - 将所有的f_h文件对象修改为f_hb,并将connection_state修改为c_state + - 在detect_network函数中,实例化HmiRequest,并在无限循环中检测心跳是否正常,如异常,则销毁hr,重新生成 + - 取消在tabview切换时,检测心跳的逻辑,这样做无法保证实时性 +2. [APIs: openapi.py] + - 将sock_conn函数移出__init__,单独作为连接函数存在 + - 新增全局变量self.t_bool,控制所有的线程中无限循环的启停,也就是可以人为的退出线程 + - 移除close_sock函数 + - heartbeat函数中新增打印所有消息的代码,调试时打开,平常关闭 + - execution函数中,新增对overview.set_autoload和overview.reload的支持 + - execution函数中,对send动作增加异常处理逻辑 +3. [APIs: do_brake.py] + - 新增文件,处理制动测试流程,建立连接,导入project,pp2main,run,采集并处理曲线数据,本地修改RL程序,推送至控制器等 + - 目前完成: + - 文件合规性检查 + - 导入工程并设置为运行工程 +4. [APIs: current.py] 修改scenario/single电机电流最大长度为150s +5. 在本文件中更新关于制动自动化测试的相关内容 \ No newline at end of file diff --git a/aio/assets/configs.xlsx b/aio/assets/configs.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..c8ae10d9848320456d57723ea35373093ff2e608 GIT binary patch literal 14863 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 1: diff --git a/aio/code/automatic_test/__init__.py b/aio/code/automatic_test/__init__.py index 30869a7..f60ee0b 100644 --- a/aio/code/automatic_test/__init__.py +++ b/aio/code/automatic_test/__init__.py @@ -1 +1 @@ -__all__ = ['openapi', 'btn_functions'] \ No newline at end of file +__all__ = ['openapi', 'btn_functions', 'do_brake', 'do_current'] \ No newline at end of file diff --git a/aio/code/automatic_test/do_brake.py b/aio/code/automatic_test/do_brake.py new file mode 100644 index 0000000..a8da2c9 --- /dev/null +++ b/aio/code/automatic_test/do_brake.py @@ -0,0 +1,129 @@ +from sys import argv +from os import scandir +from os.path import exists +import paramiko +import json + + +def traversal_files(path, w2t): + # 功能:以列表的形式分别返回指定路径下的文件和文件夹,不包含子目录 + # 参数:路径 + # 返回值:路径下的文件夹列表 路径下的文件列表 + if not exists(path): + msg = f'数据文件夹{path}不存在,请确认后重试......' + w2t(msg, 0, 1, 'red') + else: + dirs = [] + files = [] + for item in scandir(path): + if item.is_dir(): + dirs.append(item.path) + elif item.is_file(): + files.append(item.path) + + return dirs, files + + +def check_files(data_dirs, data_files, w2t): + if len(data_dirs) != 0 or len(data_files) != 5: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red') + + config_file = reach33 = reach66 = reach100 = prj_file = None + for data_file in data_files: + filename = data_file.split('\\')[-1] + if filename == 'configs.xlsx': + config_file = data_file + elif filename.startswith('reach33_') and filename.endswith('.xlsx'): + reach33 = data_file + elif filename.startswith('reach66_') and filename.endswith('.xlsx'): + reach66 = data_file + elif filename.startswith('reach100_') and filename.endswith('.xlsx'): + reach100 = data_file + elif filename.endswith('.zip'): + prj_file = data_file + else: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 2, 'red') + + if config_file and reach33 and reach66 and reach100 and prj_file: + w2t("数据目录合规性检查结束,未发现问题......") + return config_file, reach33, reach66, reach100, prj_file + else: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red') + + +def prj_to_xcore(prj_file): + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019') + sftp = ssh.open_sftp() + # stdin, stdout, stderr = ssh.exec_command('rm /tmp/target.zip') + # ssh.exec_command('rm /tmp/target.zip') + sftp.put(prj_file, '/tmp/target.zip') + cmd = 'cd /tmp; ' + cmd += 'rm -rf target/; ' + cmd += 'mkdir target; ' + cmd += 'unzip -d target/ -q target.zip; ' + cmd += 'rm target.zip; ' + ssh.exec_command(cmd) + + cmd = 'sudo rm -rf /home/luoshi/bin/controller/projects/target; ' + cmd += 'sudo mv /tmp/target/ /home/luoshi/bin/controller/projects/' + stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) + stdin.write('luoshi2019' + '\n') + stdin.flush() + print(stdout.read().decode()) # 必须得输出一下stdout,才能正确执行sudo + print(stderr.read().decode()) # 顺便也执行以下stderr + ssh.close() + + +def modify_prj(): + pass + + +def validate_resp(_id, response, w2t): + match _id: + case 'DATA ERR': + w2t(f"数据处理错误,需要确认", 0, 4, 'red') + case 'DATA READ ERR': + w2t(f"无法读取数据,需要确认", 0, 3, 'red') + case 'NOT SUPPORT': + w2t(f"不支持的功能,需要确认", 0, 2, 'red') + if not response: + w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red') + + +def execution(cmd, hr, w2t, **kwargs): + _id = hr.excution(cmd, **kwargs) + _msg = hr.get_from_id(_id) + if not _msg: + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') + else: + _response = json.loads(_msg) + validate_resp(_id, _response, w2t) + return _response + + +def run_rl(hr, w2t): + prj_path = '/home/luoshi/bin/controller/projects/target' + _response = execution('overview.set_autoload', hr, w2t, autoload_prj_path=prj_path) + print(f"set prj auto load: {_response}") + _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com']) + print(f"reload prj: {_response}") + _response = execution('overview.get_cur_prj', hr, w2t) + print(f"get prj name: {_response}") + _response = execution('overview.get_autoload', hr, w2t) + print(f"get auto load: {_response}") + + +def main(path, hr, loadsel, w2t): + data_dirs, data_files = traversal_files(path, w2t) + config_file, reach33, reach66, reach100, prj_file = check_files(data_dirs, data_files, w2t) + prj_to_xcore(prj_file) + run_rl(hr, w2t) + + +if __name__ == '__main__': + main(*argv[1:]) diff --git a/aio/code/automatic_test/do_current.py b/aio/code/automatic_test/do_current.py new file mode 100644 index 0000000..e69de29 diff --git a/aio/code/automatic_test/openapi.py b/aio/code/automatic_test/openapi.py index e0f6e90..5ede426 100644 --- a/aio/code/automatic_test/openapi.py +++ b/aio/code/automatic_test/openapi.py @@ -16,37 +16,6 @@ class HmiRequest(object): self.w2t = w2t self.c = None self.c_xs = None - - def sock_conn(): - # while True: - with open(f"{current_path}/../../assets/templates/heartbeat", "r", encoding='utf-8') as f_h: - connection_state = f_h.read().strip() - if connection_state == '0': - try: - c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - c.connect(('192.168.0.160', 5050)) - # c.connect(('192.168.84.129', 5050)) - c.setblocking(False) - c_xs = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - c_xs.connect(('192.168.0.160', 6666)) - # c_xs.connect(('192.168.84.129', 6666)) - c_xs.setblocking(False) - - self.w2t("Connection success", 0, 0, 'green') - with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: - f_h.write('1') - return c, c_xs - - except Exception as Err: - with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: - f_h.write('0') - self.w2t("Connection failed...", 0, 0, 'red') - return None, None - - self.c, self.c_xs = sock_conn() - if self.c is None or self.c_xs is None: - self.w2t("Aborting! Try to switch tabs to re-connect!", 0, 1, 'red') - self.c_msg = [] self.c_msg_xs = [] self.flag = 0 @@ -54,7 +23,9 @@ class HmiRequest(object): self.leftover = 0 self.flag_xs = 0 self.response_xs = '' + self.t_bool = True + self.sock_conn() self.t_heartbeat = threading.Thread(target=self.heartbeat) self.t_heartbeat.daemon = True self.t_heartbeat.start() @@ -65,9 +36,29 @@ class HmiRequest(object): self.t_unpackage_xs.daemon = True self.t_unpackage_xs.start() - def close_sock(self): - self.c.close() - self.c_xs.close() + def sock_conn(self): + # while True: + with open(f"{current_path}/../../assets/templates/heartbeat", "r", encoding='utf-8') as f_hb: + c_state = f_hb.read().strip() + if c_state == '0': + try: + self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c.connect(('192.168.0.160', 5050)) + # self.c.connect(('192.168.84.129', 5050)) + self.c.setblocking(False) + self.c_xs = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c_xs.connect(('192.168.0.160', 6666)) + # self.c_xs.connect(('192.168.84.129', 6666)) + self.c_xs.setblocking(False) + + self.w2t("Connection success", 0, 0, 'green') + with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: + f_hb.write('1') + + except Exception as Err: + self.w2t("Connection failed...", 0, 0, 'red') + with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: + f_hb.write('0') def header_check(self, index, data): try: @@ -87,12 +78,15 @@ class HmiRequest(object): return 'DATA READ ERR' def heartbeat(self): - while True: + while self.t_bool: _id = self.excution('controller.heart') - _flag = 0 if self.get_from_id(_id) is None else 1 - with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_h: - f_h.write(str(_flag)) + _flag = '0' if self.get_from_id(_id) is None else '1' + with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: + f_hb.write(_flag) time.sleep(3) + # with open('log.txt', 'w') as f: + # for msg in self.c_msg: + # f.write(msg + '\n') def msg_storage(self, response, flag=0): messages = self.c_msg if flag == 0 else self.c_msg_xs @@ -224,7 +218,7 @@ class HmiRequest(object): sel = selectors.DefaultSelector() sel.register(sock, selectors.EVENT_READ, to_read) - while True: + while self.t_bool: events = sel.select() for key, mask in events: callback = key.data @@ -244,7 +238,7 @@ class HmiRequest(object): sel = selectors.DefaultSelector() sel.register(sock, selectors.EVENT_READ, to_read) - while True: + while self.t_bool: events = sel.select() for key, mask in events: callback = key.data @@ -268,13 +262,22 @@ class HmiRequest(object): match command: case 'state.set_tp_mode': req['data']['tp_mode'] = kwargs['tp_mode'] - case 1: - pass + case 'overview.set_autoload': + req['data']['autoload_prj_path'] = kwargs['autoload_prj_path'] + case 'overview.reload': + req['data']['prj_path'] = kwargs['prj_path'] + req['data']['tasks'] = kwargs['tasks'] + req['id'] = self.gen_id(command) print(f"req = {req}") cmd = json.dumps(req, separators=(',', ':')) - self.c.send(self.package(cmd)) - time.sleep(2) + try: + self.c.send(self.package(cmd)) + time.sleep(2) + except Exception as Err: + self.w2t(f"{cmd}\n请求发送失败...\n{Err}", 0, 11) + return req['id'] + else: # for xService pass diff --git a/aio/code/data_process/current.py b/aio/code/data_process/current.py index 7c2b820..68d28c8 100644 --- a/aio/code/data_process/current.py +++ b/aio/code/data_process/current.py @@ -303,7 +303,7 @@ def p_single(wb, single, vel, trq, rpm, w2t): data.append(df.iloc[row, 1]) i = 0 - for row in ws.iter_rows(min_row=2, min_col=2, max_row=70000, max_col=3): + for row in ws.iter_rows(min_row=2, min_col=2, max_row=150000, max_col=3): for cell in row: try: _ = f"{data[i]:.2f}" @@ -355,7 +355,7 @@ def p_scenario(wb, single, vel, trq, rpm, dur, w2t): data.append(df.iloc[row, 1]) i = 0 - for row in ws.iter_rows(min_row=2, min_col=2, max_row=70000, max_col=3): + for row in ws.iter_rows(min_row=2, min_col=2, max_row=150000, max_col=3): for cell in row: try: _ = f"{data[i]:.2f}" From 611d848b41530276f40f0cae071671ddcf60e435 Mon Sep 17 00:00:00 2001 From: gitea Date: Sat, 29 Jun 2024 20:40:17 +0800 Subject: [PATCH 2/2] =?UTF-8?q?v0.1.7.1(2024/06/29)=201.=20[APIs:=20aio.py?= =?UTF-8?q?]=20=20=20=20-=20=E4=BF=AE=E6=94=B9detect=5Fnetwork=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=B8=ADsleep=E8=AF=AD=E5=8F=A5=E6=94=BE=E5=88=B0?= =?UTF-8?q?=E6=9C=80=E5=90=8E=EF=BC=8C=E9=87=8D=E6=96=B0=E7=94=9F=E6=88=90?= =?UTF-8?q?HmiRequest=E5=AE=9E=E4=BE=8B=E4=B8=AD=E5=A2=9E=E5=8A=A0sleep(4)?= =?UTF-8?q?=EF=BC=8C=E8=BF=99=E4=B8=AA=E5=81=9C=E9=A1=BF=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E4=B8=80=E5=AE=9A=E6=98=AF=E6=AF=94openapi=E4=B8=ADheartbeat?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E7=9A=84sleep=E8=A6=81=E9=95=BF1s=E4=BB=A5?= =?UTF-8?q?=E4=B8=8A=E6=89=8D=E8=83=BD=E6=AD=A3=E5=B8=B8=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=20=20=20=20-=20=E4=BF=AE=E6=94=B9write2textbox=E5=87=BD?= =?UTF-8?q?=E6=95=B0=EF=BC=8C=E6=96=B0=E5=A2=9E=E9=BB=98=E8=AE=A4=E5=8F=82?= =?UTF-8?q?=E6=95=B0tab=5Fname=EF=BC=8C=E5=8F=AA=E6=9C=89=E5=BD=93?= =?UTF-8?q?=E8=AF=A5=E5=80=BC=E4=B8=8E=E5=BD=93=E5=89=8Dtab=E4=B8=80?= =?UTF-8?q?=E8=87=B4=E6=97=B6=EF=BC=8C=E5=87=BD=E6=95=B0=E6=89=8D=E4=BC=9A?= =?UTF-8?q?=E6=9C=89=E8=BE=93=E5=87=BA=20=20=20=20-=20=E7=AC=AC=E4=BA=8C?= =?UTF-8?q?=E6=9D=A1=E6=94=B9=E5=8A=A8=E5=BD=B1=E5=93=8D=E5=88=B0=E4=BA=86?= =?UTF-8?q?automatic=5Ftest=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=8B=E6=89=80?= =?UTF-8?q?=E6=9C=89=E7=9A=84=E6=96=87=E4=BB=B6=202.=20[APIs:=20openapi.py?= =?UTF-8?q?]=20=20=20=20-=20=E8=A7=84=E5=AE=9A=E4=BA=86=E6=89=80=E6=9C=89?= =?UTF-8?q?=E7=9A=84=E7=BD=91=E7=BB=9C=E5=BC=82=E5=B8=B8=E5=9D=87=E7=94=B1?= =?UTF-8?q?heartbeat=E5=87=BD=E6=95=B0=E6=9D=A5=E5=AE=9A=E4=B9=89=EF=BC=8C?= =?UTF-8?q?=E5=85=B6=E4=BB=96=E5=BC=82=E5=B8=B8=E4=B8=8D=E5=81=9A=E4=B8=AD?= =?UTF-8?q?=E6=96=AD=E5=A4=84=E7=90=86=20=20=20=20-=20execution=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E4=B8=AD=E5=90=88=E5=B9=B6=E4=BA=86case=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=20=20=20=20-=20=E5=A2=9E=E5=8A=A0=E4=BA=86N=E5=A4=9A?= =?UTF-8?q?=E6=8C=87=E4=BB=A4=EF=BC=8C=E5=A4=9A=E4=B8=BA=E8=AF=8A=E6=96=AD?= =?UTF-8?q?=E6=9B=B2=E7=BA=BF=E5=92=8Crl=E7=A8=8B=E5=BA=8F=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=203.=20[APIs:=20do=5Fbrake.py]=20=20=20=20-=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=87=AA=E5=8A=A8=E6=8E=A8=E9=80=81=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B=E5=88=B0xCore=E5=B9=B6=E8=87=AA=E5=8A=A8=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=20=20=20=20-=20=E5=88=9D=E6=AD=A5=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E4=BA=86Modbus=E5=8F=91=E9=80=81=E6=B6=88=E6=81=AF=E5=92=8C?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E7=8A=B6=E6=80=81=204.=20[APIs:=20do=5Fcurre?= =?UTF-8?q?nt.py]=20=20=20=20-=20=E5=B0=86do=5Fbrake.py=E7=9A=84=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E5=AE=8C=E5=85=A8=E6=8B=B7=E8=B4=9D=E5=88=B0=E6=AD=A4?= =?UTF-8?q?=E6=96=87=E4=BB=B6=EF=BC=8C=E5=BE=85=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio/README.md | 17 +- .../templates/diagnosis.get_params.json | 8 + aio/assets/templates/diagnosis.open.json | 12 ++ aio/assets/templates/diagnosis.save.json | 8 + .../templates/diagnosis.set_params.json | 10 + aio/assets/templates/rl_task.pp_to_main.json | 8 + aio/assets/templates/rl_task.run.json | 8 + aio/assets/templates/rl_task.stop.json | 8 + aio/code/aio.py | 40 ++-- aio/code/automatic_test/btn_functions.py | 20 +- aio/code/automatic_test/do_brake.py | 102 +++++++--- aio/code/automatic_test/do_current.py | 175 ++++++++++++++++++ aio/code/automatic_test/openapi.py | 66 ++++--- 13 files changed, 398 insertions(+), 84 deletions(-) create mode 100644 aio/assets/templates/diagnosis.get_params.json create mode 100644 aio/assets/templates/diagnosis.open.json create mode 100644 aio/assets/templates/diagnosis.save.json create mode 100644 aio/assets/templates/diagnosis.set_params.json create mode 100644 aio/assets/templates/rl_task.pp_to_main.json create mode 100644 aio/assets/templates/rl_task.run.json create mode 100644 aio/assets/templates/rl_task.stop.json diff --git a/aio/README.md b/aio/README.md index f29c7ba..90c80fd 100644 --- a/aio/README.md +++ b/aio/README.md @@ -339,4 +339,19 @@ v0.1.7.1(2024/06/29) - 文件合规性检查 - 导入工程并设置为运行工程 4. [APIs: current.py] 修改scenario/single电机电流最大长度为150s -5. 在本文件中更新关于制动自动化测试的相关内容 \ No newline at end of file +5. 在本文件中更新关于制动自动化测试的相关内容 + +v0.1.7.1(2024/06/29) +1. [APIs: aio.py] + - 修改detect_network函数中sleep语句放到最后,重新生成HmiRequest实例中增加sleep(4),这个停顿时间一定是比openapi中heartbeat函数的sleep要长1s以上才能正常工作 + - 修改write2textbox函数,新增默认参数tab_name,只有当该值与当前tab一致时,函数才会有输出 + - 第二条改动影响到了automatic_test文件夹下所有的文件 +2. [APIs: openapi.py] + - 规定了所有的网络异常均由heartbeat函数来定义,其他异常不做中断处理 + - execution函数中合并了case条件 + - 增加了N多指令,多为诊断曲线和rl程序相关 +3. [APIs: do_brake.py] + - 实现自动推送工程到xCore并自动运行 + - 初步实现了Modbus发送消息和检测状态 +4. [APIs: do_current.py] + - 将do_brake.py的内容完全拷贝到此文件,待修改 \ No newline at end of file diff --git a/aio/assets/templates/diagnosis.get_params.json b/aio/assets/templates/diagnosis.get_params.json new file mode 100644 index 0000000..7e57457 --- /dev/null +++ b/aio/assets/templates/diagnosis.get_params.json @@ -0,0 +1,8 @@ +{ + "id": "xxxxxxxxxxx", + "module": "robot", + "command": "diagnosis.get_params", + "data": { + "version": "1.4.1" + } +} \ No newline at end of file diff --git a/aio/assets/templates/diagnosis.open.json b/aio/assets/templates/diagnosis.open.json new file mode 100644 index 0000000..915ff6a --- /dev/null +++ b/aio/assets/templates/diagnosis.open.json @@ -0,0 +1,12 @@ +{ + "id": "xxxxxxxxxxx", + "module": "robot", + "command": "diagnosis.open", + "data": { + "open": false, + "display_open": false, + "overrun": true, + "turn_area": true, + "delay_motion": false + } +} \ No newline at end of file diff --git a/aio/assets/templates/diagnosis.save.json b/aio/assets/templates/diagnosis.save.json new file mode 100644 index 0000000..6564248 --- /dev/null +++ b/aio/assets/templates/diagnosis.save.json @@ -0,0 +1,8 @@ +{ + "id": "xxxxxxxxxxx", + "module": "robot", + "command": "diagnosis.save", + "data": { + "save": true + } +} \ No newline at end of file diff --git a/aio/assets/templates/diagnosis.set_params.json b/aio/assets/templates/diagnosis.set_params.json new file mode 100644 index 0000000..0bb13cc --- /dev/null +++ b/aio/assets/templates/diagnosis.set_params.json @@ -0,0 +1,10 @@ +{ + "id": "xxxxxxxxxxx", + "module": "robot", + "command": "diagnosis.set_params", + "data": { + "display_pdo_params": [], + "frequency": 50, + "version": "1.4.1" + } +} \ No newline at end of file diff --git a/aio/assets/templates/rl_task.pp_to_main.json b/aio/assets/templates/rl_task.pp_to_main.json new file mode 100644 index 0000000..3e2247f --- /dev/null +++ b/aio/assets/templates/rl_task.pp_to_main.json @@ -0,0 +1,8 @@ +{ + "id": "xxxxxxxxxxx", + "module": "project", + "command": "rl_task.pp_to_main", + "data": { + "tasks": [] + } +} \ No newline at end of file diff --git a/aio/assets/templates/rl_task.run.json b/aio/assets/templates/rl_task.run.json new file mode 100644 index 0000000..52e89a1 --- /dev/null +++ b/aio/assets/templates/rl_task.run.json @@ -0,0 +1,8 @@ +{ + "id": "xxxxxxxxxxx", + "module": "project", + "command": "rl_task.run", + "data": { + "tasks": [] + } +} \ No newline at end of file diff --git a/aio/assets/templates/rl_task.stop.json b/aio/assets/templates/rl_task.stop.json new file mode 100644 index 0000000..03b0f6b --- /dev/null +++ b/aio/assets/templates/rl_task.stop.json @@ -0,0 +1,8 @@ +{ + "id": "xxxxxxxxxxx", + "module": "project", + "command": "rl_task.stop", + "data": { + "tasks": [] + } +} \ No newline at end of file diff --git a/aio/code/aio.py b/aio/code/aio.py index 1111654..bfc7d2f 100644 --- a/aio/code/aio.py +++ b/aio/code/aio.py @@ -200,17 +200,17 @@ class App(customtkinter.CTk): c_state = f_hb.read().strip() pb_color = 'green' if c_state == '1' else 'red' self.progressbar.configure(progress_color=pb_color) - sleep(1) if c_state == '0': - self.textbox.delete(index1='1.0', index2='end') + # self.textbox.delete(index1='1.0', index2='end') self.hr.t_bool = False - sleep(1) + sleep(4) del self.hr self.hr = openapi.HmiRequest(self.write2textbox) + sleep(3) def tabview_click(self): self.initialization() - self.textbox.delete(index1='1.0', index2='end') + # self.textbox.delete(index1='1.0', index2='end') tab_name = self.tabview.get() if tab_name == 'Data Process': @@ -221,6 +221,7 @@ class App(customtkinter.CTk): def initialization(self): tab_name = self.tabview.get() + self.textbox.delete(index1='1.0', index2='end') if tab_name == 'Data Process': for widgit in widgits_dp: if widgit in ['path', 'av', 'rc', 'rpm', 'rr', 'dur', 'rc1', 'rc2', 'rc3', 'rc4', 'rc5', 'rc6']: @@ -235,7 +236,6 @@ class App(customtkinter.CTk): widgits_dp[widgit]['optionmenu'].configure(state='disabled') self.menu_sub_dp.grid_forget() - self.textbox.delete(index1='1.0', index2='end') elif tab_name == 'Automatic Test': for widgit in widgits_at: if widgit in ['path', 'av1', 'av2', 'av3', 'av4', 'av5', 'av6', 'rc1', 'rc2', 'rc3', 'rc4', 'rc5', 'rc6', 'rr1', 'rr2', 'rr3', 'rr4', 'rr5', 'rr6']: @@ -334,23 +334,25 @@ class App(customtkinter.CTk): widgits_dp[widgit]['label'].configure(text_color="red") widgits_dp[widgit]['optionmenu'].configure(state='normal') - def write2textbox(self, text, wait=0, exitcode=0, color='blue'): + def write2textbox(self, text, wait=0, exitcode=0, color='blue', tab_name='Data Process'): self.textbox.tag_add(color, 'insert', 'end') self.textbox.tag_config(tagName=color, foreground=color) + tab_name_cur = self.tabview.get() - if wait != 0: - self.textbox.insert(index='end', text=text, tags=color) - self.textbox.update() - self.textbox.see('end') - elif exitcode != 0: - self.textbox.insert(index='end', text=text + '\n', tags=color) - self.textbox.update() - self.textbox.see('end') - raise Exception(f"Error code: {exitcode}") - else: - self.textbox.insert(index='end', text=text + '\n', tags=color) - self.textbox.update() - self.textbox.see('end') + if tab_name == tab_name_cur: + if wait != 0: + self.textbox.insert(index='end', text=text, tags=color) + self.textbox.update() + self.textbox.see('end') + elif exitcode != 0: + self.textbox.insert(index='end', text=text + '\n', tags=color) + self.textbox.update() + self.textbox.see('end') + raise Exception(f"Error code: {exitcode}") + else: + self.textbox.insert(index='end', text=text + '\n', tags=color) + self.textbox.update() + self.textbox.see('end') def is_float(self, flag, *args): for item in args: diff --git a/aio/code/automatic_test/btn_functions.py b/aio/code/automatic_test/btn_functions.py index e6a6d51..9536e79 100644 --- a/aio/code/automatic_test/btn_functions.py +++ b/aio/code/automatic_test/btn_functions.py @@ -5,20 +5,20 @@ from sys import argv def validate_resp(_id, response, w2t): match _id: case 'DATA ERR': - w2t(f"数据处理错误,需要确认", 0, 4, 'red') + w2t(f"数据处理错误,需要确认", 0, 4, 'red', tab_name='Automatic Test') case 'DATA READ ERR': - w2t(f"无法读取数据,需要确认", 0, 3, 'red') + w2t(f"无法读取数据,需要确认", 0, 3, 'red', tab_name='Automatic Test') case 'NOT SUPPORT': - w2t(f"不支持的功能,需要确认", 0, 2, 'red') + w2t(f"不支持的功能,需要确认", 0, 2, 'red', tab_name='Automatic Test') if not response: - w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red') + w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red', tab_name='Automatic Test') def execution(cmd, hr, w2t, **kwargs): _id = hr.excution(cmd, **kwargs) _msg = hr.get_from_id(_id) if not _msg: - w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test') else: _response = json.loads(_msg) validate_resp(_id, _response, w2t) @@ -30,7 +30,7 @@ def get_state(hr, w2t): _response = execution('state.get_state', hr, w2t) stat_desc = {'engine': '上电状态', 'operate': '操作模式', 'rc_state': '控制器状态', 'robot_action': '机器人动作', 'safety_mode': '安全模式', 'servo_mode': '伺服工作模式', 'task_space': '工作任务空间'} for component, state in _response['data'].items(): - w2t(f"{stat_desc[component]}: {state}") + w2t(f"{stat_desc[component]}: {state}", tab_name='Automatic Test') # 获取设备伺服信息 _response = execution('device.get_params', hr, w2t) @@ -39,7 +39,7 @@ def get_state(hr, w2t): for device in _response['data']['devices']: dev_vers[device['type']] = device['version'] for i in sorted(dev_desc.keys()): - w2t(f"{dev_desc[i]}: {dev_vers[i]}") + w2t(f"{dev_desc[i]}: {dev_vers[i]}", tab_name='Automatic Test') # 设置示教器模式 _response = execution('state.set_tp_mode', hr, w2t, tp_mode='without') @@ -48,15 +48,15 @@ def get_state(hr, w2t): def warning_info(hr, w2t): for msg in hr.c_msg: if 'alarm' in msg.lower(): - w2t(msg) + w2t(msg, tab_name='Automatic Test') for msg in hr.c_msg_xs: if 'alarm' in msg.lower(): - w2t(msg) + w2t(msg, tab_name='Automatic Test') def main(hr, func, w2t): if hr is None: - w2t("无法连接机器人,检查是否已经使用Robot Assist软件连接机器,重试中...", 0, 49, 'red') + w2t("无法连接机器人,检查是否已经使用Robot Assist软件连接机器,重试中...", 0, 49, 'red', tab_name='Automatic Test') # func: get_state/ match func: case 'get_state': diff --git a/aio/code/automatic_test/do_brake.py b/aio/code/automatic_test/do_brake.py index a8da2c9..d60c955 100644 --- a/aio/code/automatic_test/do_brake.py +++ b/aio/code/automatic_test/do_brake.py @@ -1,8 +1,9 @@ +from time import sleep from sys import argv from os import scandir from os.path import exists -import paramiko -import json +from paramiko import SSHClient, AutoAddPolicy +from json import loads def traversal_files(path, w2t): @@ -11,7 +12,7 @@ def traversal_files(path, w2t): # 返回值:路径下的文件夹列表 路径下的文件列表 if not exists(path): msg = f'数据文件夹{path}不存在,请确认后重试......' - w2t(msg, 0, 1, 'red') + w2t(msg, 0, 1, 'red', tab_name='Automatic Test') else: dirs = [] files = [] @@ -26,8 +27,8 @@ def traversal_files(path, w2t): def check_files(data_dirs, data_files, w2t): if len(data_dirs) != 0 or len(data_files) != 5: - w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') - w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red') + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name='Automatic Test') config_file = reach33 = reach66 = reach100 = prj_file = None for data_file in data_files: @@ -43,20 +44,20 @@ def check_files(data_dirs, data_files, w2t): elif filename.endswith('.zip'): prj_file = data_file else: - w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') - w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 2, 'red') + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 2, 'red', tab_name='Automatic Test') if config_file and reach33 and reach66 and reach100 and prj_file: - w2t("数据目录合规性检查结束,未发现问题......") + w2t("数据目录合规性检查结束,未发现问题......", tab_name='Automatic Test') return config_file, reach33, reach66, reach100, prj_file else: - w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red') - w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red') + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name='Automatic Test') def prj_to_xcore(prj_file): - ssh = paramiko.SSHClient() - ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + ssh = SSHClient() + ssh.set_missing_host_key_policy(AutoAddPolicy()) ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019') sftp = ssh.open_sftp() # stdin, stdout, stderr = ssh.exec_command('rm /tmp/target.zip') @@ -76,6 +77,14 @@ def prj_to_xcore(prj_file): stdin.flush() print(stdout.read().decode()) # 必须得输出一下stdout,才能正确执行sudo print(stderr.read().decode()) # 顺便也执行以下stderr + + cmd = 'cd /home/luoshi/bin/controller/; sudo mv projects/target/_build/*.prj projects/target/_build/target.prj ' + stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) + stdin.write('luoshi2019' + '\n') + stdin.flush() + print(stdout.read().decode()) # 必须得输出一下stdout,才能正确执行sudo + print(stderr.read().decode()) # 顺便也执行以下stderr + ssh.close() @@ -86,42 +95,79 @@ def modify_prj(): def validate_resp(_id, response, w2t): match _id: case 'DATA ERR': - w2t(f"数据处理错误,需要确认", 0, 4, 'red') + w2t(f"数据处理错误,需要确认", 0, 4, 'red', tab_name='Automatic Test') case 'DATA READ ERR': - w2t(f"无法读取数据,需要确认", 0, 3, 'red') + w2t(f"无法读取数据,需要确认", 0, 3, 'red', tab_name='Automatic Test') case 'NOT SUPPORT': - w2t(f"不支持的功能,需要确认", 0, 2, 'red') + w2t(f"不支持的功能,需要确认", 0, 2, 'red', tab_name='Automatic Test') if not response: - w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red') + w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red', tab_name='Automatic Test') def execution(cmd, hr, w2t, **kwargs): _id = hr.excution(cmd, **kwargs) _msg = hr.get_from_id(_id) if not _msg: - w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test') else: - _response = json.loads(_msg) + _response = loads(_msg) validate_resp(_id, _response, w2t) return _response def run_rl(hr, w2t): - prj_path = '/home/luoshi/bin/controller/projects/target' - _response = execution('overview.set_autoload', hr, w2t, autoload_prj_path=prj_path) - print(f"set prj auto load: {_response}") - _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com']) - print(f"reload prj: {_response}") - _response = execution('overview.get_cur_prj', hr, w2t) - print(f"get prj name: {_response}") - _response = execution('overview.get_autoload', hr, w2t) - print(f"get auto load: {_response}") + # prj_path = 'target/_build/target.prj' + # _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com']) + # print(f"reload prj: {_response}") + # # _response = execution('overview.get_cur_prj', hr, w2t) + # # print(f"get cur prj name: {_response}") + # _response = execution('rl_task.pp_to_main', hr, w2t, tasks=['Mechanical_Test_Com']) + # print(f"set pp2main of prj: {_response}") + # + # _response = execution('state.switch_auto', hr, w2t) + # _response = execution('state.switch_motor_on', hr, w2t) + # + # _response = execution('rl_task.run', hr, w2t, tasks=['Mechanical_Test_Com']) + # print(f"run prj: {_response}") + # sleep(10) + # + # _response = execution('state.switch_motor_off', hr, w2t) + # _response = execution('state.switch_manual', hr, w2t) + + _response = execution('diagnosis.open', hr, w2t, open=True, display_open=True) + print(f"打开诊断: {_response}") + # _response = execution('diagnosis.get_params', hr, w2t) + # print(f"显示诊断状态: {_response}") + display_pdo_params = [ + {"name": "device_servo_trq_feedback", "channel": 0} + ] + _response = execution('diagnosis.set_params', hr, w2t, display_pdo_params=display_pdo_params) + print(f"执行采样: {_response}") + sleep(5) + + _response = execution('diagnosis.open', hr, w2t, open=False, display_open=False) + print(f"关闭诊断: {_response}") + # sleep(1) + for _msg in hr.c_msg: + if 'diagnosis.result' in _msg: + print(_msg) + # _msg = json.loads(_msg) + # if 'channel' in _msg and 'name' in _msg: + # if int(_msg['channel']) == 0 and _msg['name'] == 'device_servo_trq_feedback': + # print(f"diagnosis.result: {_msg}") + # count += 1 + # if count * 50 > 5 * 1000: + # break + + + else: + sleep(1) def main(path, hr, loadsel, w2t): data_dirs, data_files = traversal_files(path, w2t) config_file, reach33, reach66, reach100, prj_file = check_files(data_dirs, data_files, w2t) - prj_to_xcore(prj_file) + # prj_to_xcore(prj_file) run_rl(hr, w2t) diff --git a/aio/code/automatic_test/do_current.py b/aio/code/automatic_test/do_current.py index e69de29..d60c955 100644 --- a/aio/code/automatic_test/do_current.py +++ b/aio/code/automatic_test/do_current.py @@ -0,0 +1,175 @@ +from time import sleep +from sys import argv +from os import scandir +from os.path import exists +from paramiko import SSHClient, AutoAddPolicy +from json import loads + + +def traversal_files(path, w2t): + # 功能:以列表的形式分别返回指定路径下的文件和文件夹,不包含子目录 + # 参数:路径 + # 返回值:路径下的文件夹列表 路径下的文件列表 + if not exists(path): + msg = f'数据文件夹{path}不存在,请确认后重试......' + w2t(msg, 0, 1, 'red', tab_name='Automatic Test') + else: + dirs = [] + files = [] + for item in scandir(path): + if item.is_dir(): + dirs.append(item.path) + elif item.is_file(): + files.append(item.path) + + return dirs, files + + +def check_files(data_dirs, data_files, w2t): + if len(data_dirs) != 0 or len(data_files) != 5: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name='Automatic Test') + + config_file = reach33 = reach66 = reach100 = prj_file = None + for data_file in data_files: + filename = data_file.split('\\')[-1] + if filename == 'configs.xlsx': + config_file = data_file + elif filename.startswith('reach33_') and filename.endswith('.xlsx'): + reach33 = data_file + elif filename.startswith('reach66_') and filename.endswith('.xlsx'): + reach66 = data_file + elif filename.startswith('reach100_') and filename.endswith('.xlsx'): + reach100 = data_file + elif filename.endswith('.zip'): + prj_file = data_file + else: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 2, 'red', tab_name='Automatic Test') + + if config_file and reach33 and reach66 and reach100 and prj_file: + w2t("数据目录合规性检查结束,未发现问题......", tab_name='Automatic Test') + return config_file, reach33, reach66, reach100, prj_file + else: + w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, 'red', tab_name='Automatic Test') + w2t(' 1. configs.xlsx\n 2. reach33/reach66/reach100_xxxx.xlsx\n 3. xxxx.zip', 0, 1, 'red', tab_name='Automatic Test') + + +def prj_to_xcore(prj_file): + ssh = SSHClient() + ssh.set_missing_host_key_policy(AutoAddPolicy()) + ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019') + sftp = ssh.open_sftp() + # stdin, stdout, stderr = ssh.exec_command('rm /tmp/target.zip') + # ssh.exec_command('rm /tmp/target.zip') + sftp.put(prj_file, '/tmp/target.zip') + cmd = 'cd /tmp; ' + cmd += 'rm -rf target/; ' + cmd += 'mkdir target; ' + cmd += 'unzip -d target/ -q target.zip; ' + cmd += 'rm target.zip; ' + ssh.exec_command(cmd) + + cmd = 'sudo rm -rf /home/luoshi/bin/controller/projects/target; ' + cmd += 'sudo mv /tmp/target/ /home/luoshi/bin/controller/projects/' + stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) + stdin.write('luoshi2019' + '\n') + stdin.flush() + print(stdout.read().decode()) # 必须得输出一下stdout,才能正确执行sudo + print(stderr.read().decode()) # 顺便也执行以下stderr + + cmd = 'cd /home/luoshi/bin/controller/; sudo mv projects/target/_build/*.prj projects/target/_build/target.prj ' + stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) + stdin.write('luoshi2019' + '\n') + stdin.flush() + print(stdout.read().decode()) # 必须得输出一下stdout,才能正确执行sudo + print(stderr.read().decode()) # 顺便也执行以下stderr + + ssh.close() + + +def modify_prj(): + pass + + +def validate_resp(_id, response, w2t): + match _id: + case 'DATA ERR': + w2t(f"数据处理错误,需要确认", 0, 4, 'red', tab_name='Automatic Test') + case 'DATA READ ERR': + w2t(f"无法读取数据,需要确认", 0, 3, 'red', tab_name='Automatic Test') + case 'NOT SUPPORT': + w2t(f"不支持的功能,需要确认", 0, 2, 'red', tab_name='Automatic Test') + if not response: + w2t(f"无法获取{id}请求的响应信息", 0, 1, 'red', tab_name='Automatic Test') + + +def execution(cmd, hr, w2t, **kwargs): + _id = hr.excution(cmd, **kwargs) + _msg = hr.get_from_id(_id) + if not _msg: + w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test') + else: + _response = loads(_msg) + validate_resp(_id, _response, w2t) + return _response + + +def run_rl(hr, w2t): + # prj_path = 'target/_build/target.prj' + # _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com']) + # print(f"reload prj: {_response}") + # # _response = execution('overview.get_cur_prj', hr, w2t) + # # print(f"get cur prj name: {_response}") + # _response = execution('rl_task.pp_to_main', hr, w2t, tasks=['Mechanical_Test_Com']) + # print(f"set pp2main of prj: {_response}") + # + # _response = execution('state.switch_auto', hr, w2t) + # _response = execution('state.switch_motor_on', hr, w2t) + # + # _response = execution('rl_task.run', hr, w2t, tasks=['Mechanical_Test_Com']) + # print(f"run prj: {_response}") + # sleep(10) + # + # _response = execution('state.switch_motor_off', hr, w2t) + # _response = execution('state.switch_manual', hr, w2t) + + _response = execution('diagnosis.open', hr, w2t, open=True, display_open=True) + print(f"打开诊断: {_response}") + # _response = execution('diagnosis.get_params', hr, w2t) + # print(f"显示诊断状态: {_response}") + display_pdo_params = [ + {"name": "device_servo_trq_feedback", "channel": 0} + ] + _response = execution('diagnosis.set_params', hr, w2t, display_pdo_params=display_pdo_params) + print(f"执行采样: {_response}") + sleep(5) + + _response = execution('diagnosis.open', hr, w2t, open=False, display_open=False) + print(f"关闭诊断: {_response}") + # sleep(1) + for _msg in hr.c_msg: + if 'diagnosis.result' in _msg: + print(_msg) + # _msg = json.loads(_msg) + # if 'channel' in _msg and 'name' in _msg: + # if int(_msg['channel']) == 0 and _msg['name'] == 'device_servo_trq_feedback': + # print(f"diagnosis.result: {_msg}") + # count += 1 + # if count * 50 > 5 * 1000: + # break + + + else: + sleep(1) + + +def main(path, hr, loadsel, w2t): + data_dirs, data_files = traversal_files(path, w2t) + config_file, reach33, reach66, reach100, prj_file = check_files(data_dirs, data_files, w2t) + # prj_to_xcore(prj_file) + run_rl(hr, w2t) + + +if __name__ == '__main__': + main(*argv[1:]) diff --git a/aio/code/automatic_test/openapi.py b/aio/code/automatic_test/openapi.py index 5ede426..40b609a 100644 --- a/aio/code/automatic_test/openapi.py +++ b/aio/code/automatic_test/openapi.py @@ -1,13 +1,13 @@ -import json -import socket -import threading +from json import load, dumps +from socket import socket, setdefaulttimeout, AF_INET, SOCK_STREAM +from threading import Thread import selectors -import time -import os +from time import time, sleep +from os.path import dirname MAX_FRAME_SIZE = 1024 -socket.setdefaulttimeout(2) -current_path = os.path.dirname(__file__) +setdefaulttimeout(2) +current_path = dirname(__file__) class HmiRequest(object): @@ -24,15 +24,16 @@ class HmiRequest(object): self.flag_xs = 0 self.response_xs = '' self.t_bool = True + self.tab_name = 'Automatic Test' self.sock_conn() - self.t_heartbeat = threading.Thread(target=self.heartbeat) + self.t_heartbeat = Thread(target=self.heartbeat) self.t_heartbeat.daemon = True self.t_heartbeat.start() - self.t_unpackage = threading.Thread(target=self.unpackage, args=(self.c, )) + self.t_unpackage = Thread(target=self.unpackage, args=(self.c, )) self.t_unpackage.daemon = True self.t_unpackage.start() - self.t_unpackage_xs = threading.Thread(target=self.unpackage_xs, args=(self.c_xs, )) + self.t_unpackage_xs = Thread(target=self.unpackage_xs, args=(self.c_xs, )) self.t_unpackage_xs.daemon = True self.t_unpackage_xs.start() @@ -42,21 +43,21 @@ class HmiRequest(object): c_state = f_hb.read().strip() if c_state == '0': try: - self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c = socket(AF_INET, SOCK_STREAM) self.c.connect(('192.168.0.160', 5050)) # self.c.connect(('192.168.84.129', 5050)) self.c.setblocking(False) - self.c_xs = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.c_xs = socket(AF_INET, SOCK_STREAM) self.c_xs.connect(('192.168.0.160', 6666)) # self.c_xs.connect(('192.168.84.129', 6666)) self.c_xs.setblocking(False) - self.w2t("Connection success", 0, 0, 'green') + self.w2t("Connection success", 0, 0, 'green', tab_name=self.tab_name) with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: f_hb.write('1') except Exception as Err: - self.w2t("Connection failed...", 0, 0, 'red') + self.w2t("Connection failed...", 0, 0, 'red', tab_name=self.tab_name) with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: f_hb.write('0') @@ -81,20 +82,24 @@ class HmiRequest(object): while self.t_bool: _id = self.excution('controller.heart') _flag = '0' if self.get_from_id(_id) is None else '1' + print(f"hb = {_flag}", end=' ') with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: f_hb.write(_flag) - time.sleep(3) - # with open('log.txt', 'w') as f: + if _flag == '0': + self.w2t(f"心跳丢失,连接失败,重新连接中...", 0, 0, 'red', tab_name=self.tab_name) + sleep(2) + print(len(self.c_msg), end=' ') + # with open(f"{current_path}/../../assets/templates/c_msg.log", "w", encoding='utf-8') as f: # for msg in self.c_msg: # f.write(msg + '\n') def msg_storage(self, response, flag=0): messages = self.c_msg if flag == 0 else self.c_msg_xs - if len(messages) < 1000: + if len(messages) < 20000: messages.insert(0, response) else: messages.insert(0, response) - while len(messages) > 1000: + while len(messages) > 20000: messages.pop() def get_response(self, data): @@ -187,10 +192,10 @@ class HmiRequest(object): for i in range(3): for msg in messages: if msg_id is None: - self.w2t("未能成功获取到 message id...", 0, 10, 'red') + self.w2t("未能成功获取到 message id...", 0, 10, 'red', tab_name=self.tab_name) if msg_id in msg: return msg - time.sleep(1) + sleep(1) else: return None @@ -202,7 +207,7 @@ class HmiRequest(object): return _frame_head + _pkg_head + _protocol + _reserved + cmd.encode() def package_xs(self, cmd): - return f"{json.dumps(cmd, separators=(',', ':'))}\r".encode() + return f"{dumps(cmd, separators=(',', ':'))}\r".encode() def unpackage(self, sock): def to_read(conn): @@ -245,7 +250,7 @@ class HmiRequest(object): callback(key.fileobj) def gen_id(self, command): - _now = time.time() + _now = time() _id = f"{command}-{_now}" return _id @@ -254,7 +259,7 @@ class HmiRequest(object): req = None try: with open(f'{current_path}/../../assets/templates/{command}.json', encoding='utf-8', mode='r') as f_json: - req = json.load(f_json) + req = load(f_json) except: print(f"暂不支持 {command} 功能,或确认该功能存在...") return 'NOT SUPPORT' @@ -267,15 +272,24 @@ class HmiRequest(object): case 'overview.reload': req['data']['prj_path'] = kwargs['prj_path'] req['data']['tasks'] = kwargs['tasks'] + case 'rl_task.pp_to_main' | 'rl_task.run' | 'rl_task.stop': + req['data']['tasks'] = kwargs['tasks'] + case 'diagnosis.set_params': + req['data']['display_pdo_params'] = kwargs['display_pdo_params'] + case 'diagnosis.open': + req['data']['open'] = kwargs['open'] + req['data']['display_open'] = kwargs['display_open'] + case _: + pass req['id'] = self.gen_id(command) print(f"req = {req}") - cmd = json.dumps(req, separators=(',', ':')) + cmd = dumps(req, separators=(',', ':')) try: self.c.send(self.package(cmd)) - time.sleep(2) + sleep(2) except Exception as Err: - self.w2t(f"{cmd}\n请求发送失败...\n{Err}", 0, 11) + self.w2t(f"{cmd}\n请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name) return req['id']