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的内容完全拷贝到此文件,待修改
This commit is contained in:
gitea 2024-06-29 20:40:17 +08:00
parent 802ccd8e97
commit 611d848b41
13 changed files with 398 additions and 84 deletions

View File

@ -339,4 +339,19 @@ v0.1.7.1(2024/06/29)
- 文件合规性检查 - 文件合规性检查
- 导入工程并设置为运行工程 - 导入工程并设置为运行工程
4. [APIs: current.py] 修改scenario/single电机电流最大长度为150s 4. [APIs: current.py] 修改scenario/single电机电流最大长度为150s
5. 在本文件中更新关于制动自动化测试的相关内容 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的内容完全拷贝到此文件待修改

View File

@ -0,0 +1,8 @@
{
"id": "xxxxxxxxxxx",
"module": "robot",
"command": "diagnosis.get_params",
"data": {
"version": "1.4.1"
}
}

View File

@ -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
}
}

View File

@ -0,0 +1,8 @@
{
"id": "xxxxxxxxxxx",
"module": "robot",
"command": "diagnosis.save",
"data": {
"save": true
}
}

View File

@ -0,0 +1,10 @@
{
"id": "xxxxxxxxxxx",
"module": "robot",
"command": "diagnosis.set_params",
"data": {
"display_pdo_params": [],
"frequency": 50,
"version": "1.4.1"
}
}

View File

@ -0,0 +1,8 @@
{
"id": "xxxxxxxxxxx",
"module": "project",
"command": "rl_task.pp_to_main",
"data": {
"tasks": []
}
}

View File

@ -0,0 +1,8 @@
{
"id": "xxxxxxxxxxx",
"module": "project",
"command": "rl_task.run",
"data": {
"tasks": []
}
}

View File

@ -0,0 +1,8 @@
{
"id": "xxxxxxxxxxx",
"module": "project",
"command": "rl_task.stop",
"data": {
"tasks": []
}
}

View File

@ -200,17 +200,17 @@ class App(customtkinter.CTk):
c_state = f_hb.read().strip() c_state = f_hb.read().strip()
pb_color = 'green' if c_state == '1' else 'red' pb_color = 'green' if c_state == '1' else 'red'
self.progressbar.configure(progress_color=pb_color) self.progressbar.configure(progress_color=pb_color)
sleep(1)
if c_state == '0': 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 self.hr.t_bool = False
sleep(1) sleep(4)
del self.hr del self.hr
self.hr = openapi.HmiRequest(self.write2textbox) self.hr = openapi.HmiRequest(self.write2textbox)
sleep(3)
def tabview_click(self): def tabview_click(self):
self.initialization() self.initialization()
self.textbox.delete(index1='1.0', index2='end') # self.textbox.delete(index1='1.0', index2='end')
tab_name = self.tabview.get() tab_name = self.tabview.get()
if tab_name == 'Data Process': if tab_name == 'Data Process':
@ -221,6 +221,7 @@ class App(customtkinter.CTk):
def initialization(self): def initialization(self):
tab_name = self.tabview.get() tab_name = self.tabview.get()
self.textbox.delete(index1='1.0', index2='end')
if tab_name == 'Data Process': if tab_name == 'Data Process':
for widgit in widgits_dp: for widgit in widgits_dp:
if widgit in ['path', 'av', 'rc', 'rpm', 'rr', 'dur', 'rc1', 'rc2', 'rc3', 'rc4', 'rc5', 'rc6']: 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') widgits_dp[widgit]['optionmenu'].configure(state='disabled')
self.menu_sub_dp.grid_forget() self.menu_sub_dp.grid_forget()
self.textbox.delete(index1='1.0', index2='end')
elif tab_name == 'Automatic Test': elif tab_name == 'Automatic Test':
for widgit in widgits_at: 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']: 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]['label'].configure(text_color="red")
widgits_dp[widgit]['optionmenu'].configure(state='normal') 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_add(color, 'insert', 'end')
self.textbox.tag_config(tagName=color, foreground=color) self.textbox.tag_config(tagName=color, foreground=color)
tab_name_cur = self.tabview.get()
if wait != 0: if tab_name == tab_name_cur:
self.textbox.insert(index='end', text=text, tags=color) if wait != 0:
self.textbox.update() self.textbox.insert(index='end', text=text, tags=color)
self.textbox.see('end') self.textbox.update()
elif exitcode != 0: self.textbox.see('end')
self.textbox.insert(index='end', text=text + '\n', tags=color) elif exitcode != 0:
self.textbox.update() self.textbox.insert(index='end', text=text + '\n', tags=color)
self.textbox.see('end') self.textbox.update()
raise Exception(f"Error code: {exitcode}") self.textbox.see('end')
else: raise Exception(f"Error code: {exitcode}")
self.textbox.insert(index='end', text=text + '\n', tags=color) else:
self.textbox.update() self.textbox.insert(index='end', text=text + '\n', tags=color)
self.textbox.see('end') self.textbox.update()
self.textbox.see('end')
def is_float(self, flag, *args): def is_float(self, flag, *args):
for item in args: for item in args:

