8 Commits

Author SHA1 Message Date
4925d899b4 千分表自动采集程序 2024-08-10 17:23:20 +08:00
3814d163c5 v0.2.0.6(2024/08/09)
1. [t_change_ui: all files]
   - 修改了 logger 的实现
   - 尤其是 clibs.py,使用日志字典,重写了日志记录的功能
2024-08-09 10:47:22 +08:00
340d48876b 10. [APIs: all]: 添加了 logger.setLevel(INFO),只有添加这个,单个模块内才生效 2024-08-01 19:15:08 +08:00
60726d9d07 7. [APIs: btn_functions.py]: 重写了告警输出函数,从日志中拿数据
8. [APIs: aio.py]: 将日志框输出的内容,也保存至日志文件
9. [APIs: do_brake.py]
   - 修改获取初始速度的逻辑,只获取configs文件中配置的时间内的速度
   - 新增 configs 参数 single_brake,可针对特定条件做测试
2024-08-01 17:11:12 +08:00
e713485d00 fix merge 2024-07-31 16:14:41 +08:00
25fc43be81 优化 ssh 输入密码的部分
create_plot 函数中增加 close('all'),解决循环画图不销毁占用内存的问题
2024-07-31 11:21:24 +08:00
924fad09e0 fix version again... 2024-07-31 08:28:39 +08:00
a7984a613d v0.2.0.4(2024/07/30)
1. [APIs: do_brake.py]: 修复制动数据处理过程中,只取曲线的最后 240 个数据
2. [APIs: aio.py]: 判定版本处,删除 self.destroy(),因为该语句会导致异常发生
2024-07-30 12:30:37 +08:00
19 changed files with 319 additions and 78 deletions

2
.gitignore vendored
View File

@ -12,3 +12,5 @@ aio/code/durable_action/__pycache__/
aio/assets/templates/durable/ aio/assets/templates/durable/
aio/assets/templates/.__c_msg.lock aio/assets/templates/.__c_msg.lock
aio/code/commons/__pycache__/ aio/code/commons/__pycache__/
aio/assets/templates/debug.log
dial_gauge/results.xlsx

View File

@ -558,6 +558,12 @@ v0.2.0.3(2024/07/27)
2. [APIs: do_current.py]: 精简程序,解决 OOM 问题 2. [APIs: do_current.py]: 精简程序,解决 OOM 问题
3. [APIs: factory_test.py]: 精简程序,解决 OOM 问题 3. [APIs: factory_test.py]: 精简程序,解决 OOM 问题
4. [APIsL openapi.py] 4. [APIsL openapi.py]
- 心跳修改为 1 s因为 OOM 问题的解决依赖于长久的打开曲线开关,此时对于 hr.c_msg 的定时清理是个挑战,将心跳缩短,有利于清理日志后,避免丢失心跳
- 新增 diagnosis.save 命令,但是执行时,有问题,待解决
v0.2.0.4(2024/07/30)
1. [APIs: do_brake.py]: 修复制动数据处理过程中,只取曲线的最后 240 个数据
2. [APIs: aio.py]: 判定版本处,删除 self.destroy(),因为该语句会导致异常发生
- 心跳修改为 1s因为 OOM 问题的解决依赖于长久的打开曲线开关,此时对于 hr.c_msg 的定时清理是个挑战,将心跳缩短,有利于清理日志后,避免丢失心跳 - 心跳修改为 1s因为 OOM 问题的解决依赖于长久的打开曲线开关,此时对于 hr.c_msg 的定时清理是个挑战,将心跳缩短,有利于清理日志后,避免丢失心跳
- 新增 diagnosis.save 命令,但是执行时,有问题,待解决 - 新增 diagnosis.save 命令,但是执行时,有问题,待解决
@ -567,7 +573,7 @@ v0.2.0.5(2024/07/31)
- 调整代码组织结构,新增模块,将公共函数以及类合并入此 - 调整代码组织结构,新增模块,将公共函数以及类合并入此
- 将一些常量放入该模块 - 将一些常量放入该模块
- 引入logging/concurrent_log_handler模块并作初始化操作供其他模块使用按50M切割最多保留10份 - 引入logging/concurrent_log_handler模块并作初始化操作供其他模块使用按50M切割最多保留10份
- prj_to_xcore函数设置工程名部分重写修复了多个prj工程可能不能执行的问题 - prj_to_xcore函数设置工程名部分重写修复了多个prj工程可能不能执行的问题,并优化输入密码的部分
2. [t_change_ui: openapi.py] 2. [t_change_ui: openapi.py]
- 完全重写了 get_from_id 函数,使更精准 - 完全重写了 get_from_id 函数,使更精准
- 在 msg_storage 函数中,增加 logger保留所有响应消息 - 在 msg_storage 函数中,增加 logger保留所有响应消息
@ -576,10 +582,22 @@ v0.2.0.5(2024/07/31)
3. [t_change_ui: aio.py] 3. [t_change_ui: aio.py]
- 增加了日志初始化部分 - 增加了日志初始化部分
- detect_network 函数中修改重新实例化HR间隔为 4s对应心跳 - detect_network 函数中修改重新实例化HR间隔为 4s对应心跳
- create_plot 函数中增加 close('all'),解决循环画图不销毁占用内存的问题
4. [t_change_ui: do_brake.py] 4. [t_change_ui: do_brake.py]
- 使用一直打开曲线的方法规避解决了 OOM 的问题,同时修改数据处理方式,只取最后 12s - 使用一直打开曲线的方法规避解决了 OOM 的问题,同时修改数据处理方式,只取最后 12s
- 优化 ssh 输入密码的部分
5. [t_change_ui: do_current.py] 5. [t_change_ui: do_current.py]
- 保持电流,只取最后 15s - 保持电流,只取最后 15s
- 优化 ssh 输入密码的部分
6. [t_change_ui: all the part]: 引入 commons 包,并定制了 logging 输出,后续持续优化 6. [t_change_ui: all the part]: 引入 commons 包,并定制了 logging 输出,后续持续优化
7. [APIs: btn_functions.py]: 重写了告警输出函数,从日志中拿数据
8. [APIs: aio.py]: 将日志框输出的内容,也保存至日志文件
9. [APIs: do_brake.py]
- 修改获取初始速度的逻辑只获取configs文件中配置的时间内的速度
- 新增 configs 参数 single_brake可针对特定条件做测试
10. [APIs: all]: 添加了 logger.setLevel(INFO),只有添加这个,单个模块内才生效
v0.2.0.6(2024/08/09)
1. [t_change_ui: all files]
- 修改了 logger 的实现
- 尤其是 clibs.py使用日志字典重写了日志记录的功能

