From aedac4c90cfa33f7bfbdbc0d9f92dd6ce4fca2ac Mon Sep 17 00:00:00 2001 From: gitea Date: Tue, 2 Jul 2024 21:48:00 +0800 Subject: [PATCH] =?UTF-8?q?v0.1.7.4(2024/07/02)=201.=20[APIs:=20openapi.py?= =?UTF-8?q?]=20=20=20=20-=20=E5=A2=9E=E5=8A=A0=E4=BA=86modbus=E7=9A=84pyth?= =?UTF-8?q?on=E5=AE=9E=E7=8E=B0=20=20=20=20-=20heartbeat=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=91=E9=80=81=E9=97=B4=E9=9A=94=E4=B8=BA?= =?UTF-8?q?1s=20=20=20=20-=20=E6=B8=85=E9=99=A4=E4=BA=86=E7=BB=9D=E5=A4=A7?= =?UTF-8?q?=E9=83=A8=E5=88=86=E8=B0=83=E8=AF=95=E6=80=A7=E8=BE=93=E5=87=BA?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E7=8E=B0=E5=A4=AA=E5=A4=9A=E7=9A=84=E8=BF=99?= =?UTF-8?q?=E7=A7=8D=E8=BE=93=E5=87=BA=E4=B9=9F=E4=BC=9A=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E5=BF=83=E8=B7=B3=E4=B8=A2=E5=8C=85...=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E6=B8=85=E6=A5=9A=E8=BF=99=E4=B8=AA=E5=8E=9F=E7=90=86=E6=98=AF?= =?UTF-8?q?=E4=BB=80=E4=B9=88=20=20=20=20-=20=E5=9C=A8get=5Fresponse?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E4=B8=AD=E7=9A=84while=20self.pkg=20>=200?= =?UTF-8?q?=E5=BE=AA=E7=8E=AF=E4=B8=AD=EF=BC=8C=E5=88=A0=E9=99=A4=E4=BA=86?= =?UTF-8?q?else=E8=AF=AD=E5=8F=A5=EF=BC=8C=E5=9B=A0=E4=B8=BA=E5=AE=83?= =?UTF-8?q?=E6=B0=B8=E4=B8=8D=E4=BC=9A=E8=A2=AB=E6=89=A7=E8=A1=8C=E5=88=B0?= =?UTF-8?q?=20=20=20=20-=20=E5=9C=A8get=5Fresponse=E5=87=BD=E6=95=B0?= =?UTF-8?q?=E4=B8=AD=EF=BC=8C=E4=BF=AE=E5=A4=8D=E4=B8=80=E4=B8=AAbug?= =?UTF-8?q?=EF=BC=8C=E5=9C=A8flag=3D=3D0=E7=9A=84else=E8=AF=AD=E5=8F=A5?= =?UTF-8?q?=E4=B8=AD=EF=BC=8C=E8=A1=A5=E9=BD=90=E4=BA=86index=3D=3D6?= =?UTF-8?q?=E7=9A=84=E6=83=85=E5=86=B5=202.=20[APIs:=20do=5Fcurrent.py]=20?= =?UTF-8?q?=20=20=20-=20=E5=AE=8C=E6=88=90=E4=BA=86=E5=85=AD=E4=B8=AA?= =?UTF-8?q?=E8=BD=B4=E7=9A=84=E7=94=B5=E6=9C=BA=E7=94=B5=E6=B5=81=E5=8A=A8?= =?UTF-8?q?=E4=BD=9C=E7=9A=84=E6=89=A7=E8=A1=8C=EF=BC=8C=E4=BB=A5=E5=8F=8A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E9=87=87=E9=9B=86=20=20=20=20-=20=E5=AE=8C?= =?UTF-8?q?=E6=88=90=E4=BA=86=E5=AF=B9=E5=BA=94=E7=9A=84RL=E7=A8=8B?= =?UTF-8?q?=E5=BA=8F=E7=9A=84=E7=BC=96=E5=86=99=203[APIs:=20aio.py]=20=20?= =?UTF-8?q?=20=20-=20=E5=BC=95=E5=85=A5modbus=E5=AE=9E=E4=BE=8B=E5=8C=96?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E4=BB=A5=E5=8F=82=E6=95=B0=E7=9A=84=E5=BD=A2?= =?UTF-8?q?=E5=BC=8F=EF=BC=8C=E4=BC=A0=E9=80=92=E7=BB=99=E7=9B=B8=E5=BA=94?= =?UTF-8?q?=E7=9A=84tabview=20=20=20=20-=20=E6=96=B0=E5=A2=9Epre=5Fwarning?= =?UTF-8?q?=E5=87=BD=E6=95=B0=EF=BC=8C=E5=9C=A8=E5=81=9A=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=8C=96=E6=B5=8B=E8=AF=95=E4=B9=8B=E5=89=8D=EF=BC=8C=E7=A1=AE?= =?UTF-8?q?=E4=BF=9D=E6=89=80=E6=9C=89=E6=9D=A1=E4=BB=B6=E7=9A=86=E5=85=B7?= =?UTF-8?q?=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- aio/README.md | 15 +- aio/assets/templates/c_msg.log | 27 --- aio/code/aio.py | 14 +- aio/code/automatic_test/do_current.py | 154 ++++++++------ aio/code/automatic_test/openapi.py | 283 ++++++++++++++++++-------- 6 files changed, 318 insertions(+), 178 deletions(-) delete mode 100644 aio/assets/templates/c_msg.log diff --git a/.gitignore b/.gitignore index c3bd9aa..7eb83ee 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ aio/package/ aio/venv aio/__pycache__/ aio/code/automatic_test/__pycache__/ -aio/code/data_process/__pycache__/ \ No newline at end of file +aio/code/data_process/__pycache__/ +aio/assets/templates/c_msg.log \ No newline at end of file diff --git a/aio/README.md b/aio/README.md index d06c5fa..6b60d99 100644 --- a/aio/README.md +++ b/aio/README.md @@ -389,5 +389,16 @@ v0.1.7.3(2024/07/01) > 目前看openapi.py封包解包没有任何问题了,但是所有的调试信息都默认打开,以便可以第一时间保留现场 > 打开诊断,跑了10多分钟,共计解包没有报错,应该是没有问题了 - - +v0.1.7.4(2024/07/02) +1. [APIs: openapi.py] + - 增加了modbus的python实现 + - heartbeat函数修改发送间隔为1s + - 清除了绝大部分调试性输出,发现太多的这种输出也会导致心跳丢包...,不清楚这个原理是什么 + - 在get_response函数中的while self.pkg > 0循环中,删除了else语句,因为它永不会被执行到 + - 在get_response函数中,修复一个bug,在flag==0的else语句中,补齐了index==6的情况 +2. [APIs: do_current.py] + - 完成了六个轴的电机电流动作的执行,以及数据采集 + - 完成了对应的RL程序的编写 +3[APIs: aio.py] + - 引入modbus实例化,并以参数的形式,传递给相应的tabview + - 新增pre_warning函数,在做自动化测试之前,确保所有条件皆具备 diff --git a/aio/assets/templates/c_msg.log b/aio/assets/templates/c_msg.log deleted file mode 100644 index e4aefb9..0000000 --- a/aio/assets/templates/c_msg.log +++ /dev/null @@ -1,27 +0,0 @@ -{'command': 'alarm.report', 'data': {'id': 10020, 'level': 'warning', 'msg': False, 'title': '拒绝新示教器连接[2024-07-01 16:29:26]'}, 'module': 'system'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822570.4244733'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822567.92287'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822565.4212413'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822562.9190633'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822560.4154985'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822557.913359'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822555.4105828'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822552.9065998'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822550.4040146'} -{'command': 'alarm.report', 'data': {'id': 10135, 'level': 'info', 'msg': False, 'title': '切换热插拔模式成功[2024-07-01 16:29:03]'}, 'module': 'system'} -{'data': {'tp_mode': 'without'}, 'id': 'state.set_tp_mode-1719822549.450559'} -{'data': {'devices': [{'servo_axis': 1, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 2, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 3, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 4, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 5, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 6, 'type': 0, 'vendor': '748', 'version': ''}, {'servo_axis': 1, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 2, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 3, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 4, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 5, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 6, 'type': 1, 'vendor': '748', 'version': ''}, {'servo_axis': 1, 'type': 8, 'vendor': '748', 'version': 'none'}, {'servo_axis': 2, 'type': 8, 'vendor': '748', 'version': 'none'}, {'servo_axis': 3, 'type': 8, 'vendor': '748', 'version': 'none'}, {'servo_axis': 4, 'type': 8, 'vendor': '748', 'version': 'none'}, {'servo_axis': 5, 'type': 8, 'vendor': '748', 'version': 'none'}, {'servo_axis': 6, 'type': 8, 'vendor': '748', 'version': 'none'}, {'type': 2, 'vendor': 'rokae', 'version': 'RSC : 2.0.0.4 && RSC.Algorithm : 1.0.4'}, {'type': 3, 'vendor': 'rokae', 'version': '2.2.1.5'}, {'type': 4, 'vendor': 'rokae', 'version': '3.2.10'}, {'type': 5, 'vendor': 'rokae', 'version': 'v2.2.1.2'}, {'type': 6, 'vendor': 'rokae', 'version': '2.2.0.1'}, {'type': 9, 'vendor': 'rokae', 'version': 'none'}, {'type': 10, 'vendor': 'rokae', 'version': 'A0_xC.v2.2.0.R1'}, {'type': 11, 'vendor': 'rokae', 'version': '1.0.1'}]}, 'id': 'device.get_params-1719822548.7621348'} -{'command': 'move.monitor', 'data': {'elb': 0.0, 'euler': [89.99110467974835, 29.9853154646663, -104.00466319666923], 'ext_joint': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'joint': [76.01114273071289, -59.998823126376905, -150.00352478027347, -90.00099179534756, -90.0136906550481, 0.017031260758614768], 'position': [-192.41938657578066, -462.13248519925634, 310.74790278930976], 'quaternion': [-0.2763893828152837, -0.5646272736310524, 0.4255922997043593, 0.6509040984440838], 'torque': [0.0, -0.0, -0.0, -0.0, -0.0, -0.0]}, 'module': 'motion'} -{'data': {'engine': 'off', 'operate': 'manual', 'rc_state': 'normal', 'robot_action': 'idle', 'safety_mode': 'normal', 'servo_mode': 'position', 'task_space': 'ready'}, 'id': 'state.get_state-1719822548.1687336'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822547.9009733'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822545.399719'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822542.8978984'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822540.395304'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822537.893616'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822535.3915236'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822532.8891878'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822530.387109'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822527.8851492'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822525.3829527'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822522.8800979'} -{'data': {'name': 'xCore'}, 'id': 'controller.heart-1719822520.3775096'} diff --git a/aio/code/aio.py b/aio/code/aio.py index 3561d2a..54b4e2f 100644 --- a/aio/code/aio.py +++ b/aio/code/aio.py @@ -43,6 +43,8 @@ class App(customtkinter.CTk): self.my_font = customtkinter.CTkFont(family="Consolas", size=16, weight="bold") self.w_param = 84 self.hr = None + self.md_at = None + self.md_dp = None # ===================================================================== # configure window self.title("AIO - All in one automatic toolbox") @@ -183,6 +185,8 @@ class App(customtkinter.CTk): with open(f"{current_path}/../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: f_hb.write('0') self.hr = openapi.HmiRequest(self.write2textbox) + self.md_at = openapi.ModbusRequest(self, 'Automatic Test') + self.md_dp = openapi.ModbusRequest(self, 'Data Process') while True: with open(f'{current_path}/../assets/templates/heartbeat', 'r', encoding='utf-8') as f_hb: @@ -451,12 +455,20 @@ class App(customtkinter.CTk): elif flag == 4: func_dict[flag](path=args[0], w2t=self.write2textbox) elif flag == 5: + self.pre_warning() func_dict[flag](path=args[0], hr=self.hr, loadsel=args[1], w2t=self.write2textbox) elif flag == 6: - func_dict[flag](path=args[0], hr=self.hr, w2t=self.write2textbox) + self.pre_warning() + func_dict[flag](path=args[0], hr=self.hr, md=self.md_at, w2t=self.write2textbox) else: tkinter.messagebox.showerror(title="参数错误", message="请检查对应参数是否填写正确!", ) + def pre_warning(self): + if tkinter.messagebox.askyesno(title="开始运行", message="确认机器已按照测试规范更新固件,并提按照测试机型前修改好工程?"): + pass + else: + self.write2textbox("请按照测试规范更新机器固件,并在实际运行前确认工程已经修改完毕,以防撞机!!!", 0, 123, 'red', 'Automatic Test') + def func_check_callback(self): self.textbox.delete(index1='1.0', index2='end') diff --git a/aio/code/automatic_test/do_current.py b/aio/code/automatic_test/do_current.py index 8803c7d..0b28ecf 100644 --- a/aio/code/automatic_test/do_current.py +++ b/aio/code/automatic_test/do_current.py @@ -82,10 +82,6 @@ def prj_to_xcore(prj_file): ssh.close() -def modify_prj(): - pass - - def validate_resp(_id, response, w2t): match _id: case 'DATA ERR': @@ -102,76 +98,120 @@ def execution(cmd, hr, w2t, **kwargs): _id = hr.execution(cmd, **kwargs) _msg = hr.get_from_id(_id) if not _msg: - w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test') + w2t(f"无法获取{_id}请求的响应信息", 0, 0, '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=['brake', 'current']) - 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=['brake']) - print(f"set pp2main of prj: {_response}") - - _response = execution('state.switch_auto', hr, w2t) - _response = execution('state.switch_motor_on', 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": "hw_joint_vel_feedback", "channel": 0}, - {"name": "hw_joint_vel_feedback", "channel": 1}, - {"name": "hw_joint_vel_feedback", "channel": 2}, - {"name": "hw_joint_vel_feedback", "channel": 3}, - {"name": "hw_joint_vel_feedback", "channel": 4}, - {"name": "hw_joint_vel_feedback", "channel": 5}, - {"name": "device_servo_trq_feedback", "channel": 0}, - {"name": "device_servo_trq_feedback", "channel": 1}, - {"name": "device_servo_trq_feedback", "channel": 2}, - {"name": "device_servo_trq_feedback", "channel": 3}, - {"name": "device_servo_trq_feedback", "channel": 4}, - {"name": "device_servo_trq_feedback", "channel": 5}, - {"name": "device_safety_estop", "channel": 0}, +def run_rl(hr, md, w2t): + # need to run + conditions = [ + " scenario(0, j1_p, j1_n, p_speed, p_tool)", + " scenario(0, j2_p, j2_n, p_speed, p_tool)", + " scenario(0, j3_p, j3_n, p_speed, p_tool)", + " scenario(0, j4_p, j4_n, p_speed, p_tool)", + " scenario(0, j5_p, j5_n, p_speed, p_tool)", + " scenario(0, j6_p, j6_n, p_speed, p_tool)", + " scenario(1, j5_p, j5_n, p_speed, p_tool)", + " scenario(2, j5_p, j5_n, p_speed, p_tool)", + " scenario(3, j5_p, j5_n, p_speed, p_tool)", ] - _response = execution('diagnosis.set_params', hr, w2t, display_pdo_params=display_pdo_params) - print(f"执行采样: {_response}") - _response = execution('rl_task.run', hr, w2t, tasks=['brake']) - print(f"run prj: {_response}") - sleep(10) + for condition in conditions: + disc = {0: '一轴', 1: '二轴', 2: '三轴', 3: '四轴', 4: '五轴', 5: '六轴', 6: '场景一', 7: '场景二', 8: '场景三'} + number = conditions.index(condition) + w2t(f"正在执行{disc[number]}测试......", 0, 0, 'purple', 'Automatic Test') - _response = execution('diagnosis.open', hr, w2t, open=False, display_open=False) - print(f"关闭诊断: {_response}") + # 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来 + _response = execution('diagnosis.open', hr, w2t, open=False, display_open=False) + md.trigger_estop() + md.reset_estop() + _response = execution('state.switch_manual', hr, w2t) - _response = execution('rl_task.stop', hr, w2t, tasks=['brake']) - _response = execution('state.switch_motor_off', hr, w2t) - _response = execution('state.switch_manual', hr, w2t) + # 3. 修改未要执行的场景 + ssh = SSHClient() + ssh.set_missing_host_key_policy(AutoAddPolicy()) + ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019') + cmd = f'cd /home/luoshi/bin/controller/; ' + cmd += f'sudo sed -i "/scenario/d" projects/target/current/main.mod; ' + cmd += f'sudo sed -i "/DONOTDELETE/i {condition}" projects/target/current/main.mod; ' + 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 - 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 + # 4. reload工程后,pp2main + prj_path = 'target/_build/target.prj' + _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['current']) + _response = execution('overview.get_cur_prj', hr, w2t) + _response = execution('rl_task.pp_to_main', hr, w2t, tasks=['current']) + print(f"set pp2main of prj: {_response}") + + # 5. 切换自动并上电 + _response = execution('state.switch_auto', hr, w2t) + _response = execution('state.switch_motor_on', hr, w2t) + + # 6. 开始运行程序,单轴运行15s + _response = execution('rl_task.run', hr, w2t, tasks=['current']) + print(f"run prj: {_response}") + for i in range(3): + if md.read_ready_to_go() == 1: + md.write_act(True) + sleep(1) + md.write_act(False) + break + else: + sleep(1) + continue + else: + w2t("未收到机器人的运行信号,需要确认RL程序编写正确并正常执行...", 0, 111, 'red', 'Automatic Test') + # 7. 打开诊断曲线,并执行采集 + _response = execution('diagnosis.open', hr, w2t, open=True, display_open=True) + display_pdo_params = [ + {"name": "hw_joint_vel_feedback", "channel": 0}, + {"name": "hw_joint_vel_feedback", "channel": 1}, + {"name": "hw_joint_vel_feedback", "channel": 2}, + {"name": "hw_joint_vel_feedback", "channel": 3}, + {"name": "hw_joint_vel_feedback", "channel": 4}, + {"name": "hw_joint_vel_feedback", "channel": 5}, + {"name": "device_servo_trq_feedback", "channel": 0}, + {"name": "device_servo_trq_feedback", "channel": 1}, + {"name": "device_servo_trq_feedback", "channel": 2}, + {"name": "device_servo_trq_feedback", "channel": 3}, + {"name": "device_servo_trq_feedback", "channel": 4}, + {"name": "device_servo_trq_feedback", "channel": 5}, + {"name": "device_safety_estop", "channel": 0}, + ] + _response = execution('diagnosis.set_params', hr, w2t, display_pdo_params=display_pdo_params) + sleep(8) + # 8. 关闭诊断曲线,停止程序运行,下电并且换成手动模式 + _response = execution('diagnosis.open', hr, w2t, open=False, display_open=False) + _response = execution('rl_task.stop', hr, w2t, tasks=['current']) + _response = execution('state.switch_motor_off', hr, w2t) + _response = execution('state.switch_manual', hr, w2t) + sleep(1) + # 9. 处理数据并输出文件 + # 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 -def main(path, hr, w2t): +def main(path, hr, md, w2t): data_dirs, data_files = traversal_files(path, w2t) config_file, current_file, prj_file = check_files(data_dirs, data_files, w2t) prj_to_xcore(prj_file) - run_rl(hr, w2t) + run_rl(hr, md, w2t) if __name__ == '__main__': diff --git a/aio/code/automatic_test/openapi.py b/aio/code/automatic_test/openapi.py index 0239c12..a7f4418 100644 --- a/aio/code/automatic_test/openapi.py +++ b/aio/code/automatic_test/openapi.py @@ -5,12 +5,115 @@ import selectors from time import time, sleep from os.path import dirname from binascii import b2a_hex, a2b_hex +from pymodbus.client.tcp import ModbusTcpClient MAX_FRAME_SIZE = 1024 setdefaulttimeout(2) current_path = dirname(__file__) +class ModbusRequest(object): + def __init__(self, w2t, tab_name): + super().__init__() + self.w2t = w2t + self.tab_name = tab_name + self.host = '192.168.0.160' + self.port = 502 + self.c = ModbusTcpClient(self.host, self.port) + self.c.connect() + + def motor_off(self): + try: + self.c.write_register(40002, 1) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法正常下电,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def motor_on(self): + try: + self.c.write_register(40003, 1) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法正常上电,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def trigger_estop(self): + try: + self.c.write_register(40012, 0) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法触发软急停,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def reset_estop(self): + try: + self.c.write_register(40012, 1) + # self.c.write_register(40001, 1) + # sleep(0.2) + # self.c.write_register(40001, 1) + # sleep(0.2) + # self.c.write_register(40001, 0) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法重置软急停,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def clear_alarm(self): + try: + self.c.write_register(40000, 1) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法清除告警,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def get_cart_vel(self): + try: + results = self.c.read_holding_registers(40537, 7) + print(f"cart vel: {results.registers}") + + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法读取笛卡尔速度,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def get_jnt_vel(self): + try: + results = self.c.read_holding_registers(40579, 7) + print(f"joint vel: {results.registers}") + + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法读取关节速度,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def get_tcp_vel(self): + try: + results = self.c.read_holding_registers(40607, 7) + print(f"tcp vel: {results.registers}") + + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法读取TCP速度,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def get_tcp_mag_vel(self): + try: + results = self.c.read_holding_registers(40621, 1) + print(f"tcp mag: {results.registers}") + + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法读取TCP合成速度,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def write_act(self, number): + try: + self.c.write_register(41000, number) + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法发送执行信号,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + def read_ready_to_go(self): + try: + results = self.c.read_holding_registers(41001, 1) + return results.registers[0] + except Exception as Err: + self.w2t(f"{Err}") + self.w2t("无法读取准备信号,连接Modbus失败,需要确认网络是否通畅,或是未正确导入寄存器文件...", 0, 100, 'red', self.tab_name) + + class HmiRequest(object): def __init__(self, w2t): super().__init__() @@ -62,6 +165,10 @@ class HmiRequest(object): 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') + md = ModbusRequest(self.w2t, self.tab_name) + md.reset_estop() + md.clear_alarm() + md.write_act(False) except Exception as Err: 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: @@ -87,9 +194,9 @@ class HmiRequest(object): self.half_length = len(data) - index self.half = data[index:] - print(f"in head check half: {self.half}") - print(f"in head check length: {self.half_length}") - print(f"in head check data: {data}") + # print(f"in head check half: {self.half}") + # print(f"in head check length: {self.half_length}") + # print(f"in head check data: {data}") self.broke = 100 index += MAX_FRAME_SIZE @@ -101,11 +208,12 @@ class HmiRequest(object): _flag = '0' if self.get_from_id(_id) is None else '1' print(f"hb = {_flag}", end=' ') print(f"len(c_msg) = {len(self.c_msg)}", end=' ') + print(f"len(c_msg_xs) = {len(self.c_msg_xs)}", end=' ') with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb: f_hb.write(_flag) if _flag == '0': - self.w2t(f"心跳丢失,连接失败,重新连接中...", 0, 0, 'red', tab_name=self.tab_name) - sleep(2) + self.w2t(f"{_id} 心跳丢失,连接失败,重新连接中...", 0, 7, 'red', tab_name=self.tab_name) + sleep(1) # with open(f"{current_path}/../../assets/templates/c_msg.log", "w", encoding='utf-8') as f: # for msg in self.c_msg: # f.write(str(loads(msg)) + '\n') @@ -122,12 +230,12 @@ class HmiRequest(object): def get_response(self, data): # 流式获取单次请求的响应 if self.broke == 100: - print("*****************************************") - print(f"in get_response if broke == 100 half = {self.half}") + # print("*****************************************") + # print(f"in get_response if broke == 100 half = {self.half}") _half_1 = self.half _half_2 = data[:8-self.half_length] _full = _half_1 + _half_2 - print(f"in get_response if broke == 100 _full = {_full}") + # print(f"in get_response if broke == 100 _full = {_full}") _frame_size = int.from_bytes(_full[:2], byteorder='big') _pkg_size = int.from_bytes(_full[2:6], byteorder='big') @@ -139,9 +247,9 @@ class HmiRequest(object): self.pkg_size = _pkg_size self.index = 8 - self.half_length - print(f"broke == 100 index = {self.index}") - print(f"broke == 100 INIT pkg size = {self.pkg_size}") - print(f"broke == 100 data = {data}") + # print(f"broke == 100 index = {self.index}") + # print(f"broke == 100 INIT pkg size = {self.pkg_size}") + # print(f"broke == 100 data = {data}") else: if self.reset_index == 1: self.index = 0 @@ -153,9 +261,9 @@ class HmiRequest(object): self.broke = 0 else: self.index, _frame_size, self.pkg_size = self.header_check(self.index, data) - print(f"broke == 0 index = {self.index-8}") - print(f"broke == 0 INIT pkg size = {self.pkg_size}") - print(f"broke == 0 data = {data}") + # print(f"broke == 0 index = {self.index-8}") + # print(f"broke == 0 INIT pkg size = {self.pkg_size}") + # print(f"broke == 0 data = {data}") if self.index > MAX_FRAME_SIZE: break # 详见解包原理数据.txt,self.pkg_size 永远是除了当前data之外剩余未处理的数据大小 @@ -164,10 +272,10 @@ class HmiRequest(object): self.response = data[self.index:self.index + self.pkg_size].decode() self.msg_storage(flag=0, response=self.response) self.index += self.pkg_size - print(f"in flag=0 if data = {data}") - print(f"in flag=0 if index = {self.index}") - print(f"in flag=0 if pkg size = {self.pkg_size}") - print(f"in flag=0 if leftover = {self.leftover}") + # print(f"in flag=0 if data = {data}") + # print(f"in flag=0 if index = {self.index}") + # print(f"in flag=0 if pkg size = {self.pkg_size}") + # print(f"in flag=0 if leftover = {self.leftover}") self.flag = 0 self.response = '' self.leftover = 0 @@ -177,7 +285,7 @@ class HmiRequest(object): # 执行到这里说明该data是首包,且有有分包的情况发生了也就是该响应数据量稍微比较大 # 分散在了相邻的两个及以上的data中,需要flag=1的处理 self.flag = 1 - if self.index+_frame_size-6 < len(data): + if self.index+_frame_size-6 <= len(data): self.response = data[self.index:self.index+_frame_size-6].decode() self.index += (_frame_size-6) self.pkg_size -= (_frame_size-6) # 详见解包原理数据.txt,self.pkg_size @@ -191,13 +299,13 @@ class HmiRequest(object): if self.index + 2 == len(data): self.broke = 1 self.half = data[-2:] - print(f"flag = 0 encounter broke == 1 - half = {self.half}") + # print(f"flag = 0 encounter broke == 1 - half = {self.half}") elif self.index + 1 == len(data): self.broke = 2 self.half = data[-1:] - print(f"flag = 0 encounter broke == 2 - half = {self.half}") + # print(f"flag = 0 encounter broke == 2 - half = {self.half}") elif self.index == len(data): - print('flag = 0 encounter broke == 3') + # print('flag = 0 encounter broke == 3') self.broke = 3 self.index += MAX_FRAME_SIZE @@ -211,10 +319,10 @@ class HmiRequest(object): self.index += MAX_FRAME_SIZE self.reset_index = 1 - print(f"in flag=0 else data = {data}") - print(f"in flag=0 else index = {self.index}") - print(f"in flag=0 else pkg size = {self.pkg_size}") - print(f"in flag=0 else leftover = {self.leftover}") + # print(f"in flag=0 else data = {data}") + # print(f"in flag=0 else index = {self.index}") + # print(f"in flag=0 else pkg size = {self.pkg_size}") + # print(f"in flag=0 else leftover = {self.leftover}") # break elif self.flag == 1: # 继续处理之前为接收完的数据,处理完之后将flag重置为0 @@ -223,23 +331,23 @@ class HmiRequest(object): self.index = 0 self.leftover = int.from_bytes(self.half, byteorder='big') self.broke = 0 - print(f"broke 1 leftover: {self.leftover}") + # print(f"broke 1 leftover: {self.leftover}") elif self.broke == 2: self.leftover = int.from_bytes(self.half+data[:1], byteorder='big') self.index = 1 self.broke = 0 - print(f"broke 2 leftover: {self.leftover}") + # print(f"broke 2 leftover: {self.leftover}") if self.broke == 3: self.leftover = int.from_bytes(data[:2], byteorder='big') - print(f"broke 3 leftover: {self.leftover}") + # print(f"broke 3 leftover: {self.leftover}") self.index = 2 self.broke = 0 while self.pkg_size > 0: if self.index + self.leftover <= len(data): - print(f"in pkg size > 0 loop before if data = {data}") - print(f"in pkg size > 0 loop before if index = {self.index}") - print(f"in pkg size > 0 loop before if pkg size = {self.pkg_size}") - print(f"in pkg size > 0 loop before if leftover = {self.leftover}") + # print(f"in pkg size > 0 loop before if data = {data}") + # print(f"in pkg size > 0 loop before if index = {self.index}") + # print(f"in pkg size > 0 loop before if pkg size = {self.pkg_size}") + # print(f"in pkg size > 0 loop before if leftover = {self.leftover}") if self.leftover < 0 or self.leftover > 1024: self.w2t("", 0, 111, 'red') self.response += data[self.index:self.index + self.leftover].decode() @@ -252,10 +360,10 @@ class HmiRequest(object): self.leftover = 0 self.pkg_size = 0 self.reset_index = 0 if self.index < len(data) else 1 - print(f"in pkg size > 0 loop break if data = {data}") - print(f"in pkg size > 0 loop break if index = {self.index}") - print(f"in pkg size > 0 loop break if pkg size = {self.pkg_size}") - print(f"in pkg size > 0 loop break if leftover = {self.leftover}") + # print(f"in pkg size > 0 loop break if data = {data}") + # print(f"in pkg size > 0 loop break if index = {self.index}") + # print(f"in pkg size > 0 loop break if pkg size = {self.pkg_size}") + # print(f"in pkg size > 0 loop break if leftover = {self.leftover}") break self.index += self.leftover @@ -268,29 +376,29 @@ class HmiRequest(object): if self.index + 2 == len(data): self.broke = 1 self.half = data[-2:] - print(f"flag = 1 encounter broke == 1 - half = {self.half}") + # print(f"flag = 1 encounter broke == 1 - half = {self.half}") elif self.index + 1 == len(data): self.broke = 2 self.half = data[-1:] - print(f"flag = 1 encounter broke == 2 - half = {self.half}") + # print(f"flag = 1 encounter broke == 2 - half = {self.half}") elif self.index == len(data): - print('flag = 1 encounter broke == 3') + # print('flag = 1 encounter broke == 3') self.broke = 3 self.index += MAX_FRAME_SIZE self.reset_index = 1 break # 因为 index + 2 的大小超过 MAX_FRAME_SIZE - print(f"in pkg size > 0 loop after if data = {data}") - print(f"in pkg size > 0 loop after if index = {self.index}") - print(f"in pkg size > 0 loop after if pkg size = {self.pkg_size}") - print(f"in pkg size > 0 loop after if leftover = {self.leftover}") + # print(f"in pkg size > 0 loop after if data = {data}") + # print(f"in pkg size > 0 loop after if index = {self.index}") + # print(f"in pkg size > 0 loop after if pkg size = {self.pkg_size}") + # print(f"in pkg size > 0 loop after if leftover = {self.leftover}") if self.leftover < 0 or self.leftover > 1024: self.w2t("", 0, 111, 'red') else: - print(f"in pkg size > 0 loop before else data = {data}") - print(f"in pkg size > 0 loop before else index = {self.index}") - print(f"in pkg size > 0 loop before else pkg size = {self.pkg_size}") - print(f"in pkg size > 0 loop before else leftover = {self.leftover}") + # print(f"in pkg size > 0 loop before else data = {data}") + # print(f"in pkg size > 0 loop before else index = {self.index}") + # print(f"in pkg size > 0 loop before else pkg size = {self.pkg_size}") + # print(f"in pkg size > 0 loop before else leftover = {self.leftover}") if self.leftover < 0 or self.leftover > 1024: self.w2t("", 0, 111, 'red') self.response += data[self.index:].decode() @@ -298,22 +406,21 @@ class HmiRequest(object): self.pkg_size -= (len(data) - self.index) self.index += MAX_FRAME_SIZE self.reset_index = 1 - print(f"in pkg size > 0 loop after else data = {data}") - print(f"in pkg size > 0 loop after else index = {self.index}") - print(f"in pkg size > 0 loop after else pkg size = {self.pkg_size}") - print(f"in pkg size > 0 loop after else leftover = {self.leftover}") + # print(f"in pkg size > 0 loop after else data = {data}") + # print(f"in pkg size > 0 loop after else index = {self.index}") + # print(f"in pkg size > 0 loop after else pkg size = {self.pkg_size}") + # print(f"in pkg size > 0 loop after else leftover = {self.leftover}") if self.leftover < 0 or self.leftover > 1024: self.w2t("", 0, 111, 'red') break # 该data内数据已经处理完毕,需要跳出大循环,通过break和index - else: - self.msg_storage(flag=0, response=self.response) - self.flag = 0 - self.response = '' - self.leftover = 0 - self.pkg_size = 0 - self.index -= 2 - # self.reset_index = 1 - self.reset_index = 0 if (len(data) > self.index > 0) else 1 + # else: + # self.msg_storage(flag=0, response=self.response) + # self.flag = 0 + # self.response = '' + # self.leftover = 0 + # self.pkg_size = 0 + # self.index -= 2 + # self.reset_index = 0 if (len(data) > self.index > 0) else 1 def get_response_xs(self, data): if self.flag_xs == 0: @@ -354,8 +461,8 @@ class HmiRequest(object): for i in range(3): for msg in messages: if msg_id is None: - self.w2t("未能成功获取到 message id...", 0, 10, 'red', tab_name=self.tab_name) - if msg_id in msg: + return None + elif msg_id in msg: return msg sleep(1) else: @@ -372,37 +479,13 @@ class HmiRequest(object): return f"{dumps(cmd, separators=(',', ':'))}\r".encode() def unpackage(self, sock): - def to_read(conn): + def to_read(conn, mask): data = conn.recv(MAX_FRAME_SIZE) if data: # print(data) self.get_response(data) else: - print('closing', sock) - sel.unregister(conn) - conn.close() - - sel = selectors.DefaultSelector() - sel.register(sock, selectors.EVENT_READ, to_read) - - while self.t_bool: - try: - events = sel.select() - except: - sleep(1) - continue - for key, mask in events: - callback = key.data - callback(key.fileobj) - - def unpackage_xs(self, sock): - def to_read(conn): - data = conn.recv(1024) # Should be ready - if data: - # print(data) - self.get_response_xs(data) - else: - print('closing', sock) + print('closing', conn) sel.unregister(conn) conn.close() @@ -413,7 +496,27 @@ class HmiRequest(object): events = sel.select() for key, mask in events: callback = key.data - callback(key.fileobj) + callback(key.fileobj, mask) + + def unpackage_xs(self, sock): + def to_read(conn, mask): + data = conn.recv(1024) # Should be ready + if data: + # print(data) + self.get_response_xs(data) + else: + print('closing', conn) + sel.unregister(conn) + conn.close() + + sel = selectors.DefaultSelector() + sel.register(sock, selectors.EVENT_READ, to_read) + + while self.t_bool: + events = sel.select() + for key, mask in events: + callback = key.data + callback(key.fileobj, mask) def gen_id(self, command): _now = time()