View File

@ -5,20 +5,20 @@ from sys import argv
def validate_resp(_id, response, w2t): def validate_resp(_id, response, w2t):
match _id: match _id:
case 'DATA ERR': case 'DATA ERR':
w2t(f"数据处理错误,需要确认", 0, 4, 'red') w2t(f"数据处理错误,需要确认", 0, 4, 'red', tab_name='Automatic Test')
case 'DATA READ ERR': case 'DATA READ ERR':
w2t(f"无法读取数据,需要确认", 0, 3, 'red') w2t(f"无法读取数据,需要确认", 0, 3, 'red', tab_name='Automatic Test')
case 'NOT SUPPORT': case 'NOT SUPPORT':
w2t(f"不支持的功能,需要确认", 0, 2, 'red') w2t(f"不支持的功能,需要确认", 0, 2, 'red', tab_name='Automatic Test')
if not response: 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): def execution(cmd, hr, w2t, **kwargs):
_id = hr.excution(cmd, **kwargs) _id = hr.excution(cmd, **kwargs)
_msg = hr.get_from_id(_id) _msg = hr.get_from_id(_id)
if not _msg: if not _msg:
w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test')
else: else:
_response = json.loads(_msg) _response = json.loads(_msg)
validate_resp(_id, _response, w2t) validate_resp(_id, _response, w2t)
@ -30,7 +30,7 @@ def get_state(hr, w2t):
_response = execution('state.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': '工作任务空间'} stat_desc = {'engine': '上电状态', 'operate': '操作模式', 'rc_state': '控制器状态', 'robot_action': '机器人动作', 'safety_mode': '安全模式', 'servo_mode': '伺服工作模式', 'task_space': '工作任务空间'}
for component, state in _response['data'].items(): 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) _response = execution('device.get_params', hr, w2t)
@ -39,7 +39,7 @@ def get_state(hr, w2t):
for device in _response['data']['devices']: for device in _response['data']['devices']:
dev_vers[device['type']] = device['version'] dev_vers[device['type']] = device['version']
for i in sorted(dev_desc.keys()): 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') _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): def warning_info(hr, w2t):
for msg in hr.c_msg: for msg in hr.c_msg:
if 'alarm' in msg.lower(): if 'alarm' in msg.lower():
w2t(msg) w2t(msg, tab_name='Automatic Test')
for msg in hr.c_msg_xs: for msg in hr.c_msg_xs:
if 'alarm' in msg.lower(): if 'alarm' in msg.lower():
w2t(msg) w2t(msg, tab_name='Automatic Test')
def main(hr, func, w2t): def main(hr, func, w2t):
if hr is None: if hr is None:
w2t("无法连接机器人检查是否已经使用Robot Assist软件连接机器重试中...", 0, 49, 'red') w2t("无法连接机器人检查是否已经使用Robot Assist软件连接机器重试中...", 0, 49, 'red', tab_name='Automatic Test')
# func: get_state/ # func: get_state/
match func: match func:
case 'get_state': case 'get_state':

View File