Binary file not shown.

View File

@ -11,18 +11,17 @@ from data_process import brake, current, iso, wavelogger
from automatic_test import do_current, do_brake, btn_functions from automatic_test import do_current, do_brake, btn_functions
from durable_action import factory_test from durable_action import factory_test
from commons import openapi, clibs from commons import openapi, clibs
from matplotlib.pyplot import rcParams, figure, subplots_adjust from matplotlib.pyplot import rcParams, figure, subplots_adjust, close
from matplotlib import use from matplotlib import use
from pandas import DataFrame, read_excel from pandas import DataFrame, read_excel
import logging
with open(clibs.log_data, 'w') as _: with open(clibs.log_data_hmi, 'w') as _hmi, open(clibs.log_data_debug, 'w', encoding='utf-8') as _debug:
for i in range(1, 11): for i in range(1, 11):
try: try:
remove(f'{clibs.log_data}.{i}') remove(f'{clibs.log_data_hmi}.{i}')
except FileNotFoundError: except FileNotFoundError:
pass pass
logger = logging.getLogger(__file__) logger = clibs.log_prod
logger.info("日志文件初始化完成...") logger.info("日志文件初始化完成...")
use('Agg') use('Agg')
@ -94,7 +93,7 @@ class App(customtkinter.CTk):
btns_func['log']['btn'].configure(command=lambda: self.thread_it(self.func_log_callback)) btns_func['log']['btn'].configure(command=lambda: self.thread_it(self.func_log_callback))
btns_func['end']['btn'].configure(command=lambda: self.thread_it(self.func_end_callback)) btns_func['end']['btn'].configure(command=lambda: self.thread_it(self.func_end_callback))
# create version info # create version info
self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.3\nDate: 07/27/2024", font=self.my_font, text_color="#4F4F4F") self.label_version = customtkinter.CTkLabel(self.frame_func, justify='left', text="Vers: 0.2.0.5\nDate: 08/02/2024", font=self.my_font, text_color="#4F4F4F")
self.frame_func.rowconfigure(6, weight=1) self.frame_func.rowconfigure(6, weight=1)
self.label_version.grid(row=6, column=0, padx=20, pady=20, sticky='s') self.label_version.grid(row=6, column=0, padx=20, pady=20, sticky='s')
# ===================================================================== # =====================================================================
@ -230,6 +229,7 @@ class App(customtkinter.CTk):
self.flg = 1 self.flg = 1
self.df_copy = df.copy() self.df_copy = df.copy()
self.old_curve = widgits_da['curvesel']['optionmenu'].get() self.old_curve = widgits_da['curvesel']['optionmenu'].get()
close('all')
_figure = figure(frameon=True, facecolor='#E9E9E9') _figure = figure(frameon=True, facecolor='#E9E9E9')
subplots_adjust(left=0.04, right=0.98, bottom=0.1, top=0.95) subplots_adjust(left=0.04, right=0.98, bottom=0.1, top=0.95)
@ -448,6 +448,7 @@ class App(customtkinter.CTk):
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() tab_name_cur = self.tabview.get()
logger.info(text)
if tab_name == tab_name_cur: if tab_name == tab_name_cur:
if wait != 0: if wait != 0:

View File

@ -1,10 +1,8 @@
from json import loads
from sys import argv from sys import argv
from logging import getLogger
from commons import clibs from commons import clibs
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
logger = getLogger(__file__) logger = clibs.log_prod
def trigger_estop(md, w2t): def trigger_estop(md, w2t):
@ -38,12 +36,15 @@ def get_state(hr, w2t):
def warning_info(hr, w2t): def warning_info(hr, w2t):
for msg in hr.c_msg: for postfix in ['', '.2', '.3', '.4', '.5', '.6', '.7', '.8', '.9', '.10']:
if 'alarm' in msg.lower(): log_name = clibs.log_data_hmi + postfix
w2t(str(loads(msg)), tab_name=tab_name) try:
for msg in hr.c_msg_xs: with open(log_name, 'r', encoding='utf-8') as f_log:
if 'alarm' in msg.lower(): for line in f_log:
w2t(str(loads(msg)), tab_name=tab_name) if 'alarm' in line:
w2t(line.strip(), tab_name=tab_name)
except FileNotFoundError:
pass
def main(hr, md, func, w2t): def main(hr, md, func, w2t):

View File

@ -5,11 +5,10 @@ from paramiko import SSHClient, AutoAddPolicy
from json import loads from json import loads
from openpyxl import load_workbook from openpyxl import load_workbook
from pandas import DataFrame, concat from pandas import DataFrame, concat
from logging import getLogger
from commons import clibs from commons import clibs
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
logger = getLogger(__file__) logger = clibs.log_prod
def check_files(path, loadsel, data_dirs, data_files, w2t): def check_files(path, loadsel, data_dirs, data_files, w2t):
@ -61,7 +60,7 @@ def gen_result_file(path, curve_data, axis, _reach, _load, _speed, count):
_d2d_vel = {'hw_joint_vel_feedback': []} _d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []} _d2d_trq = {'device_servo_trq_feedback': []}
_d2d_stop = {'device_safety_estop': []} _d2d_stop = {'device_safety_estop': []}
for data in curve_data[-240:]: for data in curve_data[-240:]: # 保留最后12s的数据
dict_results = data['data'] dict_results = data['data']
for item in dict_results: for item in dict_results:
try: try:
@ -85,6 +84,7 @@ def gen_result_file(path, curve_data, axis, _reach, _load, _speed, count):
def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t): def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
_count = 0 _count = 0
_total = 63
display_pdo_params = [ display_pdo_params = [
{"name": "hw_joint_vel_feedback", "channel": 0}, {"name": "hw_joint_vel_feedback", "channel": 0},
{"name": "hw_joint_vel_feedback", "channel": 1}, {"name": "hw_joint_vel_feedback", "channel": 1},
@ -104,6 +104,9 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
ws = wb['Target'] ws = wb['Target']
write_diagnosis = float(ws.cell(row=3, column=10).value) write_diagnosis = float(ws.cell(row=3, column=10).value)
get_init_speed = float(ws.cell(row=4, column=10).value) get_init_speed = float(ws.cell(row=4, column=10).value)
single_brake = str(ws.cell(row=5, column=10).value)
logger.info(f"write_diagnosis = {write_diagnosis}, get_init_speed = {get_init_speed}, single_brake = {single_brake}")
if ws.cell(row=1, column=1).value == 'positive': if ws.cell(row=1, column=1).value == 'positive':
md.write_pon(1) md.write_pon(1)
elif ws.cell(row=1, column=1).value == 'negative': elif ws.cell(row=1, column=1).value == 'negative':
@ -118,7 +121,19 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
_load = condition.split('_')[1].removeprefix('load') _load = condition.split('_')[1].removeprefix('load')
_speed = condition.split('_')[2].removeprefix('speed') _speed = condition.split('_')[2].removeprefix('speed')
# for single condition test
_single_axis = 0
if single_brake != '0':
_total = 3
_single_axis = int(single_brake.split('-')[0])
if _reach != single_brake.split('-')[1] or _load != single_brake.split('-')[2] or _speed != single_brake.split('-')[3]:
continue
for axis in range(1, 4): for axis in range(1, 4):
# for single condition test
if _single_axis != 0 and _single_axis != axis:
continue
md.write_axis(axis) md.write_axis(axis)
speed_max = 0 speed_max = 0
if axis == 3 and _reach != '100': if axis == 3 and _reach != '100':
@ -130,7 +145,7 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
_count += 1 _count += 1
this_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time())) this_time = strftime("%Y-%m-%d %H:%M:%S", localtime(time()))
prj_path = 'target/_build/target.prj' prj_path = 'target/_build/target.prj'
w2t(f"[{this_time} | {_count}/63] 正在执行 {axis}{condition} 的第 {count} 次制动测试...", 0, 0, 'purple', tab_name) w2t(f"[{this_time} | {_count}/{_total}] 正在执行 {axis}{condition} 的第 {count} 次制动测试...", 0, 0, 'purple', tab_name)
# 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电 # 1. 关闭诊断曲线,触发软急停,并解除,目的是让可能正在运行着的机器停下来,切手动模式并下电
md.trigger_estop() md.trigger_estop()
@ -161,9 +176,8 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
cmd += f'sudo sed -i "/VelSet/i {_rl_tool}" projects/target/_build/brake/main.mod; ' cmd += f'sudo sed -i "/VelSet/i {_rl_tool}" projects/target/_build/brake/main.mod; '
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n') stdin.write('luoshi2019' + '\n')
stdin.flush() stdout.read().decode() # 需要read一下才能正常执行
print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo stderr.read().decode()
print(stderr.read().decode()) # 顺便也执行以下stderr
# 3. reload工程后pp2main并且自动模式和上电最后运行程序 # 3. reload工程后pp2main并且自动模式和上电最后运行程序
clibs.execution('overview.reload', hr, w2t, tab_name, prj_path=prj_path, tasks=['brake', 'stop0_related']) clibs.execution('overview.reload', hr, w2t, tab_name, prj_path=prj_path, tasks=['brake', 'stop0_related'])
@ -181,13 +195,17 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
w2t("20s内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name) w2t("20s内未收到机器人的运行信号需要确认RL程序编写正确并正常执行...", 0, 111, 'red', tab_name)
else: else:
sleep(1) sleep(1)
# 4. 打开诊断曲线,并执行采集,之后触发软急停,关闭曲线采集,找出最大速度传递给RL程序最后清除相关记录 # 4. 找出最大速度传递给RL程序最后清除相关记录
sleep(get_init_speed) # 获取实际最大速度可通过configs.xlsx配置 sleep(get_init_speed+5) # 冗余5s指定时间后获取实际【正|负】方向的最大速度可通过configs.xlsx配置
clibs.execution('rl_task.stop', hr, w2t, tab_name, tasks=['brake']) clibs.execution('rl_task.stop', hr, w2t, tab_name, tasks=['brake'])
# 找出最大速度 # 找出最大速度
_c_msg = hr.c_msg.copy() _c_msg = hr.c_msg.copy()
_number = 0
for _msg in _c_msg: for _msg in _c_msg:
if _number > get_init_speed*20: # 最开始回零点的时候,二轴速度可以达到最大值,实际摆动时,某一方向可能达不到
break
if 'diagnosis.result' in _msg: if 'diagnosis.result' in _msg:
_number += 1
dict_results = loads(_msg)['data'] dict_results = loads(_msg)['data']
for item in dict_results: for item in dict_results:
if item.get('channel', None) == axis-1 and item.get('name', None) == 'hw_joint_vel_feedback': if item.get('channel', None) == axis-1 and item.get('name', None) == 'hw_joint_vel_feedback':
@ -196,7 +214,7 @@ def run_rl(path, loadsel, hr, md, config_file, result_dirs, w2t):
speed_max = max(_, speed_max) speed_max = max(_, speed_max)
elif ws.cell(row=1, column=1).value == 'negative': elif ws.cell(row=1, column=1).value == 'negative':
speed_max = min(_, speed_max) speed_max = min(_, speed_max)
print(f"speed max = {speed_max}") logger.info(f"speed max = {speed_max}")
speed_max = abs(speed_max) speed_max = abs(speed_max)
speed_target = float(ws.cell(row=3, column=axis+1).value) * float(_speed) / 100 speed_target = float(ws.cell(row=3, column=axis+1).value) * float(_speed) / 100
if speed_max < speed_target*0.95 or speed_max > speed_target*1.05: if speed_max < speed_target*0.95 or speed_max > speed_target*1.05:

View File

@ -4,10 +4,9 @@ from sys import argv
from paramiko import SSHClient, AutoAddPolicy from paramiko import SSHClient, AutoAddPolicy
from json import loads from json import loads
from pandas import DataFrame, concat from pandas import DataFrame, concat
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
tab_name = clibs.tab_names['at'] tab_name = clibs.tab_names['at']
display_pdo_params = [ display_pdo_params = [
{"name": "hw_joint_vel_feedback", "channel": 0}, {"name": "hw_joint_vel_feedback", "channel": 0},
@ -64,7 +63,7 @@ def data_proc_regular(path, filename, channel, scenario_time):
lines = f_obj.readlines() lines = f_obj.readlines()
_d2d_vel = {'hw_joint_vel_feedback': []} _d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []} _d2d_trq = {'device_servo_trq_feedback': []}
for line in lines: for line in lines[-500:]: # 保留最后25s的数据
data = eval(line.strip())['data'] data = eval(line.strip())['data']
for item in data: for item in data:
try: try:
@ -168,7 +167,7 @@ def data_proc_regular(path, filename, channel, scenario_time):
lines = f_obj.readlines() lines = f_obj.readlines()
_d2d_vel = {'hw_joint_vel_feedback': []} _d2d_vel = {'hw_joint_vel_feedback': []}
_d2d_trq = {'device_servo_trq_feedback': []} _d2d_trq = {'device_servo_trq_feedback': []}
for line in lines[-300:]: for line in lines[-300:]: # 保留最后15s的数据
data = eval(line.strip())['data'] data = eval(line.strip())['data']
for item in data: for item in data:
try: try:
@ -280,9 +279,8 @@ def run_rl(path, hr, md, loadsel, w2t):
cmd += f'sudo sed -i "/DONOTDELETE/i {condition}" projects/target/_build/current/main.mod' cmd += f'sudo sed -i "/DONOTDELETE/i {condition}" projects/target/_build/current/main.mod'
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n') stdin.write('luoshi2019' + '\n')
stdin.flush() stdout.read().decode() # 需要read一下才能正常执行
print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo stderr.read().decode()
print(stderr.read().decode()) # 顺便也执行以下stderr
# 2. reload工程后pp2main并且自动模式和上电 # 2. reload工程后pp2main并且自动模式和上电
prj_path = 'target/_build/target.prj' prj_path = 'target/_build/target.prj'

View File

@ -4,10 +4,12 @@ from time import sleep
from os.path import exists from os.path import exists
from paramiko import SSHClient, AutoAddPolicy from paramiko import SSHClient, AutoAddPolicy
from socket import setdefaulttimeout from socket import setdefaulttimeout
from logging import DEBUG, INFO, WARNING, ERROR, CRITICAL, Formatter, StreamHandler, basicConfig from logging import getLogger
from concurrent_log_handler import ConcurrentRotatingFileHandler from logging.config import dictConfig
import concurrent_log_handler
ip_addr = '192.168.0.160' ip_addr = '192.168.0.160' # for product
# ip_addr = '192.168.84.129' # for test
RADIAN = 57.3 # 180 / 3.1415926 RADIAN = 57.3 # 180 / 3.1415926
MAX_FRAME_SIZE = 1024 MAX_FRAME_SIZE = 1024
TIMEOUT = 5 TIMEOUT = 5
@ -15,7 +17,8 @@ setdefaulttimeout(TIMEOUT)
tab_names = {'dp': 'Data Process', 'at': 'Automatic Test', 'da': 'Duration Action', 'op': 'openapi'} tab_names = {'dp': 'Data Process', 'at': 'Automatic Test', 'da': 'Duration Action', 'op': 'openapi'}
# PREFIX = '' # for pyinstaller packaging # PREFIX = '' # for pyinstaller packaging
PREFIX = '../assets/' # for source code debug PREFIX = '../assets/' # for source code debug
log_data = f'{PREFIX}templates/c_msg.log' log_data_hmi = f'{PREFIX}templates/c_msg.log'
log_data_debug = f'{PREFIX}templates/debug.log'
heartbeat = f'{PREFIX}templates/heartbeat' heartbeat = f'{PREFIX}templates/heartbeat'
durable_data_current_xlsx = f'{PREFIX}templates/durable/durable_data_current.xlsx' durable_data_current_xlsx = f'{PREFIX}templates/durable/durable_data_current.xlsx'
durable_data_current_max_xlsx = f'{PREFIX}templates/durable/durable_data_current_max.xlsx' durable_data_current_max_xlsx = f'{PREFIX}templates/durable/durable_data_current_max.xlsx'
@ -38,21 +41,80 @@ durable_data_current_max = {
'axis6': [0 for _ in range(18)], 'axis6': [0 for _ in range(18)],
} }
fmt = Formatter('%(asctime)s # %(levelname)s-%(filename)s-%(funcName)s # %(message)s') # version表示版本该键值为从1开始的整数。该key必选除此之外其它key都是可选。
# file_handler = logging.FileHandler(log_data) # formatters日志格式化器其value值为一个字典该字典的每个键值对都代表一个Formatter键值对中key代表Formatter ID(自定义ID)value为字典描述如何配置相应的Formatter实例。默认格式为 %(message)s
# file_handler = RotatingFileHandler(filename=log_data, backupCount=10, maxBytes=50*1024*1024, encoding='utf-8') # filters日志过滤器其value值为一个字典该字典的每个键值对都代表一个Filter键值对中key代表Filter ID(自定义ID)value为字典描述如何配置相应的Filter实例。
file_handler = ConcurrentRotatingFileHandler(filename=log_data, backupCount=10, maxBytes=50*1024*1024, encoding='utf-8') # handlers日志处理器其value值为一个字典该字典的每个键值对都代表一个Handler键值对中key代表Handler ID(自定义ID)value为字典描述如何配置相应的Handler实例包含以下配置key
file_handler.setFormatter(fmt) # class (必选):日志处理器类全称
file_handler.setLevel(INFO) # level (可选)指定该日志处理器需要处理哪些级别的日志低于该级别的日志将不被该handler处理。level可以为代表日志级别的整数或者表大写字符串字符串日志级别和数字日志级别对应关系如下
console_handler = StreamHandler() # CRITICAL 50
console_handler.setFormatter(fmt) # ERROR 40
console_handler.setLevel(ERROR) # WARNING 30
# INFO 20
# basicConfig(level=WARNING, # for product # DEBUG 10
basicConfig(level=WARNING, # NOTSET 0
datefmt='%Y-%m-%dT%H:%M:%S', f_complex = '%(asctime)s # %(name)s-%(levelname)s-%(module)s-%(funcName)s-%(lineno)d # %(message)s'
# handlers=[file_handler]) # for product f_simple = '%(levelname)s-%(module)s-%(funcName)s-%(lineno)d: %(message)s'
handlers=[file_handler, console_handler]) log_dicts = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'standard': {
'format': f_complex,
'style': '%',
'datefmt': '%Y-%m-%dT%H:%M:%S',
},
'test': {
'format': f_simple,
'style': '%',
'datefmt': '%Y-%m-%dT%H:%M:%S',
},
},
'filters': {},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'test',
},
'hmi.log': {
'level': 'DEBUG',
'class': 'concurrent_log_handler.ConcurrentRotatingFileHandler',
'filename': log_data_hmi,
'maxBytes': 1024*1024*50,
'backupCount': 10,
'encoding': 'utf-8',
'formatter': 'standard',
},
'debug.log': {
'level': 'INFO',
'class': 'logging.FileHandler',
'filename': log_data_debug,
'encoding': 'utf-8',
'formatter': 'standard',
},
},
'loggers': {
'normal': {
'handlers': ['hmi.log', 'debug.log'],
'level': 'DEBUG',
'propagate': False
},
'debug': {
'handlers': ['console'],
'level': 'DEBUG',
'propagate': False
},
'': {
'handlers': ['hmi.log', 'debug.log'],
'level': 'DEBUG',
'propagate': False
},
}
}
dictConfig(log_dicts)
log_prod = getLogger('normal')
log_debug = getLogger('debug')
class GetThreadResult(Thread): class GetThreadResult(Thread):
@ -107,18 +169,16 @@ def prj_to_xcore(prj_file):
cmd += 'sudo mv /tmp/target/ /home/luoshi/bin/controller/projects/' cmd += 'sudo mv /tmp/target/ /home/luoshi/bin/controller/projects/'
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n') stdin.write('luoshi2019' + '\n')
stdin.flush() stdout.read().decode() # 需要read一下才能正常执行
print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo stderr.read().decode()
print(stderr.read().decode()) # 顺便也执行以下stderr
cmd = 'cd /home/luoshi/bin/controller/; ' cmd = 'cd /home/luoshi/bin/controller/; '
cmd += 'sudo chmod -R 755 projects; rm /tmp/*.prj; sudo mv projects/target/_build/*.prj /tmp; cd /tmp; ' cmd += 'sudo chmod -R 755 projects; rm /tmp/*.prj; sudo mv projects/target/_build/*.prj /tmp; cd /tmp; '
cmd += 'prj=($(ls *.prj)); sudo mv ${prj[0]} /home/luoshi/bin/controller/projects/target/_build/target.prj; ' cmd += 'prj=($(ls *.prj)); sudo mv ${prj[0]} /home/luoshi/bin/controller/projects/target/_build/target.prj; '
stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True) stdin, stdout, stderr = ssh.exec_command(cmd, get_pty=True)
stdin.write('luoshi2019' + '\n') stdin.write('luoshi2019' + '\n')
stdin.flush() stdout.read().decode() # 需要read一下才能正常执行
print(stdout.read().decode()) # 必须得输出一下stdout才能正确执行sudo stderr.read().decode()
print(stderr.read().decode()) # 顺便也执行以下stderr
ssh.close() ssh.close()

