diff --git a/.gitignore b/.gitignore index a7c4f60..9689c16 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .idea/ rokae/testbench.py **/__pycache__/ +gui/ +testing/ \ No newline at end of file diff --git a/README.md b/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/rokae/README.md b/rokae/README.md new file mode 100644 index 0000000..b0acab6 --- /dev/null +++ b/rokae/README.md @@ -0,0 +1,220 @@ +## 自动化测试工具脚本 + +### 0. 用前须知 + +1. 调用必须在rokae目录下执行 +2. python3.13开发,使用时需版本匹配,并安装requirements.txt中的依赖库 + +### 1. socket通信(支持xService) + +> #### **A. 调用方法示例** + +```python +from codes import openapi +import time + +hr = openapi.HmiRequest() +time.sleep(2) +hr.close() +msg_id = hr.exec_cmd("controller.get_params") +record = hr.get_from_id(msg_id) +print(f"version = {eval(record)['data']['version']}") +``` + +> #### **B. 目前支持(后续可按需增加)** + +``` +collision.get_params +collision.set_params +controller.get_params +controller.heart +controller.reboot +controller.set_params +device.get_params +diagnosis.get_params +diagnosis.open +diagnosis.save +diagnosis.set_params +drag.get_params +drag.set_params +fieldbus_device.get_params +fieldbus_device.load_cfg +fieldbus_device.set_params +io_device.load_cfg +jog.get_params +jog.set_params +jog.start +log_code.data.code_list +log_code.data +modbus.get_params +modbus.get_values +modbus.load_cfg +modbus.set_params +move.get_joint_pos +move.get_monitor_cfg +move.get_params +move.get_pos +move.get_quickstop_distance +move.get_quickturn_pos +move.quick_turn +move.set_monitor_cfg +move.set_params +move.set_quickstop_distance +move.set_quickturn_pos +move.stop +overview.get_autoload +overview.get_cur_prj +overview.reload +overview.set_autoload +register.set_value +rl_task.pp_to_main +rl_task.run +rl_task.set_run_params +rl_task.stop +safety.safety_area.overall_enable +safety.safety_area.safety_area_enable +safety.safety_area.set_param +safety.safety_area.signal_enable +safety_area_data +servo.clear_alarm +socket.get_params +socket.set_params +soft_limit.get_params +soft_limit.set_params +state.get_state +state.get_tp_mode +state.set_tp_mode +state.switch_auto +state.switch_manual +state.switch_motor_off +state.switch_motor_on +system_io.query_configuration +system_io.query_event_cfg +system_io.update_configuration +``` + +### 2. modbus通信 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +md = openapi.ModbusRequest() +md.r_switch_auto() +_ = md.w_sta_tcp_vel +print(_) +``` + +> #### **B. 目前支持** + +自定义的寄存器读写操作,以及98%以上的预置modbus功能码。 + +### 3. 外部通信 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +ec = openapi.EcRequest() +_ = ec.get_cart_pos +ec.close_reduced_mode() +``` + +> #### **B. 目前支持** + +包括状态和控制操作,覆盖98%以上的外部通信功能。 + +### 4. 文件传输 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +pd = openapi.PreDos() +downloads = "C:/Users/Administrator/Downloads" +pd.pull_prj_from_server("aio", downloads) +local_prj = downloads + "/aio.zip" +pd.push_prj_to_server(local_prj) + +local_file = downloads + "/aio.txt" +server_file = "/tmp/aio.txt" +pd.push_file_to_server(local_file, server_file) +pd.pull_file_from_server(server_file, local_file) +``` + +> #### **B. 目前支持(除了prj_name为工程名,其他均为对应系统下的绝对路径)** + +- push_prj_to_server(prj_file) +- pull_prj_from_server(prj_name, local_prj_path) +- push_file_to_server(local_file, server_file) +- pull_file_from_server(server_file, local_file) + +### 5. 初始化以及固件更新 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +ri = openapi.RobotInit() +ri.robot_init() +ri.fw_updater("C:/Users/Administrator/Downloads/FW/v3.1.1.rpa") +ri.fw_updater("C:/Users/Administrator/Downloads/XMS3-R580-W4G3C2_ME_AE_SS_xC.v3.1.0.R0.rpa") +``` + +> #### **B. 目前支持** + +- robot_init() # 初始化机器人,新建modbus设备,并配置寄存器文件,打开IO设备中的modbus设备 +- fw_updater(fw_file) # 目前仅测试支持机型文件和控制器 + +### 6. 升级协议 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +ur = openapi.UpgradeRequest() +ur.version_query() +ur.robot_reboot() +``` + +> #### **B. 目前支持** + +- erase_cfg +- clear_rubbish +- soft_reboot +- version_query +- robot_reboot +- backup_origin +- origin_recovery + +### 7. 生成运动轨迹 + +> #### **A. 调用方法示例** + +```python +from codes import openapi + +hr = openapi.HmiRequest() +pd = openapi.PreDos() # 如下三行首次运行时,必须打开 +ri = openapi.RobotInit(hr, pd) # 非首次重复运行时,可以注释 +ri.robot_init() # 注释后可以节省运行时间 +md = openapi.ModbusRequest() + +pt = openapi.PlotTrajectory(hr, md, prj_name="arc_test_M", tasks=["task0", ], curve_name="hw_cart_pos_feedback_tcp_in_world") +pt.draw_traj() +``` + +> #### **B. 目前支持** + +自动保存3D空间运动曲线图到本地的trajectory.html文件 + +- hw_cart_pos_feedback_motorside +- hw_cart_pos_feedback_linkside +- hw_cart_pos_feedback_encoder_tcp_in_world +- hw_cart_pos_feedback_flan_in_world +- hw_cart_pos_feedback_tcp_in_world diff --git a/rokae/assets/confs/configs.json b/rokae/assets/confs/configs.json index f3f3325..f939c3b 100644 --- a/rokae/assets/confs/configs.json +++ b/rokae/assets/confs/configs.json @@ -1,5 +1,5 @@ { - "ip_addr": "192.168.40.130", + "ip_addr": "192.168.0.160", "ssh_port": "22", "socket_port": 5050, "xService_port": 6666, diff --git a/rokae/codes/openapi.cp313-win_amd64.pyd b/rokae/codes/openapi.cp313-win_amd64.pyd new file mode 100644 index 0000000..0de65e7 Binary files /dev/null and b/rokae/codes/openapi.cp313-win_amd64.pyd differ diff --git a/rokae/codes/openapi.py b/rokae/codes/openapi.py index b29cfbc..4174692 100644 --- a/rokae/codes/openapi.py +++ b/rokae/codes/openapi.py @@ -11,13 +11,18 @@ from typing import Callable, Dict from loguru import logger from pymodbus.client.tcp import ModbusTcpClient from paramiko import SSHClient, AutoAddPolicy +import plotly.graph_objects as go from codes import clibs class HmiRequest: def __init__(self): - self.c = self.c_xs = self.t_rx_pkg = self.t_rx_pkg_xs = self.t_s_heart = None + self.c: socket.socket + self.c_xs: socket.socket + self.t_rx_pkg: threading.Thread + self.t_rx_pkg_xs: threading.Thread + self.t_s_heart: threading.Thread self.data = self.data_xs = b"" self.is_connected = True self.sock_conn() @@ -170,8 +175,8 @@ class HmiRequest: cmd, ts = msg_id.split("@") t = ts.replace("T", " ") t_ts = datetime.timestamp(datetime.strptime(t, "%Y-%m-%d %H:%M:%S.%f")) - t_send = datetime.strftime(datetime.fromtimestamp(t_ts-time_delay), '%Y-%m-%d %H:%M:%S.%f') - t_receive = datetime.strftime(datetime.fromtimestamp(t_ts+time_delay), '%Y-%m-%d %H:%M:%S.%f') + t_send = datetime.strftime(datetime.fromtimestamp(t_ts-time_delay), "%Y-%m-%d %H:%M:%S.%f") + t_receive = datetime.strftime(datetime.fromtimestamp(t_ts+time_delay), "%Y-%m-%d %H:%M:%S.%f") for idx in range(time_delay): time.sleep(clibs.interval) try: @@ -187,7 +192,7 @@ class HmiRequest: logger.error(f"hr: {time_delay}s内无法找到请求 {msg_id} 的响应!") # raise Exception() - def exec_cmd(self, cmd, **kwargs): + def exec_cmd(self, cmd: str, **kwargs): try: with open(f"{clibs.base_path}/assets/protocols/{cmd}.json", mode="r", encoding="utf-8") as f_cmd: req = json.load(f_cmd) @@ -199,15 +204,14 @@ class HmiRequest: logger.error(f"hr: 暂不支持 {cmd} 功能,或确认该功能存在,err = {err}") raise Exception() - match cmd: - case "state.set_tp_mode" | "overview.set_autoload" | "overview.reload" | "rl_task.pp_to_main" | "rl_task.run" | "rl_task.stop" | "rl_task.set_run_params" | "diagnosis.set_params" | "diagnosis.open" | "drag.set_params" | "controller.set_params" | "collision.set_params" | "move.set_quickstop_distance" | "move.set_params" | "move.set_monitor_cfg" | "modbus.get_values" | "modbus.set_params" | "system_io.update_configuration" | "diagnosis.get_params" | "jog.set_params" | "jog.start" | "move.stop" | "move.quick_turn" | "move.set_quickturn_pos" | "soft_limit.set_params" | "fieldbus_device.set_params" | "socket.set_params" | "diagnosis.save" | "register.set_value": - req["data"].update(kwargs) - case "safety.safety_area.signal_enable" | "safety.safety_area.overall_enable" | "safety.safety_area.safety_area_enable" | "safety.safety_area.set_param": - req["c"].update(kwargs) - case "log_code.data.code_list": - req["s"]["log_code.data"]["code_list"] = kwargs["code_list"] - case _: - pass + if cmd in ["state.set_tp_mode", "overview.set_autoload", "overview.reload", "rl_task.pp_to_main", "rl_task.run", "rl_task.stop", "rl_task.set_run_params", "diagnosis.set_params", "diagnosis.open", "drag.set_params", "controller.set_params", "collision.set_params", "move.set_quickstop_distance", "move.set_params", "move.set_monitor_cfg", "modbus.get_values", "modbus.set_params", "system_io.update_configuration", "diagnosis.get_params", "jog.set_params", "jog.start", "move.stop", "move.quick_turn", "move.set_quickturn_pos", "soft_limit.set_params", "fieldbus_device.set_params", "socket.set_params", "diagnosis.save", "register.set_value"]: + req["data"].update(kwargs) + elif cmd in ["safety.safety_area.signal_enable", "safety.safety_area.overall_enable", "safety.safety_area.safety_area_enable", "safety.safety_area.set_param"]: + req["c"].update(kwargs) + elif cmd in ["log_code.data.code_list"]: + req["s"]["log_code.data"]["code_list"] = kwargs["code_list"] + else: + pass cmd = json.dumps(req, separators=(",", ":")) if p_type == 0: @@ -217,12 +221,13 @@ class HmiRequest: else: raise Exception("Unexpected CMD Input") + time.sleep(clibs.interval/4) return req["id"] class ModbusRequest: def __init__(self): - self.c = None + self.c: ModbusTcpClient self.sock_conn() def sock_conn(self): @@ -250,10 +255,10 @@ class ModbusRequest: def r_reset_estop_clear_alarm(self): self.__reg_high_pulse(40002, "复位外部急停状态,并清除告警信息") - def r_motor_off(self): + def r_motor_on(self): self.__reg_high_pulse(40004, "上电") - def r_motor_on(self): + def r_motor_off(self): self.__reg_high_pulse(40005, "下电") def r_motor_on_off(self, action: bool): @@ -333,7 +338,7 @@ class ModbusRequest: def __get_state(self, addr: int, count: int = 1, **kwargs): res = self.c.read_holding_registers(addr, count=count).registers[0] - logger.info(f"md: {addr}-{kwargs['func']},结果为{res} {kwargs['desc']}") + logger.info(f'md: {addr}-{kwargs["func"]},结果为{res} {kwargs["desc"]}') return res @property @@ -501,7 +506,7 @@ class ModbusRequest: class EcRequest: def __init__(self): - self.c = None + self.c: socket.socket self.exec_desc = " :--: true表示执行成功,false表示执行失败" self.sock_conn() @@ -783,7 +788,7 @@ class PreDos(object): logger.error(f"pd: SSH无法连接,需检查网络连通性或者登录信息是否正确 -- {e}") raise Exception() - def push_prj_to_server(self, prj_file): + def push_prj_to_server(self, prj_file: str): # prj_file:工程的本地完整路径 self.__ssh2server() prj_name, postfix = os.path.basename(prj_file).split(".") @@ -797,7 +802,7 @@ class PreDos(object): _ = stderr.read().decode() self.__ssh.close() - def pull_prj_from_server(self, prj_name, local_prj_path): + def pull_prj_from_server(self, prj_name: str, local_prj_path: str): # prj_name:要拉取的服务端工程名 # local_prj_path:存放工程文件的本地路径 self.__ssh2server() @@ -817,7 +822,7 @@ class PreDos(object): self.__ssh.close() - def push_file_to_server(self, local_file, server_file): + def push_file_to_server(self, local_file: str, server_file: str): # local_file:本地文件完整路径 # server_file:服务端文件完整路径 self.__ssh2server() @@ -830,7 +835,7 @@ class PreDos(object): _ = stderr.read().decode() self.__ssh.close() - def pull_file_from_server(self, server_file, local_file): + def pull_file_from_server(self, server_file: str, local_file: str): # local_file:本地文件完整路径 # server_file:服务端文件完整路径 self.__ssh2server() @@ -851,9 +856,9 @@ class PreDos(object): class RobotInit(object): - def __init__(self): - self.pd = PreDos() - self.hr = HmiRequest() + def __init__(self, hr: HmiRequest, pd: PreDos): + self.hr: HmiRequest = hr + self.pd: PreDos = pd def robot_init(self): # 推送配置文件 @@ -903,7 +908,7 @@ class RobotInit(object): self.hr.exec_cmd("io_device.load_cfg") self.hr.exec_cmd("modbus.load_cfg") - def fw_updater(self, fw_file): + def fw_updater(self, fw_file: str): """ :param fw_file: xCore升级文件/机型文件的绝对路径 :return: None @@ -984,7 +989,7 @@ class UpgradeRequest: http://confluence.i.rokae.com/pages/viewpage.action?pageId=21531754 """ def __init__(self): - self.c = None + self.c: socket.socket self.sock_conn() def sock_conn(self): @@ -1039,3 +1044,88 @@ class UpgradeRequest: def origin_recovery(self): # OK 恢复备份,恢复后手动设置,并重启生效 self.sr_pkg({"cmd": "recover"}) + + +class PlotTrajectory: + # hw_cart_pos_feedback_motorside:笛卡尔空间下电机侧位置反馈,单位m,rad + # hw_cart_pos_feedback_linkside:笛卡尔空间下连杆侧位置反馈,单位m,rad + # hw_cart_pos_feedback_encoder_tcp_in_world:笛卡尔位置反馈(关节端编码器数据),单位m,rad + # hw_cart_pos_feedback_flan_in_world:笛卡尔位置反馈(法兰相对于世界坐标系) + # hw_cart_pos_feedback_tcp_in_world:笛卡尔位置反馈(tcp相对于世界坐标系) + def __init__(self, hr: HmiRequest, md: ModbusRequest, prj_name: str, tasks: list, curve_name: str = "hw_cart_pos_feedback_tcp_in_world"): + self.hr: HmiRequest = hr + self.md: ModbusRequest = md + self.curve_name: str = curve_name + self.prj_name: str = prj_name + self.tasks: list = tasks + + def __change_curve_state(self, stat): + if not stat: + display_pdo_params = [{"name": "count", "channel": 0}] + else: + display_pdo_params = [{"name": self.curve_name, "channel": chl} for chl in range(3)] + self.hr.exec_cmd("diagnosis.set_params", display_pdo_params=display_pdo_params) + self.hr.exec_cmd("diagnosis.open", open=stat, display_open=stat) + + def __plot_trajectory(self, start_time, end_time): + x, y, z = [], [], [] + try: + clibs.lock.acquire(True) + clibs.cursor.execute(f"SELECT content FROM logs WHERE timestamp BETWEEN '{start_time}' AND '{end_time}' AND content LIKE '%diagnosis.result%' ORDER BY id ASC") + records = clibs.cursor.fetchall() + finally: + clibs.lock.release() + + for record in records: + data = eval(record[0])["data"] + for item in data: + item_rm = [x * 1000 for x in reversed(item["value"])] + # item_rm = item["value"] + if item.get("channel", None) == 0 and item.get("name", None) == self.curve_name: + x.extend(item_rm) + elif item.get("channel", None) == 1 and item.get("name", None) == self.curve_name: + y.extend(item_rm) + elif item.get("channel", None) == 2 and item.get("name", None) == self.curve_name: + z.extend(item_rm) + + # pyplot + trace_path = go.Scatter3d(x=x, y=y, z=z, mode="lines", line=dict(color="blue", width=4), name="运动轨迹") + trace_start = go.Scatter3d(x=[x[0]], y=[y[0]], z=[z[0]], mode="markers+text", marker=dict(color="green", size=8), text=["起点"], textposition="top center", name="起点") + trace_end = go.Scatter3d(x=[x[-1]], y=[y[-1]], z=[z[-1]], mode="markers+text", marker=dict(color="red", size=8), text=["终点"], textposition="bottom center", name="终点") + fig = go.Figure(data=[trace_path, trace_start, trace_end]) + fig.write_html("trajectory.html", auto_open=False) + + fig.update_layout( + scene=dict( + xaxis_title="X", + yaxis_title="Y", + zaxis_title="Z" + ), + margin=dict(l=0, r=0, b=0, t=30), + legend=dict(x=0, y=1), + dragmode="orbit" + ) + + fig.show(config={"scrollZoom": True}) + + def draw_traj(self): + self.md.r_soft_estop(True) + self.md.r_reset_estop_clear_alarm() + self.md.r_switch_auto() + self.md.r_motor_on() + + self.__change_curve_state(True) + self.hr.exec_cmd("overview.reload", prj_path=f"{self.prj_name}/_build/{self.prj_name}.prj", tasks=self.tasks) + self.hr.exec_cmd("rl_task.set_run_params", loop_mode=False, override=1.0) + self.hr.exec_cmd("rl_task.pp_to_main", tasks=self.tasks) + self.hr.exec_cmd("rl_task.run", tasks=self.tasks) + + t_start = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) + time.sleep(clibs.interval) + while self.md.w_sta_robot_is_moving: + time.sleep(clibs.interval * 10) + time.sleep(clibs.interval * 5) + t_end = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) + self.__change_curve_state(False) + + self.__plot_trajectory(t_start, t_end) diff --git a/rokae/codes/openapi.pyi b/rokae/codes/openapi.pyi new file mode 100644 index 0000000..00ca192 --- /dev/null +++ b/rokae/codes/openapi.pyi @@ -0,0 +1,229 @@ +import socket +import threading +from pymodbus.client.tcp import ModbusTcpClient + +class HmiRequest: + is_connected: bool + def __init__(self) -> None: ... + def close(self) -> None: ... + @staticmethod + def get_from_id(msg_id: str) -> str: ... + def exec_cmd(self, cmd: str, **kwargs): ... + +class ModbusRequest: + def __init__(self) -> None: ... + def r_clear_alarm(self) -> None: ... + def r_reset_estop(self) -> None: ... + def r_reset_estop_clear_alarm(self) -> None: ... + def r_motor_on(self) -> None: ... + def r_motor_off(self) -> None: ... + def r_motor_on_off(self, action: bool): ... + def r_motoron_pp2main_start(self) -> None: ... + def r_motoron_start(self) -> None: ... + def r_pulse_motoroff(self) -> None: ... + def r_pp2main(self) -> None: ... + def r_program_start(self) -> None: ... + def r_program_stop(self) -> None: ... + def r_program_start_stop(self, action: bool): ... + def r_set_program_speed(self, speed: int): ... + def r_soft_estop(self, action: bool): ... + def r_switch_auto_motoron(self) -> None: ... + def r_switch_auto(self) -> None: ... + def r_switch_manual(self) -> None: ... + def r_switch_auto_manual(self, action: bool): ... + def r_reduced_mode(self, action: bool): ... + def r_switch_safe_region(self, idx: int, enable: bool): ... + @property + def w_alarm_state(self): ... + @property + def w_sta_collision(self): ... + @property + def w_sta_collision_alarm(self): ... + @property + def w_sta_collision_open(self): ... + @property + def w_controller_is_running(self): ... + @property + def w_encoder_low_battery(self): ... + @property + def w_sta_error_code(self): ... + @property + def w_sta_estop(self): ... + @property + def w_sta_heartbeat(self): ... + @property + def w_sta_home(self): ... + @property + def w_sta_motor(self): ... + @property + def w_sta_operation_mode(self): ... + @property + def w_sta_program(self): ... + @property + def w_sta_program_full(self): ... + @property + def w_sta_program_not_run(self): ... + @property + def w_sta_program_reset(self): ... + @property + def w_sta_program_speed(self): ... + @property + def w_sta_reduce_mode(self): ... + @property + def w_sta_robot_is_busy(self): ... + @property + def w_sta_robot_is_moving(self): ... + @property + def w_safe_door_state(self): ... + @property + def w_sta_safe_jnt_pos(self): ... + @property + def w_sta_soft_estop(self): ... + @property + def w_sta_safe_region(self): ... + @property + def w_sta_on_path(self): ... + @property + def w_sta_near_path(self): ... + @property + def w_sta_cart_pose(self) -> list: ... + @property + def w_sta_cart_vel(self) -> list: ... + @property + def w_sta_jnt_pose(self) -> list: ... + @property + def w_sta_jnt_vel(self) -> list: ... + @property + def w_sta_tcp_pose(self) -> list: ... + @property + def w_sta_tcp_vel(self) -> list: ... + @property + def w_sta_tcp_vel_mag(self): ... + def io_write_coils(self, addr, value: bool): ... + def io_read_coils(self): ... + def io_read_discretes(self): ... + +class EcRequest: + def __init__(self) -> None: ... + def motor_on(self): ... + def motor_off(self): ... + def pp_to_main(self): ... + def program_start(self): ... + def program_stop(self): ... + def clear_alarm(self): ... + def switch_operation_auto(self): ... + def switch_operation_manual(self): ... + def open_drag_mode(self): ... + def close_drag_mode(self): ... + def get_project_list(self): ... + def get_current_project(self): ... + def load_project(self, project_name): ... + def estop_reset(self): ... + def estopreset_and_clearalarm(self): ... + def motoron_pp2main_start(self): ... + def motoron_start(self): ... + def pause_motoroff(self): ... + def set_program_speed(self, speed: int = 20): ... + def set_soft_estop(self, enable: str): ... + def switch_auto_motoron(self): ... + def open_safe_region(self, number: int): ... + def close_safe_region(self, number: int): ... + def open_reduced_mode(self): ... + def close_reduced_mode(self): ... + def setdo_value(self, do_name: str, do_value: str): ... + def set_robot_time(self, robot_time: str = ...): ... + @property + def motor_on_state(self): ... + @property + def robot_running_state(self): ... + @property + def estop_state(self): ... + @property + def operation_mode(self): ... + @property + def home_state(self): ... + @property + def fault_state(self): ... + @property + def collision_state(self): ... + @property + def task_state(self): ... + @property + def get_cart_pos(self): ... + @property + def get_joint_pos(self): ... + @property + def get_joint_vel(self): ... + @property + def get_joint_trq(self): ... + @property + def reduced_mode_state(self): ... + def get_io_state(self, io_list: str): ... + @property + def alarm_state(self): ... + @property + def collision_alarm_state(self): ... + @property + def collision_open_state(self): ... + @property + def controller_is_running(self): ... + @property + def encoder_low_battery_state(self): ... + @property + def robot_error_code(self): ... + @property + def rl_pause_state(self): ... + @property + def program_reset_state(self): ... + @property + def program_speed_value(self): ... + @property + def robot_is_busy(self): ... + @property + def robot_is_moving(self): ... + @property + def safe_door_state(self): ... + @property + def soft_estop_state(self): ... + @property + def get_cart_vel(self): ... + @property + def get_tcp_pos(self): ... + @property + def get_tcp_vel(self): ... + @property + def get_tcp_vel_mag(self): ... + @property + def ext_estop_state(self): ... + @property + def hand_estop_state(self): ... + @property + def sta_on_path(self): ... + @property + def sta_near_path(self): ... + +class PreDos: + def __init__(self) -> None: ... + def push_prj_to_server(self, prj_file: str): ... + def pull_prj_from_server(self, prj_name: str, local_prj_path: str): ... + def push_file_to_server(self, local_file: str, server_file: str): ... + def pull_file_from_server(self, server_file: str, local_file: str): ... + +class RobotInit: + def __init__(self, hr: HmiRequest, pd: PreDos) -> None: ... + def robot_init(self) -> None: ... + def fw_updater(self, fw_file: str): ... + +class UpgradeRequest: + def __init__(self) -> None: ... + def erase_cfg(self) -> None: ... + def clear_rubbish(self) -> None: ... + def soft_reboot(self) -> None: ... + def version_query(self) -> None: ... + def robot_reboot(self) -> None: ... + def backup_origin(self) -> None: ... + def origin_recovery(self) -> None: ... + +class PlotTrajectory: + def __init__(self, hr: HmiRequest, md: ModbusRequest, prj_name: str, tasks: list, curve_name: str = 'hw_cart_pos_feedback_tcp_in_world') -> None: ... + def draw_traj(self) -> None: ... diff --git a/rokae/requirements.txt b/rokae/requirements.txt new file mode 100644 index 0000000..db8a4ab --- /dev/null +++ b/rokae/requirements.txt @@ -0,0 +1,4 @@ +loguru==0.7.3 +paramiko==3.5.1 +plotly==6.3.0 +pymodbus==3.9.2 diff --git a/rokae/自动化测试工具脚本说明.pdf b/rokae/自动化测试工具脚本说明.pdf new file mode 100644 index 0000000..6b5e164 Binary files /dev/null and b/rokae/自动化测试工具脚本说明.pdf differ