@ -1,8 +1,9 @@
from time import sleep
from sys import argv from sys import argv
from os import scandir from os import scandir
from os.path import exists from os.path import exists
import paramiko from paramiko import SSHClient, AutoAddPolicy
import json from json import loads
def traversal_files(path, w2t): def traversal_files(path, w2t):
@ -11,7 +12,7 @@ def traversal_files(path, w2t):
# 返回值:路径下的文件夹列表 路径下的文件列表 # 返回值:路径下的文件夹列表 路径下的文件列表
if not exists(path): if not exists(path):
msg = f'数据文件夹{path}不存在,请确认后重试......' msg = f'数据文件夹{path}不存在,请确认后重试......'
w2t(msg, 0, 1, 'red') w2t(msg, 0, 1, 'red', tab_name='Automatic Test')
else: else:
dirs = [] dirs = []
files = [] files = []
@ -26,8 +27,8 @@ def traversal_files(path, w2t):
def check_files(data_dirs, data_files, w2t): def check_files(data_dirs, data_files, w2t):
if len(data_dirs) != 0 or len(data_files) != 5: if len(data_dirs) != 0 or len(data_files) != 5:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, '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') 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 config_file = reach33 = reach66 = reach100 = prj_file = None
for data_file in data_files: for data_file in data_files:
@ -43,20 +44,20 @@ def check_files(data_dirs, data_files, w2t):
elif filename.endswith('.zip'): elif filename.endswith('.zip'):
prj_file = data_file prj_file = data_file
else: else:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, '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') 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: 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 return config_file, reach33, reach66, reach100, prj_file
else: else:
w2t('初始路径下不允许有文件夹,且初始路径下只能存在如下五个文件,确认后重新运行!', 0, 0, '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') 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): def prj_to_xcore(prj_file):
ssh = paramiko.SSHClient() ssh = SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) ssh.set_missing_host_key_policy(AutoAddPolicy())
ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019') ssh.connect('192.168.0.160', 22, username='luoshi', password='luoshi2019')
sftp = ssh.open_sftp() sftp = ssh.open_sftp()
# stdin, stdout, stderr = ssh.exec_command('rm /tmp/target.zip') # stdin, stdout, stderr = ssh.exec_command('rm /tmp/target.zip')
@ -76,6 +77,14 @@ def prj_to_xcore(prj_file):
stdin.flush() stdin.flush()
print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo
print(stderr.read().decode()) # 顺便也执行以下stderr 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() ssh.close()
@ -86,42 +95,79 @@ def modify_prj():
def validate_resp(_id, response, w2t): def validate_resp(_id, response, w2t):
match _id: match _id:
case 'DATA ERR': case 'DATA ERR':
w2t(f"数据处理错误,需要确认", 0, 4, 'red') w2t(f"数据处理错误,需要确认", 0, 4, 'red', tab_name='Automatic Test')
case 'DATA READ ERR': case 'DATA READ ERR':
w2t(f"无法读取数据,需要确认", 0, 3, 'red') w2t(f"无法读取数据,需要确认", 0, 3, 'red', tab_name='Automatic Test')
case 'NOT SUPPORT': case 'NOT SUPPORT':
w2t(f"不支持的功能,需要确认", 0, 2, 'red') w2t(f"不支持的功能,需要确认", 0, 2, 'red', tab_name='Automatic Test')
if not response: 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): def execution(cmd, hr, w2t, **kwargs):
_id = hr.excution(cmd, **kwargs) _id = hr.excution(cmd, **kwargs)
_msg = hr.get_from_id(_id) _msg = hr.get_from_id(_id)
if not _msg: if not _msg:
w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red') w2t(f"无法获取{_id}请求的响应信息", 0, 6, 'red', tab_name='Automatic Test')
else: else:
_response = json.loads(_msg) _response = loads(_msg)
validate_resp(_id, _response, w2t) validate_resp(_id, _response, w2t)
return _response return _response
def run_rl(hr, w2t): def run_rl(hr, w2t):
prj_path = '/home/luoshi/bin/controller/projects/target' # prj_path = 'target/_build/target.prj'
_response = execution('overview.set_autoload', hr, w2t, autoload_prj_path=prj_path) # _response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com'])
print(f"set prj auto load: {_response}") # print(f"reload prj: {_response}")
_response = execution('overview.reload', hr, w2t, prj_path=prj_path, tasks=['Durable_Test_Com', 'Mechanical_Test_Com']) # # _response = execution('overview.get_cur_prj', hr, w2t)
print(f"reload prj: {_response}") # # print(f"get cur prj name: {_response}")
_response = execution('overview.get_cur_prj', hr, w2t) # _response = execution('rl_task.pp_to_main', hr, w2t, tasks=['Mechanical_Test_Com'])
print(f"get prj name: {_response}") # print(f"set pp2main of prj: {_response}")
_response = execution('overview.get_autoload', hr, w2t) #
print(f"get auto load: {_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): def main(path, hr, loadsel, w2t):
data_dirs, data_files = traversal_files(path, w2t) data_dirs, data_files = traversal_files(path, w2t)
config_file, reach33, reach66, reach100, prj_file = check_files(data_dirs, data_files, 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) run_rl(hr, w2t)

View File

@ -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:])

View File