View File

@ -6,10 +6,10 @@ from time import time, sleep
from pymodbus.client.tcp import ModbusTcpClient from pymodbus.client.tcp import ModbusTcpClient
from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder from pymodbus.payload import BinaryPayloadDecoder, BinaryPayloadBuilder
from pymodbus.constants import Endian from pymodbus.constants import Endian
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
class ModbusRequest(object): class ModbusRequest(object):
def __init__(self, w2t): def __init__(self, w2t):
@ -261,7 +261,7 @@ class HmiRequest(object):
def msg_storage(self, response, flag=0): def msg_storage(self, response, flag=0):
# response是解码后的字符串 # response是解码后的字符串
messages = self.c_msg if flag == 0 else self.c_msg_xs messages = self.c_msg if flag == 0 else self.c_msg_xs
logger.warning(f"{loads(response)}") logger.debug(f"{loads(response)}")
if 'move.monitor' in response: if 'move.monitor' in response:
pass pass
elif len(messages) < 10000: elif len(messages) < 10000:
@ -502,7 +502,7 @@ class HmiRequest(object):
def get_from_id(self, msg_id, flag=0): def get_from_id(self, msg_id, flag=0):
for i in range(3): for i in range(3):
with open(clibs.log_data, mode='r', encoding='utf-8') as f_log: with open(clibs.log_data_hmi, mode='r', encoding='utf-8') as f_log:
for line in f_log: for line in f_log:
if msg_id in line.strip(): if msg_id in line.strip():
return line return line
@ -510,7 +510,7 @@ class HmiRequest(object):
else: # 尝试在上一次分割的日志中查找,只做一次 else: # 尝试在上一次分割的日志中查找,只做一次
sleep(1) sleep(1)
try: try:
with open(clibs.log_data+'.1', mode='r', encoding='utf-8') as f_log: with open(clibs.log_data_hmi+'.1', mode='r', encoding='utf-8') as f_log:
for line in f_log: for line in f_log:
if msg_id in line.strip(): if msg_id in line.strip():
return line return line
@ -615,7 +615,7 @@ class HmiRequest(object):
self.c.send(self.package(cmd)) self.c.send(self.package(cmd))
sleep(0.5) sleep(0.5)
except Exception as Err: except Exception as Err:
self.w2t(f"{cmd}\n请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name) self.w2t(f"{cmd}: 请求发送失败...{Err}", 0, 0, 'red', tab_name=self.tab_name)
return req['id'] return req['id']

View File

@ -1,14 +1,12 @@
# coding: utf-8
from os.path import isfile from os.path import isfile
from sys import argv from sys import argv
from openpyxl import load_workbook from openpyxl import load_workbook
from time import time, sleep, strftime, localtime from time import time, sleep, strftime, localtime
from threading import Thread from threading import Thread
from pandas import read_csv from pandas import read_csv
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
def check_files(path, raw_data_dirs, result_files, w2t): def check_files(path, raw_data_dirs, result_files, w2t):

View File

@ -5,10 +5,9 @@ from re import match
from threading import Thread from threading import Thread
from time import sleep from time import sleep
from csv import reader, writer from csv import reader, writer
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
def w2t_local(msg, wait, w2t): def w2t_local(msg, wait, w2t):

View File

@ -1,12 +1,10 @@
# _*_ encodingutf-8 _*_
import pdfplumber import pdfplumber
from openpyxl import load_workbook from openpyxl import load_workbook
from os import remove from os import remove
from sys import argv from sys import argv
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
def p_iso(file, p_files, ws, tmpfile): def p_iso(file, p_files, ws, tmpfile):

View File

@ -2,10 +2,9 @@ from pandas import read_csv
from csv import reader from csv import reader
from sys import argv from sys import argv
from openpyxl import Workbook from openpyxl import Workbook
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
def find_point(bof, step, pos, data_file, flag, df, row, w2t): def find_point(bof, step, pos, data_file, flag, df, row, w2t):

View File

@ -6,10 +6,9 @@ from openpyxl import load_workbook
from math import sqrt from math import sqrt
from numpy import power from numpy import power
from csv import writer from csv import writer
from logging import getLogger
from commons import clibs from commons import clibs
logger = getLogger(__file__) logger = clibs.log_prod
tab_name = clibs.tab_names['da'] tab_name = clibs.tab_names['da']
count = 0 count = 0
display_pdo_params = [ display_pdo_params = [

2
dial_gauge/README.md Normal file
View File

@ -0,0 +1,2 @@
## 千分表数据自动采集

6
dial_gauge/conf.ini Normal file
View File

@ -0,0 +1,6 @@
[md_rtu]
port = COM10
[md_tcp]
addr = 192.168.0.160
port = 502

99
dial_gauge/gauge.py Normal file
View File

@ -0,0 +1,99 @@
from configparser import ConfigParser
from pymodbus.client import ModbusSerialClient, ModbusTcpClient
from time import sleep, strftime, localtime, time
from openpyxl import load_workbook, Workbook
from os import rename
# import pymodbus
# pymodbus.pymodbus_apply_logging_config("DEBUG")
def initializations():
try:
now = strftime("%Y%m%d%H%M%S", localtime(time()))
rename('results.xlsx', f'results_{now}.xlsx')
except FileNotFoundError:
pass
wb = Workbook()
ws = wb.active
ws.title = 'results'
ws['A1'].value = '时间'
ws['B1'].value = '次数'
ws['C1'].value = '结果'
wb.save('results.xlsx')
wb.close()
def do_connections():
configs = ConfigParser()
configs.read('conf.ini')
# ================ 配置Modbus TCP客户端 ================
tcp_host = configs.get('md_tcp', 'addr')
tcp_port = configs.getint('md_tcp', 'port')
client_tcp = ModbusTcpClient(tcp_host, tcp_port)
if client_tcp.connect():
print(f"Modbus TCP已连接到{tcp_host}:{tcp_port}...")
else:
raise Exception(f"Modbus TCP无法连接到{tcp_host}:{tcp_port}...")
# ================ 配置Modbus RTU客户端 ================
rtu_port = configs.get('md_rtu', 'port')
client_rtu = ModbusSerialClient(
method='rtu',
port=rtu_port, # 根据实际情况调整端口Windows上可能是 'COM3'
baudrate=38400, # 根据协议设定波特率为38400
timeout=1,
parity='N', # 无奇偶校验
stopbits=2, # 2个停止位
bytesize=8 # 8个数据位
)
if client_rtu.connect():
print(f"Modbus RTU已连接到系统{rtu_port}端口...")
else:
raise Exception(f"Modbus RTU无法连接到系统{rtu_port}端口...")
return client_tcp, client_rtu
def get_gauge_data(client_tcp, client_rtu):
count = 2
client_tcp.write_register(41000, 1) # 将 act 信号置为 True
# ================ 功能实现 ================
while True:
while True:
res_tcp = client_tcp.read_holding_registers(41001, 1) # 获取 time_to_go 的值
sleep(0.5)
if not res_tcp.registers[0]:
continue
else:
break
try:
res_rtu = client_rtu.read_holding_registers(0x0000, 2, slave=1)
plus_or_minus = 1 if res_rtu.registers[0] == 0 else -1
result = res_rtu.registers[1] * plus_or_minus / 10000
now = strftime("%Y-%m-%d %H:%M:%S", localtime(time()))
wb = load_workbook('results.xlsx')
ws = wb['results']
ws[f'A{count}'].value = now
ws[f'B{count}'].value = count-1
ws[f'C{count}'].value = float(result)
wb.save('results.xlsx')
wb.close()
count += 1
except:
client_tcp.write_register(41000, 0) # 将 act 信号置为 False
sleep(2) #
def main():
initializations()
client_tcp, client_rtu = do_connections()
get_gauge_data(client_tcp, client_rtu)
if __name__ == '__main__':
main()

43
dial_gauge/gauge.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<m>
<l>
<c name="addr" type="2" value="41000"/>
<c name="addr_1st" type="2" value="0"/>
<c name="addr_2nd" type="2" value="0"/>
<c name="bit_bias" type="2" value="0"/>
<c name="byte_bias" type="4" value="0"/>
<c name="description" type="10" value="pc to robot"/>
<c name="dev_name" type="10" value="autotest"/>
<c name="dev_type" type="10" value="MODBUS"/>
<c name="end_addr" type="2" value="41000"/>
<c name="function" type="10" value=""/>
<c name="len" type="2" value="1"/>
<c name="name" type="10" value="act"/>
<c name="retain" type="1" value="false"/>
<c name="rw" type="10" value="rd"/>
<c name="type" type="10" value="bool"/>
<c name="value"/>
<c name="value_single" type="10" value=""/>
<c name="bias" type="2" value="0"/>
</l>
<l>
<c name="addr" type="2" value="41001"/>
<c name="addr_1st" type="2" value="0"/>
<c name="addr_2nd" type="2" value="0"/>
<c name="bit_bias" type="2" value="0"/>
<c name="byte_bias" type="4" value="0"/>
<c name="description" type="10" value="robot to pc"/>
<c name="dev_name" type="10" value="autotest"/>
<c name="dev_type" type="10" value="MODBUS"/>
<c name="end_addr" type="2" value="41001"/>
<c name="function" type="10" value=""/>
<c name="len" type="2" value="1"/>
<c name="name" type="10" value="time_to_go"/>
<c name="retain" type="1" value="false"/>
<c name="rw" type="10" value="rdwr"/>
<c name="type" type="10" value="bool"/>
<c name="value"/>
<c name="value_single" type="10" value=""/>
<c name="bias" type="2" value="0"/>
</l>
</m>

Binary file not shown.