@ -1,13 +1,13 @@
import json from json import load, dumps
import socket from socket import socket, setdefaulttimeout, AF_INET, SOCK_STREAM
import threading from threading import Thread
import selectors import selectors
import time from time import time, sleep
import os from os.path import dirname
MAX_FRAME_SIZE = 1024 MAX_FRAME_SIZE = 1024
socket.setdefaulttimeout(2) setdefaulttimeout(2)
current_path = os.path.dirname(__file__) current_path = dirname(__file__)
class HmiRequest(object): class HmiRequest(object):
@ -24,15 +24,16 @@ class HmiRequest(object):
self.flag_xs = 0 self.flag_xs = 0
self.response_xs = '' self.response_xs = ''
self.t_bool = True self.t_bool = True
self.tab_name = 'Automatic Test'
self.sock_conn() 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.daemon = True
self.t_heartbeat.start() 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.daemon = True
self.t_unpackage.start() 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.daemon = True
self.t_unpackage_xs.start() self.t_unpackage_xs.start()
@ -42,21 +43,21 @@ class HmiRequest(object):
c_state = f_hb.read().strip() c_state = f_hb.read().strip()
if c_state == '0': if c_state == '0':
try: 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.0.160', 5050))
# self.c.connect(('192.168.84.129', 5050)) # self.c.connect(('192.168.84.129', 5050))
self.c.setblocking(False) 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.0.160', 6666))
# self.c_xs.connect(('192.168.84.129', 6666)) # self.c_xs.connect(('192.168.84.129', 6666))
self.c_xs.setblocking(False) 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: with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb:
f_hb.write('1') f_hb.write('1')
except Exception as Err: 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: with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb:
f_hb.write('0') f_hb.write('0')
@ -81,20 +82,24 @@ class HmiRequest(object):
while self.t_bool: while self.t_bool:
_id = self.excution('controller.heart') _id = self.excution('controller.heart')
_flag = '0' if self.get_from_id(_id) is None else '1' _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: with open(f"{current_path}/../../assets/templates/heartbeat", "w", encoding='utf-8') as f_hb:
f_hb.write(_flag) f_hb.write(_flag)
time.sleep(3) if _flag == '0':
# with open('log.txt', 'w') as f: 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: # for msg in self.c_msg:
# f.write(msg + '\n') # f.write(msg + '\n')
def msg_storage(self, response, flag=0): def msg_storage(self, response, flag=0):
messages = self.c_msg if flag == 0 else self.c_msg_xs messages = self.c_msg if flag == 0 else self.c_msg_xs
if len(messages) < 1000: if len(messages) < 20000:
messages.insert(0, response) messages.insert(0, response)
else: else:
messages.insert(0, response) messages.insert(0, response)
while len(messages) > 1000: while len(messages) > 20000:
messages.pop() messages.pop()
def get_response(self, data): def get_response(self, data):
@ -187,10 +192,10 @@ class HmiRequest(object):
for i in range(3): for i in range(3):
for msg in messages: for msg in messages:
if msg_id is None: 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: if msg_id in msg:
return msg return msg
time.sleep(1) sleep(1)
else: else:
return None return None
@ -202,7 +207,7 @@ class HmiRequest(object):
return _frame_head + _pkg_head + _protocol + _reserved + cmd.encode() return _frame_head + _pkg_head + _protocol + _reserved + cmd.encode()
def package_xs(self, cmd): 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 unpackage(self, sock):
def to_read(conn): def to_read(conn):
@ -245,7 +250,7 @@ class HmiRequest(object):
callback(key.fileobj) callback(key.fileobj)
def gen_id(self, command): def gen_id(self, command):
_now = time.time() _now = time()
_id = f"{command}-{_now}" _id = f"{command}-{_now}"
return _id return _id
@ -254,7 +259,7 @@ class HmiRequest(object):
req = None req = None
try: try:
with open(f'{current_path}/../../assets/templates/{command}.json', encoding='utf-8', mode='r') as f_json: 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: except:
print(f"暂不支持 {command} 功能,或确认该功能存在...") print(f"暂不支持 {command} 功能,或确认该功能存在...")
return 'NOT SUPPORT' return 'NOT SUPPORT'
@ -267,15 +272,24 @@ class HmiRequest(object):
case 'overview.reload': case 'overview.reload':
req['data']['prj_path'] = kwargs['prj_path'] req['data']['prj_path'] = kwargs['prj_path']
req['data']['tasks'] = kwargs['tasks'] 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) req['id'] = self.gen_id(command)
print(f"req = {req}") print(f"req = {req}")
cmd = json.dumps(req, separators=(',', ':')) cmd = dumps(req, separators=(',', ':'))
try: try:
self.c.send(self.package(cmd)) self.c.send(self.package(cmd))
time.sleep(2) sleep(2)
except Exception as Err: 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'] return req['id']