增加了解析功能、增加了发送全部通道、为将QTextEdit 改为 PlainText做备份

This commit is contained in:
wangxibao 2025-01-24 15:22:55 +08:00
parent 87730b1732
commit 2a48d097be
16 changed files with 1062 additions and 1867 deletions

118
PyNetAssistant/--PyNet.ini Normal file
View File

@ -0,0 +1,118 @@
[UI_config]
port = 9000
hex_send = 0
hex_receive = 0
add_date = 0
cr_lf = 0
auto_sav_log = 1
modbus_csv = 0
[DisHex_config]
row00 = ||||
[Modbus_config]
funcode = F4
position = 5
[Quick_config]
log_time = 1
button00 = |
button01 = |
button02 = |
button03 = |
button04 = |
button05 = |
button06 = |
button07 = |
button08 = |
button09 = |
button10 = |
button11 = |
button12 = |
button13 = |
button14 = |
button15 = |
button16 = |
button17 = |
button18 = |
button19 = |
button20 = |
button21 = |
button22 = |
button23 = |
button24 = |
button25 = |
button26 = |
button27 = |
button28 = |
button29 = |
button30 = |
button31 = |
button32 = |
button33 = |
button34 = |
button35 = |
button36 = |
button37 = |
button38 = |
button39 = |
button40 = |
button41 = |
button42 = |
button43 = |
button44 = |
button45 = |
button46 = |
button47 = |
button48 = |
button49 = |
button50 = |
button51 = |
button52 = |
button53 = |
button54 = |
button55 = |
button56 = |
button57 = |
button58 = |
button59 = |
button60 = |
button61 = |
button62 = |
button63 = |
button64 = |
button65 = |
button66 = |
button67 = |
button68 = |
button69 = |
button70 = |
button71 = |
button72 = |
button73 = |
button74 = |
button75 = |
button76 = |
button77 = |
button78 = |
button79 = |
button80 = |
button81 = |
button82 = |
button83 = |
button84 = |
button85 = |
button86 = |
button87 = |
button88 = |
button89 = |
button90 = |
button91 = |
button92 = |
button93 = |
button94 = |
button95 = |
button96 = |
button97 = |
button98 = |

8
PyNetAssistant/.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
PyNetAssistant/.idea/PyNetAssistant.iml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,12 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPep8NamingInspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
<option name="ignoredErrors">
<list>
<option value="N806" />
</list>
</option>
</inspection_tool>
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
PyNetAssistant/.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>

8
PyNetAssistant/.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/PyNetAssistant.iml" filepath="$PROJECT_DIR$/.idea/PyNetAssistant.iml" />
</modules>
</component>
</project>

6
PyNetAssistant/.idea/vcs.xml generated Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

View File

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
"""
Created on Tue May 28 15:40:48 2024
@author: WANGXIBAO
"""
# -*- coding: utf-8 -*-
import csv
import os
import re
import time
class GetDataTF(): # 读取费加罗或者自定义数据
def __init__(self, parent=None):
super().__init__()
self.indOfReturn = 0
self.TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
self.headStr = ""
self.rowTitle = []
self.csv_buffer = []
def SetConfig(self, config_in):
self.regex = re.compile(config_in[0]) # 正则表达
self.headStr = config_in[1]
self.rowTitleStr = config_in[2]
# print(self.rowTitleStr)
self.rowTitle = self.rowTitleStr.split(',')
def Transdata(self, data):
if data[:2] == self.headStr:
self.data2csv = self.regex.findall(data)
returnData = float(self.data2csv[self.indOfReturn])
print("returnData", returnData)
return returnData
else:
return "noNum"
def SaveCsv(self, filenameCsv, num):
# 打开一个文件用于写入,如果文件不存在则创建
# 增加num 写入文件间隔
if os.path.isfile(filenameCsv) == 0:
# 文件为空,需要写入表头
with open(filenameCsv, mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(self.rowTitle)
else:
timeCrvt = time.strftime(self.TIME_FORMAT, time.localtime())
self.data2csv.insert(0, timeCrvt)
print(self.data2csv)
self.csv_buffer.append(self.data2csv)
if len(self.csv_buffer) >= num:
with open(filenameCsv, mode='a', newline='') as file:
# 创建一个写入器对象
writer = csv.writer(file)
# 写入数据行
writer.writerows(self.csv_buffer)
self.csv_buffer.clear()
def IndOfReturn(self, ind):
self.indOfReturn = ind
class HexData2Num():
def __init__(self):
super().__init__()

Binary file not shown.

View File

@ -1,45 +1,159 @@
[UI_config]
port = 9000
hex_send = 0
hex_receive = 0
add_date = 0
cr_lf = 2
auto_sav_log = 2
modbus_csv = 0
[Modbus_config]
funcode = F4
position = 5
[DisHex_config]
row00 = 浓度|0|4|1|2
row01 = 测试|1|3|1|2
row02 = ||||0
row03 = ||||0
row04 = ||||0
row05 = ||||0
row06 = ||||0
row07 = ||||0
row08 = ||||0
row09 = ||||0
row10 = ||||0
row11 = ||||0
row12 = ||||0
row13 = ||||0
row14 = ||||0
row15 = ||||0
row16 = ||||0
row17 = ||||0
row18 = ||||0
row19 = ||||0
row20 = ||||0
row21 = ||||0
row22 = ||||0
row23 = ||||0
row24 = ||||0
row25 = ||||0
row26 = ||||0
row27 = ||||0
row28 = ||||0
row29 = ||||0
row30 = ||||0
row31 = ||||0
row32 = ||||0
row33 = ||||0
row34 = ||||0
row35 = ||||0
row36 = ||||0
row37 = ||||0
row38 = ||||0
row39 = ||||0
row40 = ||||0
row41 = ||||0
row42 = ||||0
row43 = ||||0
row44 = ||||0
row45 = ||||0
row46 = ||||0
row47 = ||||0
row48 = ||||0
row49 = ||||0
row50 = ||||0
row51 = ||||0
row52 = ||||0
row53 = ||||0
row54 = ||||0
row55 = ||||0
row56 = ||||0
row57 = ||||0
row58 = ||||0
row59 = ||||0
row60 = ||||0
row61 = ||||0
row62 = ||||0
row63 = ||||0
row64 = ||||0
row65 = ||||0
row66 = ||||0
row67 = ||||0
row68 = ||||0
row69 = ||||0
row70 = ||||0
row71 = ||||0
row72 = ||||0
row73 = ||||0
row74 = ||||0
row75 = ||||0
row76 = ||||0
row77 = ||||0
row78 = ||||0
row79 = ||||0
row80 = ||||0
row81 = ||||0
row82 = ||||0
row83 = ||||0
row84 = ||||0
row85 = ||||0
row86 = ||||0
row87 = ||||0
row88 = ||||0
row89 = ||||0
row90 = ||||0
row91 = ||||0
row92 = ||||0
row93 = ||||0
row94 = ||||0
row95 = ||||0
row96 = ||||0
row97 = ||||0
row98 = ||||0
[Quick_config]
log_time = 1
button00 = read 0|序列号
button01 = read 1|激光温度
button02 = read 2|K*1000
button03 = read 3|B*1000
button04 = read 4|电阻阻值
button05 = read 5|电阻抽头
button06 = read 6|输出温度
button07 = read 7|输出激光
button08 = read 8|输出状态
button09 = read 9|激光温补
button10 = read 10|噪声长度
button11 = read 11|扫描长度
log_time = 10
button00 = |
button01 = |
button02 = |
button03 = read|
button04 = |
button05 = |
button06 = |
button07 = |
button08 = |
button09 = |
button10 = |
button11 = |
button12 = |
button13 = read 13|气温校准
button14 = read 14|滑动开关
button15 = read 15|滑动标准差
button16 = read 16|浓度温补
button17 = read all|读取全部
button13 = |
button14 = |
button15 = |
button16 = |
button17 = |
button18 = |
button19 = |
button20 = write 0,2024100103|序列号
button21 = write 1,65000|激光温度
button22 = write 2,1000|K*1000
button23 = write 3,0|B*1000
button24 = write 4,0|电阻阻值
button25 = write 5,30|电阻抽头
button26 = write 6,0|输出温度
button27 = write 7,0|输出激光
button28 = write 8,1|输出状态
button29 = write 9,0|激光温补
button30 = write 10,100|噪声长度
button31 = write 11,600|扫描长度
button32 = 22|eee
button33 = write 13,30500|气温校准
button34 = write 14,1|滑动开关
button35 = write 15,10|滑动标准差
button36 = write 16,1|浓度温补
button20 = |
button21 = |
button22 = |
button23 = |
button24 = |
button25 = |
button26 = |
button27 = |
button28 = |
button29 = |
button30 = |
button31 = |
button32 = |
button33 = |
button34 = |
button35 = |
button36 = |
button37 = |
button38 = |
button39 = 01 04 01 2D 00 01 A0 3F|
button39 = |
button40 = |
button41 = |
button42 = |

View File

@ -4,19 +4,23 @@ Created on Sun Sep 29 09:01:22 2024
@author: WANGXIBAO
"""
import sys,os
import re,socket
import time,datetime
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMessageBox ,QFileDialog,QInputDialog
from PyQt5.QtCore import QTimer
from PyNetUi import Ui_UartAssistant
import datetime
import os
import re
import socket
import sys
import time
from configparser import ConfigParser
class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
from PyQt5 import QtWidgets
from PyQt5.QtCore import QTimer,Qt
from PyQt5.QtWidgets import QMessageBox, QFileDialog, QInputDialog, QTableWidgetItem
from PyNetUi import Ui_UartAssistant
class Pyqt5Net(QtWidgets.QWidget, Ui_UartAssistant):
# %%初始化程序
def __init__(self):
super(Pyqt5Net, self).__init__()
@ -25,6 +29,8 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
self.init() #信号和槽
self.IniPath = "PyNet.ini"
self.log_time = 10
self.funcode = "F4"
self.position = 5
self.CheckCfgIniData() #更改按钮的文字
self.log_count = 0
self.log_buffer = {} #定义成一个字典,键--文件名,值--对于收到的字符串列表
@ -51,18 +57,21 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
self.get_all_local_ips()
# 定时器接收数据
self.timer = QTimer()
self.timer.timeout.connect(self.data_receive)
#self.timer = QTimer()
self.timer: QTimer = QTimer()
#self.timer.timeout.connect(self.data_receive)
timeout_signal = self.timer.timeout
timeout_signal.connect(self.data_receive)
#加载快捷指令
self.widget_6.hide()
#加载快捷指令的按键值
#建立信号与槽
def init(self):
self.pushButton_openNet.clicked.connect(self.open_net)
self.pushButton_closeNet.clicked.connect(self.close_net)
self.pushButtonSend.clicked.connect(lambda:self.data_send(text_quick= None))
self.pushButtonSend.clicked.connect(lambda: self.data_send(text_quick=None))
# 清除发送按钮
self.pushButtonClearSend.clicked.connect(self.send_data_clear)
# 清除接收按钮
@ -98,27 +107,26 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
button = getattr(self, buttonName)
if button:
button.clicked.connect(lambda checked, idx=i: self.onButtonClick(idx))
self.double_click_timers = {} # 存储双击定时器
# 建立表格解析并显示hex
self.tableWidget.setRowCount(self.quick_num)
for i in range(self.quick_num): # 从0到20
item = QtWidgets.QTableWidgetItem()
item.setCheckState(Qt.Unchecked)
self.tableWidget.setItem(i, 0, item)
self.double_click_timers = {} # 存储双击定时器
#%% 重写关闭按钮
def closeEvent(self, event):
#关闭界面前保存快捷区域的命令和名称
for i in range(self.quick_num): # 假设有20个按钮
index_str = f"{i:02}" # 确保编号为两位数字形式
lineEditName = f"lineEditQuick_{index_str}"
buttonName = f"pushButtonQuick_{index_str}" # 格式化按钮名称,确保两位数
button_name = f"button{index_str}"
set_text = getattr(self,lineEditName).text()+ "|" + getattr(self,buttonName).text()
self.SetCfgIniData(button_name, set_text)
self.SavConfig()
self.close_net()
# 调用父类的关闭事件处理函数
super().closeEvent(event)
#加载本地网络地址
def get_all_local_ips(self):
ip_addresses = []
@ -128,7 +136,7 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
ip_addresses.append(address)
print(ip_addresses)
for ip in ip_addresses:
self.comboBox_localAddr.insertItem(0,ip)
self.comboBox_localAddr.insertItem(0, ip)
self.comboBox_localAddr.setCurrentIndex(0)
# 打开网络连接
@ -147,16 +155,13 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
print(f"Error reading configuration: {e}")
return None
#使能相关按钮
self.pushButton_closeNet.setEnabled(True)
self.pushButton_openNet.setEnabled(False)
# 打开串口接收定时器周期为1ms
self.timer.start(20)
def close_net(self):
if hasattr(self, 'udp_socket'):
self.timer.stop()
@ -165,6 +170,7 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
self.pushButton_closeNet.setEnabled(False)
self.pushButton_openNet.setEnabled(True)
print("关闭网络连接")
#接收数据
def data_receive(self):
try:
@ -172,19 +178,20 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
out_s = ''
# 打印接收到的数据
if self.checkBoxHexReceive.checkState():
line_utf8 = recv_data[0].hex()
line_utf8 = recv_data[0].hex().upper()
out_s = ' '.join(['{:02X}'.format(b) for b in bytes.fromhex(line_utf8)])
else:
line_utf8 = recv_data[0].decode('utf-8',errors='replace')
line_utf8 = recv_data[0].decode('utf-8', errors='replace')
print("[From %s:%d]:%s" % (recv_data[1][0], recv_data[1][1], line_utf8))
num = len(line_utf8)
# 接收窗口中增加来源地址显示
recv_addr = recv_data[1][0]+':'+str(recv_data[1][1])
recv_addr = recv_data[1][0] + ':' + str(recv_data[1][1])
if not self.is_in_comboBox_channel(recv_addr):
self.comboBox_channel.addItem(recv_addr)
if recv_addr==self.comboBox_channel.currentText() or self.comboBox_channel.currentText()=="ALL":
if recv_addr == self.comboBox_channel.currentText() or self.comboBox_channel.currentText() == "ALL":
#self.textEditReceive.insertPlainText('<' + recv_addr+ '> ' )
if self.checkBoxAddDate.isChecked():
@ -199,24 +206,25 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
# for byte in line_utf8_bytes:
# out_s += '{:02X} '.format(byte) # 使用大写字母 X
out_s = ' '.join(['{:02X}'.format(b) for b in bytes.fromhex(line_utf8)])
# self.textEditReceive.insertPlainText(out_s)
# self.textEditReceive.insertPlainText('\r\n')
self.add_line_to_textedit('<' + recv_addr+ '> ' + out_s)
self.add_line_to_textedit('<' + recv_addr + '> ' + out_s)
# 解析数据
self.Disp_hex_receive(line_utf8)
# ASCII显示数据
else:
#print("解码前",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
#self.textEditReceive.insertPlainText(line_utf8)
self.add_line_to_textedit('<' + recv_addr+ '> ' + line_utf8)
self.add_line_to_textedit('<' + recv_addr + '> ' + line_utf8)
#print("解码数据",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
# 接收换行
if self.checkBoxCRLF.isChecked():
self.textEditReceive.insertPlainText('\r\n')
# 获取到text光标
textCursor = self.textEditReceive.textCursor()
# 滚动到底部
@ -230,19 +238,27 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
# 自动保存日志
if self.checkBoxAutoSaveLog.isChecked():
line = line_utf8.split(',')
if len(line) ==2:
sav_name = line[0] +'_'+ datetime.datetime.now().strftime("%Y-%m-%d")+'.txt'
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] +" " +line[1]
else:
sav_name = datetime.datetime.now().strftime("%Y-%m-%d")+'.log'
if self.checkBoxHexReceive.checkState():
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] +" " +out_s +"\r\n"
#根据功能码保存数据
if line_utf8[2*self.position:2*self.position+2] == self.funcode:
sav_name = line_utf8[0:8] + '_' + datetime.datetime.now().strftime("%Y-%m-%d") + '.txt'
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_s[12:] + "\r\n"
else:
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] +" " +line_utf8
sav_name = datetime.datetime.now().strftime("%Y-%m-%d") + '.log'
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_s + "\r\n"
else:
line = line_utf8.split(',')
if len(line) == 2:
sav_name = line[0] + '_' + datetime.datetime.now().strftime("%Y-%m-%d") + '.txt'
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + line[1]
else:
sav_name = datetime.datetime.now().strftime("%Y-%m-%d") + '.log'
sav_str = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + line_utf8
# 将日志信息添加到缓冲区
if sav_name not in self.log_buffer:
self.log_buffer[sav_name] = []
@ -250,7 +266,7 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
# 当缓冲区中的记录达到10条时写入文件
if len(self.log_buffer[sav_name]) >= self.log_time:
with open(sav_name, mode='a', newline='',encoding='utf-8', errors='replace') as file:
with open(sav_name, mode='a', newline='', encoding='utf-8', errors='replace') as file:
file.writelines(self.log_buffer[sav_name])
self.log_buffer[sav_name].clear()
@ -258,8 +274,9 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
#print(f"Socket error: {e}")
pass
def data_send(self,text_quick = None):
if text_quick== None:
def data_send(self, text_quick=None):
if text_quick == None:
input_s = self.textEditSend.toPlainText()
else:
input_s = text_quick
@ -297,10 +314,11 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
for i in range(0, len(input_s)):
out_s = out_s + '{:02X}'.format(input_s[i]) + ' '
print(out_s)
self.textEditReceive.insertPlainText(out_s)
self.add_line_to_textedit(out_s)
# ASCII接收显示
else:
self.textEditReceive.insertPlainText(input_s.decode('utf-8'))
self.add_line_to_textedit(input_s.decode('utf-8'))
# 接收换行
if self.checkBoxCRLF.isChecked():
@ -313,6 +331,22 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
# 设置光标到Text中去
self.textEditReceive.setTextCursor(textCursor)
# 发送全部通道
if self.checkBoxSendAll.isChecked():
# 弹出确认对话框
if QMessageBox.question(None, "警告", "发送所有通道,是否继续执行?") == QMessageBox.Yes:
for i in range(1,self.comboBox_channel.count()):
# 定义服务器的IP地址和端口号
sever = self.comboBox_channel.itemText(i).split(':')
server_ip = sever[0]
server_port = int(sever[1])
server_address = (server_ip, server_port)
# 将消息发送到服务器
num = self.udp_socket.sendto(input_s, server_address)
# 统计发送字符数量
self.data_num_sended += num
else:
#发送单个通道
#定义服务器的IP地址和端口号
sever = self.comboBox_channel.currentText().split(':')
server_ip = sever[0]
@ -320,18 +354,20 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
server_address = (server_ip, server_port)
# 将消息发送到服务器
num = self.udp_socket.sendto(input_s, server_address)
# 统计发送字符数量
self.data_num_sended += num
self.lineEditSendNum.setText(str(self.data_num_sended))
except:
pass
# %%定时发送数据
def data_send_timer(self):
try:
if 1<= int(self.lineEditTime.text()) <= 30000: # 定时时间1ms~30s内
if 1 <= int(self.lineEditTime.text()) <= 30000: # 定时时间1ms~30s内
if self.checkBoxReapitSend.isChecked():
self.timer_send.start(int(self.lineEditTime.text()))
self.lineEditTime.setEnabled(False)
@ -344,26 +380,29 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
QMessageBox.critical(self, '定时发送数据异常', '请设置正确的数值类型!')
# %%保存日志
def savefiles(self):
dlg = QFileDialog()
filenames = dlg.getSaveFileName(None, "保存日志文件", None, "Txt files(*.txt)")
try:
with open(file = filenames[0], mode='w', encoding='utf-8') as file:
with open(file=filenames[0], mode='w', encoding='utf-8') as file:
file.write(self.textEditReceive.toPlainText())
except:
QMessageBox.critical(self, '日志异常', '保存日志文件失败!')
#%% 加载日志
def openfiles(self):
dlg = QFileDialog()
filenames = dlg.getOpenFileName(None, "加载日志文件", None, "Txt files(*.txt)")
try:
with open(file = filenames[0], mode='r', encoding='utf-8') as file:
with open(file=filenames[0], mode='r', encoding='utf-8') as file:
self.textEditSend.setPlainText(file.read())
except:
QMessageBox.critical(self, '日志异常', '加载日志文件失败!')
#%% 清除计数
def send_data_clear(self):
self.textEditSend.setText("")
@ -378,6 +417,24 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
self.data_num_received = 0
self.lineEditSendNum.setText(str(self.data_num_received))
def Disp_hex_receive(self,hexdata):
len = self.tableWidget.rowCount()
try:
for i in range(len):
if self.tableWidget.item(i, 0).checkState() == 2:
start = int(self.tableWidget.item(i, 1).text())
num = int(self.tableWidget.item(i, 2).text())
scale = int(self.tableWidget.item(i, 3).text())
value = int(hexdata[start*2:(start+num)*2],16)/scale
item = QTableWidgetItem(str(value))
self.tableWidget.setItem(i, 4, item)
except Exception as e:
print(e)
pass
#设置接受区域显示条数
def add_line_to_textedit(self, new_line):
# 获取当前文本并按行分割
@ -391,7 +448,7 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
self.textEditReceive.setPlainText('\n'.join(current_lines))
#检查是否在comboBox_channel中
def is_in_comboBox_channel(self,addr_rece):
def is_in_comboBox_channel(self, addr_rece):
for i in range(self.comboBox_channel.count()):
if addr_rece == self.comboBox_channel.itemText(i):
return True
@ -399,7 +456,7 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
def channel_clear(self):
self.comboBox_channel.lineEdit().clear()
for i in range(self.comboBox_channel.count()-1):
for i in range(self.comboBox_channel.count() - 1):
self.comboBox_channel.removeItem(1)
self.comboBox_channel.setCurrentIndex(0)
@ -420,19 +477,83 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
def CheckCfgIniData(self):
if not os.path.exists(self.IniPath):
config = ConfigParser()
#UI_config
config.add_section('UI_config')
config.set('UI_config', 'port', '9000')
config.set('UI_config', 'hex_send', '0')
config.set('UI_config', 'hex_receive', '0')
config.set('UI_config', 'add_date', '0')
config.set('UI_config', 'cr_lf', '0')
config.set('UI_config', 'auto_sav_log', '2')
config.set('UI_config', 'modbus_csv', '0')
# Modbus_config
config.add_section('Modbus_config')
config.set('Modbus_config', 'funcode', 'F4') #识别码
config.set('Modbus_config', 'position', '5') #识别码所在位置
#DisHex_config
config.add_section('DisHex_config')
for i in range(self.quick_num):
idx = f'{i:02}'
rowname = f'row{idx}'
config.set('DisHex_config', rowname, '|||||0')
#Quick_config
config.add_section('Quick_config')
config.set('Quick_config', 'log_time', '10')
for i in range(self.quick_num):
idx = f'{i:02}'
button_name = f'Button{idx}' # 格式化按钮名称,确保两位数
config.set('Quick_config', button_name, '')
with open(self.IniPath, 'w' ,encoding='utf-8') as f:
with open(self.IniPath, 'w', encoding='utf-8') as f:
config.write(f)
#读取数据
config = ConfigParser()
config.read(self.IniPath, encoding='utf-8')
try:
# UI_config
port = config.get('UI_config', 'port')
hex_send = int(config.get('UI_config', 'hex_send'))
hex_receive = int(config.get('UI_config', 'hex_receive'))
add_date = int(config.get('UI_config', 'add_date'))
cr_lf = int(config.get('UI_config', 'cr_lf'))
auto_sav_log = int(config.get('UI_config', 'auto_sav_log'))
modbus_csv = int(config.get('UI_config', 'modbus_csv'))
self.lineEdit_port.setText(port)
self.checkBoxHexSend.setChecked(hex_send)
self.checkBoxHexReceive.setChecked(hex_receive)
self.checkBoxAddDate.setChecked(add_date)
self.checkBoxCRLF.setChecked(cr_lf)
self.checkBoxAutoSaveLog.setChecked(auto_sav_log)
self.checkBoxAutoSaveCsv.setChecked(modbus_csv)
# Modbus_config
self.funcode = config.get('Modbus_config', 'funcode')
self.position = int(config.get('Modbus_config', 'position'))
# DisHex_config
for i in range(self.quick_num):
idx = f'{i:02}'
rowname = f'row{idx}'
rowstr = config.get('DisHex_config', rowname)
rowstr_split = rowstr.split('|')
for col in range(len(rowstr_split)-1):
item = QtWidgets.QTableWidgetItem()
item.setText(rowstr_split[col])
self.tableWidget.setItem(i, col, item)
select = int(rowstr_split[col+1])
item = self.tableWidget.item(i, 0) # 先反读回来再设置不然text丢失
item.setCheckState(select)
self.tableWidget.setItem(i, 0, item)
# Quick_config
# 创建一个空字典来存储按钮名称和对应的配置
self.log_time = int(config.get('Quick_config', 'log_time'))
# 循环遍历按钮编号从0到19
@ -445,21 +566,52 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
# 将按钮名称和配置信息存储在字典中
if len(config_value_split) == 2:
# 打印字典查看结果,并赋值
print(button_name,config_value_split[0],config_value_split[1])
print(button_name, config_value_split[0], config_value_split[1])
getattr(self, f'pushButtonQuick_{idx}').setText(config_value_split[1])
getattr(self, f'lineEditQuick_{idx}').setText(config_value_split[0])
except Exception as e:
print(f"Error reading configuration: {e}")
def SetCfgIniData(self,button_name,set_text):
def SavConfig(self):
#关闭界面前保存快捷区域的命令和名称
config = ConfigParser()
config.read(self.IniPath, encoding='utf-8')
config.set('Quick_config', button_name, set_text)
with open(self.IniPath, 'w' ,encoding='utf-8') as f:
config.write(f)
# 保存UI_config
config.set('UI_config', 'port', str(self.lineEdit_port.text()))
config.set('UI_config', 'hex_send', str(self.checkBoxHexSend.checkState()))
config.set('UI_config', 'hex_receive', str(self.checkBoxHexReceive.checkState()))
config.set('UI_config', 'add_date', str(self.checkBoxAddDate.checkState()))
config.set('UI_config','cr_lf',str(self.checkBoxCRLF.checkState()))
config.set('UI_config', 'auto_sav_log', str(self.checkBoxAutoSaveLog.checkState()))
config.set('UI_config', 'modbus_csv', str(self.checkBoxAutoSaveCsv.checkState()))
# 保存DisHex_config
for i in range(self.quick_num):
rowstr = []
idx = f'{i:02}'
rowname = f'row{idx}'
for col in range(self.tableWidget.columnCount()-1):
item = self.tableWidget.item(i, col)
if item is not None:
rowstr.append(item.text())
else:
rowstr.append('') # 如果单元格为空,则添加空字符串
selectStr = str(self.tableWidget.item(i,0).checkState())
row_string = '|'.join(rowstr) + f'|{selectStr}'
config.set('DisHex_config', rowname, row_string)
# 保存快捷按钮
for i in range(self.quick_num): # 假设有20个按钮
index_str = f"{i:02}" # 确保编号为两位数字形式
lineEditName = f"lineEditQuick_{index_str}"
buttonName = f"pushButtonQuick_{index_str}" # 格式化按钮名称,确保两位数
button_name = f"button{index_str}"
set_text = getattr(self, lineEditName).text() + "|" + getattr(self, buttonName).text()
config.set('Quick_config', button_name, set_text)
with open(self.IniPath, 'w', encoding='utf-8') as f:
config.write(f)
def onButtonClick(self, idx):
# 槽函数处理按钮点击事件
@ -495,9 +647,6 @@ class Pyqt5Net(QtWidgets.QWidget,Ui_UartAssistant):
button.setText(new_name)
#执行
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)

View File

@ -24,8 +24,8 @@ class Ui_UartAssistant(object):
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
UartAssistant.setWindowIcon(icon)
self.horizontalLayout_15 = QtWidgets.QHBoxLayout(UartAssistant)
self.horizontalLayout_15.setObjectName("horizontalLayout_15")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(UartAssistant)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.widget_7 = QtWidgets.QWidget(UartAssistant)
self.widget_7.setObjectName("widget_7")
self.horizontalLayout_14 = QtWidgets.QHBoxLayout(self.widget_7)
@ -37,7 +37,7 @@ class Ui_UartAssistant(object):
self.splitter.setObjectName("splitter")
self.widget_4 = QtWidgets.QWidget(self.splitter)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(3)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.widget_4.sizePolicy().hasHeightForWidth())
self.widget_4.setSizePolicy(sizePolicy)
@ -132,10 +132,20 @@ class Ui_UartAssistant(object):
self.pushButtonLogLoad = QtWidgets.QPushButton(self.layoutWidget_6)
self.pushButtonLogLoad.setObjectName("pushButtonLogLoad")
self.horizontalLayout_13.addWidget(self.pushButtonLogLoad)
self.checkBoxAutoSaveLog = QtWidgets.QCheckBox(self.groupBox_2)
self.checkBoxAutoSaveLog.setGeometry(QtCore.QRect(12, 103, 90, 16))
self.layoutWidget1 = QtWidgets.QWidget(self.groupBox_2)
self.layoutWidget1.setGeometry(QtCore.QRect(12, 100, 191, 31))
self.layoutWidget1.setObjectName("layoutWidget1")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.layoutWidget1)
self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.checkBoxAutoSaveLog = QtWidgets.QCheckBox(self.layoutWidget1)
self.checkBoxAutoSaveLog.setChecked(True)
self.checkBoxAutoSaveLog.setObjectName("checkBoxAutoSaveLog")
self.horizontalLayout_4.addWidget(self.checkBoxAutoSaveLog)
self.checkBoxAutoSaveCsv = QtWidgets.QCheckBox(self.layoutWidget1)
self.checkBoxAutoSaveCsv.setChecked(False)
self.checkBoxAutoSaveCsv.setObjectName("checkBoxAutoSaveCsv")
self.horizontalLayout_4.addWidget(self.checkBoxAutoSaveCsv)
self.verticalLayout_5.addWidget(self.groupBox_2)
self.groupBox_3 = QtWidgets.QGroupBox(self.widget)
self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0))
@ -187,27 +197,58 @@ class Ui_UartAssistant(object):
self.widget_5.setSizePolicy(sizePolicy)
self.widget_5.setMinimumSize(QtCore.QSize(400, 0))
self.widget_5.setObjectName("widget_5")
self.horizontalLayout_9 = QtWidgets.QHBoxLayout(self.widget_5)
self.horizontalLayout_9.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_9.setSpacing(0)
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.tabWidget = QtWidgets.QTabWidget(self.widget_5)
self.tabWidget.setMouseTracking(False)
self.tabWidget.setObjectName("tabWidget")
self.tab = QtWidgets.QWidget()
self.tab.setObjectName("tab")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab)
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget_5)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.groupBox_4 = QtWidgets.QGroupBox(self.tab)
self.groupBox_4.setObjectName("groupBox_4")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox_4)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.textEditReceive = QtWidgets.QTextEdit(self.groupBox_4)
self.tabWidget = QtWidgets.QTabWidget(self.widget_5)
self.tabWidget.setObjectName("tabWidget")
self.tab1 = QtWidgets.QWidget()
self.tab1.setFocusPolicy(QtCore.Qt.TabFocus)
self.tab1.setObjectName("tab1")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab1)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.textEditReceive = QtWidgets.QTextEdit(self.tab1)
self.textEditReceive.setSizeIncrement(QtCore.QSize(0, 0))
self.textEditReceive.setObjectName("textEditReceive")
self.horizontalLayout_2.addWidget(self.textEditReceive)
self.verticalLayout_3.addWidget(self.groupBox_4)
self.groupBox_7 = QtWidgets.QGroupBox(self.tab)
self.verticalLayout_2.addWidget(self.textEditReceive)
self.tabWidget.addTab(self.tab1, "")
self.tab2 = QtWidgets.QWidget()
self.tab2.setEnabled(True)
self.tab2.setFocusPolicy(QtCore.Qt.NoFocus)
self.tab2.setObjectName("tab2")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab2)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.tableWidget = QtWidgets.QTableWidget(self.tab2)
self.tableWidget.setGridStyle(QtCore.Qt.SolidLine)
self.tableWidget.setRowCount(10)
self.tableWidget.setColumnCount(5)
self.tableWidget.setObjectName("tableWidget")
item = QtWidgets.QTableWidgetItem()
item.setBackground(QtGui.QColor(172, 172, 172))
self.tableWidget.setHorizontalHeaderItem(0, item)
item = QtWidgets.QTableWidgetItem()
item.setBackground(QtGui.QColor(172, 172, 172))
self.tableWidget.setHorizontalHeaderItem(1, item)
item = QtWidgets.QTableWidgetItem()
item.setBackground(QtGui.QColor(172, 172, 172))
self.tableWidget.setHorizontalHeaderItem(2, item)
item = QtWidgets.QTableWidgetItem()
self.tableWidget.setHorizontalHeaderItem(3, item)
item = QtWidgets.QTableWidgetItem()
item.setBackground(QtGui.QColor(172, 172, 172))
self.tableWidget.setHorizontalHeaderItem(4, item)
self.tableWidget.horizontalHeader().setCascadingSectionResizes(False)
self.tableWidget.horizontalHeader().setDefaultSectionSize(50)
self.tableWidget.horizontalHeader().setMinimumSectionSize(20)
self.tableWidget.horizontalHeader().setSortIndicatorShown(True)
self.tableWidget.horizontalHeader().setStretchLastSection(True)
self.tableWidget.verticalHeader().setVisible(False)
self.tableWidget.verticalHeader().setCascadingSectionResizes(False)
self.tableWidget.verticalHeader().setDefaultSectionSize(25)
self.verticalLayout_4.addWidget(self.tableWidget)
self.tabWidget.addTab(self.tab2, "")
self.verticalLayout_3.addWidget(self.tabWidget)
self.groupBox_7 = QtWidgets.QGroupBox(self.widget_5)
self.groupBox_7.setObjectName("groupBox_7")
self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_7)
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
@ -222,13 +263,33 @@ class Ui_UartAssistant(object):
self.horizontalLayout_3.setStretch(0, 8)
self.horizontalLayout_3.setStretch(1, 1)
self.verticalLayout_3.addWidget(self.groupBox_7)
self.groupBox_5 = QtWidgets.QGroupBox(self.tab)
self.groupBox_5 = QtWidgets.QGroupBox(self.widget_5)
self.groupBox_5.setObjectName("groupBox_5")
self.gridLayout = QtWidgets.QGridLayout(self.groupBox_5)
self.gridLayout.setObjectName("gridLayout")
self.textEditSend = QtWidgets.QTextEdit(self.groupBox_5)
self.textEditSend.setObjectName("textEditSend")
self.gridLayout.addWidget(self.textEditSend, 0, 0, 3, 1)
self.pushButton_expend = QtWidgets.QPushButton(self.groupBox_5)
self.pushButton_expend.setObjectName("pushButton_expend")
self.gridLayout.addWidget(self.pushButton_expend, 0, 1, 1, 1)
self.pushButtonClearReceive = QtWidgets.QPushButton(self.groupBox_5)
self.pushButtonClearReceive.setObjectName("pushButtonClearReceive")
self.gridLayout.addWidget(self.pushButtonClearReceive, 1, 1, 1, 1)
self.pushButtonClearSend = QtWidgets.QPushButton(self.groupBox_5)
self.pushButtonClearSend.setObjectName("pushButtonClearSend")
self.gridLayout.addWidget(self.pushButtonClearSend, 2, 1, 2, 1)
self.widget_2 = QtWidgets.QWidget(self.groupBox_5)
self.widget_2.setObjectName("widget_2")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout(self.widget_2)
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.checkBoxSendAll = QtWidgets.QCheckBox(self.widget_2)
self.checkBoxSendAll.setObjectName("checkBoxSendAll")
self.horizontalLayout_5.addWidget(self.checkBoxSendAll)
self.checkBoxAddCRC = QtWidgets.QCheckBox(self.widget_2)
self.checkBoxAddCRC.setObjectName("checkBoxAddCRC")
self.horizontalLayout_5.addWidget(self.checkBoxAddCRC)
self.gridLayout.addWidget(self.widget_2, 3, 0, 2, 1)
self.pushButtonSend = QtWidgets.QPushButton(self.groupBox_5)
font = QtGui.QFont()
font.setFamily("3ds")
@ -239,22 +300,11 @@ class Ui_UartAssistant(object):
self.pushButtonSend.setCheckable(False)
self.pushButtonSend.setFlat(False)
self.pushButtonSend.setObjectName("pushButtonSend")
self.gridLayout.addWidget(self.pushButtonSend, 3, 1, 1, 1)
self.pushButtonClearSend = QtWidgets.QPushButton(self.groupBox_5)
self.pushButtonClearSend.setObjectName("pushButtonClearSend")
self.gridLayout.addWidget(self.pushButtonClearSend, 2, 1, 1, 1)
self.pushButton_expend = QtWidgets.QPushButton(self.groupBox_5)
self.pushButton_expend.setObjectName("pushButton_expend")
self.gridLayout.addWidget(self.pushButton_expend, 0, 1, 1, 1)
self.textEditSend = QtWidgets.QTextEdit(self.groupBox_5)
self.textEditSend.setObjectName("textEditSend")
self.gridLayout.addWidget(self.textEditSend, 0, 0, 4, 1)
self.gridLayout.addWidget(self.pushButtonSend, 4, 1, 1, 1)
self.verticalLayout_3.addWidget(self.groupBox_5)
self.verticalLayout_3.setStretch(0, 6)
self.verticalLayout_3.setStretch(0, 7)
self.verticalLayout_3.setStretch(1, 1)
self.verticalLayout_3.setStretch(2, 2)
self.tabWidget.addTab(self.tab, "")
self.horizontalLayout_9.addWidget(self.tabWidget)
self.widget_6 = QtWidgets.QWidget(self.splitter)
self.widget_6.setEnabled(True)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
@ -273,7 +323,7 @@ class Ui_UartAssistant(object):
self.scrollArea.setWidgetResizable(False)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -2388, 241, 3000))
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 241, 3000))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.widget_8 = QtWidgets.QWidget(self.scrollAreaWidgetContents)
self.widget_8.setGeometry(QtCore.QRect(12, 2, 221, 34))
@ -291,17 +341,17 @@ class Ui_UartAssistant(object):
self.widget_9 = QtWidgets.QWidget(self.scrollAreaWidgetContents)
self.widget_9.setGeometry(QtCore.QRect(10, 40, 231, 3000))
self.widget_9.setObjectName("widget_9")
self.layoutWidget1 = QtWidgets.QWidget(self.widget_9)
self.layoutWidget1.setGeometry(QtCore.QRect(12, 12, 218, 2941))
self.layoutWidget1.setObjectName("layoutWidget1")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.layoutWidget1)
self.layoutWidget2 = QtWidgets.QWidget(self.widget_9)
self.layoutWidget2.setGeometry(QtCore.QRect(12, 12, 218, 2941))
self.layoutWidget2.setObjectName("layoutWidget2")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.layoutWidget2)
self.verticalLayout_8.setSizeConstraint(QtWidgets.QLayout.SetMaximumSize)
self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_8.setObjectName("verticalLayout_8")
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.horizontalLayout_16.addWidget(self.scrollArea)
self.horizontalLayout_14.addWidget(self.splitter)
self.horizontalLayout_15.addWidget(self.widget_7)
self.horizontalLayout_2.addWidget(self.widget_7)
self.retranslateUi(UartAssistant)
self.comboBox_localAddr.setCurrentIndex(0)
@ -330,6 +380,7 @@ class Ui_UartAssistant(object):
self.pushButtonLogSave.setText(_translate("UartAssistant", "保存日志"))
self.pushButtonLogLoad.setText(_translate("UartAssistant", "加载日志"))
self.checkBoxAutoSaveLog.setText(_translate("UartAssistant", "自动保存日志"))
self.checkBoxAutoSaveCsv.setText(_translate("UartAssistant", "modbus2csv"))
self.groupBox_3.setTitle(_translate("UartAssistant", "定时发送"))
self.checkBoxReapitSend.setText(_translate("UartAssistant", "定时发送"))
self.label_7.setText(_translate("UartAssistant", "ms/次"))
@ -337,15 +388,27 @@ class Ui_UartAssistant(object):
self.label_9.setText(_translate("UartAssistant", "Rx"))
self.label_10.setText(_translate("UartAssistant", "Powerd by Byan"))
self.label_SendNum.setText(_translate("UartAssistant", "Tx"))
self.groupBox_4.setTitle(_translate("UartAssistant", "数据接收区"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab1), _translate("UartAssistant", "数据"))
item = self.tableWidget.horizontalHeaderItem(0)
item.setText(_translate("UartAssistant", "select"))
item = self.tableWidget.horizontalHeaderItem(1)
item.setText(_translate("UartAssistant", "start"))
item = self.tableWidget.horizontalHeaderItem(2)
item.setText(_translate("UartAssistant", "num"))
item = self.tableWidget.horizontalHeaderItem(3)
item.setText(_translate("UartAssistant", "scale"))
item = self.tableWidget.horizontalHeaderItem(4)
item.setText(_translate("UartAssistant", "value"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab2), _translate("UartAssistant", "解析"))
self.groupBox_7.setTitle(_translate("UartAssistant", "选择通道"))
self.comboBox_channel.setItemText(0, _translate("UartAssistant", "ALL"))
self.pushButtonClearChannel.setText(_translate("UartAssistant", "清空"))
self.groupBox_5.setTitle(_translate("UartAssistant", "数据发送区"))
self.pushButtonClearReceive.setText(_translate("UartAssistant", "清除接收"))
self.pushButtonSend.setText(_translate("UartAssistant", "发送"))
self.pushButtonClearSend.setText(_translate("UartAssistant", "清除发送"))
self.pushButton_expend.setText(_translate("UartAssistant", "快捷指令"))
self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("UartAssistant", "数据"))
self.pushButtonClearReceive.setText(_translate("UartAssistant", "清除接收"))
self.pushButtonClearSend.setText(_translate("UartAssistant", "清除发送"))
self.checkBoxSendAll.setText(_translate("UartAssistant", "发送全部通道"))
self.checkBoxAddCRC.setText(_translate("UartAssistant", "附加校验"))
self.pushButtonSend.setText(_translate("UartAssistant", "发送"))
self.label_8.setText(_translate("UartAssistant", "快捷指令"))
self.checkBox_return.setText(_translate("UartAssistant", "添加\"\\r\\n\""))

View File

@ -26,7 +26,7 @@
<iconset>
<normaloff>favicon.ico</normaloff>favicon.ico</iconset>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QWidget" name="widget_7" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_14" stretch="0">
@ -47,7 +47,7 @@
<widget class="QWidget" name="widget_4" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>3</horstretch>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
@ -278,15 +278,18 @@
</item>
</layout>
</widget>
<widget class="QCheckBox" name="checkBoxAutoSaveLog">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>12</x>
<y>103</y>
<width>90</width>
<height>16</height>
<y>100</y>
<width>191</width>
<height>31</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QCheckBox" name="checkBoxAutoSaveLog">
<property name="text">
<string>自动保存日志</string>
</property>
@ -294,6 +297,19 @@
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAutoSaveCsv">
<property name="text">
<string>modbus2csv</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
@ -463,40 +479,22 @@
<height>0</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="7,1,2">
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="mouseTracking">
<bool>false</bool>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="tab">
<widget class="QWidget" name="tab1">
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<attribute name="title">
<string>数据</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3" stretch="6,1,2">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>数据接收区</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QTextEdit" name="textEditReceive">
<widget class="QPlainTextEdit" name="plainTextEditReceive">
<property name="sizeIncrement">
<size>
<width>0</width>
@ -507,6 +505,120 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tab2">
<property name="enabled">
<bool>true</bool>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<attribute name="title">
<string>解析</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QTableWidget" name="tableWidget">
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="rowCount">
<number>10</number>
</property>
<property name="columnCount">
<number>5</number>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>20</number>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>50</number>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>25</number>
</attribute>
<row/>
<row/>
<row/>
<row/>
<row/>
<row/>
<row/>
<row/>
<row/>
<row/>
<column>
<property name="text">
<string>select</string>
</property>
<property name="background">
<color>
<red>172</red>
<green>172</green>
<blue>172</blue>
</color>
</property>
</column>
<column>
<property name="text">
<string>start</string>
</property>
<property name="background">
<color>
<red>172</red>
<green>172</green>
<blue>172</blue>
</color>
</property>
</column>
<column>
<property name="text">
<string>num</string>
</property>
<property name="background">
<color>
<red>172</red>
<green>172</green>
<blue>172</blue>
</color>
</property>
</column>
<column>
<property name="text">
<string>scale</string>
</property>
</column>
<column>
<property name="text">
<string>value</string>
</property>
<property name="background">
<color>
<red>172</red>
<green>172</green>
<blue>172</blue>
</color>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_7">
@ -542,6 +654,16 @@
<string>数据发送区</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" rowspan="3">
<widget class="QTextEdit" name="textEditSend"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButton_expend">
<property name="text">
<string>快捷指令</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButtonClearReceive">
<property name="text">
@ -549,7 +671,34 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="2" column="1" rowspan="2">
<widget class="QPushButton" name="pushButtonClearSend">
<property name="text">
<string>清除发送</string>
</property>
</widget>
</item>
<item row="3" column="0" rowspan="2">
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QCheckBox" name="checkBoxSendAll">
<property name="text">
<string>发送全部通道</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxAddCRC">
<property name="text">
<string>附加校验</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="1">
<widget class="QPushButton" name="pushButtonSend">
<property name="font">
<font>
@ -574,32 +723,11 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pushButtonClearSend">
<property name="text">
<string>清除发送</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButton_expend">
<property name="text">
<string>快捷指令</string>
</property>
</widget>
</item>
<item row="0" column="0" rowspan="4">
<widget class="QTextEdit" name="textEditSend"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="widget_6" native="true">
<property name="enabled">
<bool>true</bool>
@ -644,7 +772,7 @@
<property name="geometry">
<rect>
<x>0</x>
<y>-2388</y>
<y>0</y>
<width>241</width>
<height>3000</height>
</rect>

File diff suppressed because it is too large Load Diff

View File

@ -1,347 +0,0 @@
# -*- coding: utf-8 -*-
"""
Created on Tue May 28 15:40:48 2024
@author: WANGXIBAO
"""
# -*- coding: utf-8 -*-
import time,math,os
import re,csv,datetime
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QMessageBox
from PyQt5.QtGui import QPen
from configparser import ConfigParser
# 波形显示
# 使用线程不断更新波形数据
class UpdateDataThread(QThread):
_signal_update = pyqtSignal(float) # 信号
def __init__(self, parent=None):
super(UpdateDataThread, self).__init__(parent)
self.is_exit = False
self.x_range = 1024
self.getDateQx = GetDataQX()
self.flag = 0
def run(self):
print("run start")
while not self.is_exit: # 直接在循环中检查退出标志
# for i in range(self.x_range):
# print(i,self.sin.get_data(i))
# self._signal_update.emit(str(self.sin.get_data(i))) # 发射信号
# time.sleep(0.01) # 实际应用中推荐使用QTimer代替
# 这里应该有一个 flag 默认是 0 外部调用可以传紧来1没循环完自己置零while 只起到监控左右
if self.flag == 1:
#print("flag",self.flag)
#data = self.setReceiveData
#print("发数",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
print("data receive ",self.setReceiveData)
# print(f"{data:.3f}")
try:
self._signal_update.emit(self.setReceiveData)
self.flag = 0
except Exception:
QMessageBox.critical(self, '数据异常', '数据格式不对,不能绘图')
pass
def SetReceiveData(self,data_in):
self.setReceiveData = data_in
def SetFlag(self,flag):
self.flag = flag
def SetFilenameCsv(self,filename):
self.filenameCsv = filename
def SetPlotItem(self,ind): #设置显示项目
self.ind = ind
def stop(self):
self.is_exit = True # 设置退出标志
print("停止绘图")
def restart(self):
self.is_exit = False
class GetDataQX(): #读取请芯数据
def __init__(self, parent=None):
super().__init__()
self.indOfReturn =0
self.regexQx = re.compile(r'(A\+|B\+|\s)+') # 编译正则表达式
self.TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
def Transdata(self,data):
parts = re.split(self.regexQx,data)
# 过滤掉空字符串
parts = [part for part in parts if part]
#print(parts)
methane = float(parts[1])
airTemp = float(parts[3])
laserTemp = float( parts[5])/1
laerIntensity = float(parts[7])*10
timeCrvt=time.strftime(self.TIME_FORMAT, time.localtime())
self.data2csv =[(timeCrvt,methane,airTemp,laserTemp,laerIntensity)]
#print(self.data2csv)
if self.indOfReturn == 0:
returnData = methane
elif self.indOfReturn == 1:
returnData = airTemp
elif self.indOfReturn == 2:
returnData = laserTemp
elif self.indOfReturn == 3:
returnData = laerIntensity
print(returnData)
return returnData
def SaveCsv(self,filenameCsv):
# 打开一个文件用于写入,如果文件不存在则创建
if os.path.isfile(filenameCsv) == 0:
# 文件为空,需要写入表头
with open(filenameCsv, mode='w', newline='') as file:
writer = csv.writer(file)
writer.writerow(('time', 'Methane', 'Air Temp', 'Laser Temp', 'Laser Intensity'))
else:
with open(filenameCsv, mode='a', newline='') as file:
# 创建一个写入器对象
writer = csv.writer(file)
# 写入数据行
writer.writerows(self.data2csv)
def IndOfReturn(self,ind):
self.indOfReturn = ind
class GetDataTF(): #读取费加罗或者自定义数据
def __init__(self, parent=None):
super().__init__()
self.indOfReturn =0
#self.regex = re.compile(r'(A\+|B\+|\s)+') # 编译正则表达式
self.TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
self.regularIniPath = "regular.ini" # 配置文件默认路径
self.headStr = ""
self.rowTitle=[]
self.buttons_config = [[None for _ in range(3)] for _ in range(20)]
#存放快捷按键配置
self.CheckCfgIniData() # 初始化配置文件
def Transdata(self,data):
if data[:2] ==self.headStr:
# parts = re.split(self.regex,data)
# # 过滤掉空字符串
# parts = [part for part in parts if part]
#print(parts)
# methane = float(parts[1])
# airTemp = float(parts[3])
# laserTemp = float( parts[5])/1
# laerIntensity = float(parts[7])*10
# self.data2csv =[(timeCrvt,methane,airTemp,laserTemp,laerIntensity)]
self.data2csv = self.regex.findall(data)
#print(self.data2csv)
# if self.indOfReturn == 0:
# returnData = methane
# elif self.indOfReturn == 1:
# returnData = airTemp
# elif self.indOfReturn == 2:
# returnData = laserTemp
# elif self.indOfReturn == 3:
# returnData = laerIntensity
returnData = float(self.data2csv[self.indOfReturn])
print("returnData",returnData)
return returnData
else:
return "noNum"
def SaveCsv(self,filenameCsv):
# 打开一个文件用于写入,如果文件不存在则创建
if os.path.isfile(filenameCsv) == 0:
# 文件为空,需要写入表头
with open(filenameCsv, mode='w', newline='') as file:
writer = csv.writer(file)
#writer.writerow(('time', 'Methane', 'Air Temp', 'Laser Temp', 'Laser Intensity'))
writer.writerow(self.rowTitle)
else:
with open(filenameCsv, mode='a', newline='') as file:
# 创建一个写入器对象
writer = csv.writer(file)
# 写入数据行
timeCrvt=time.strftime(self.TIME_FORMAT, time.localtime())
self.data2csv.insert(0, timeCrvt)
print(self.data2csv)
writer.writerows([self.data2csv])
def IndOfReturn(self,ind):
self.indOfReturn = ind
def CheckCfgIniData(self):
if not os.path.exists(self.regularIniPath):
config = ConfigParser()
config.add_section('TF_config')
config.set('TF_config', 'regular', '\+?-?\d+(?:\.\d+)?')
#config.set('TF_config', 'regular', '(A\+|B\+|\s)+')
config.set('TF_config', 'headStr', 'A+')
config.set('TF_config', 'rowTitle', 'time,Methane,Air Temp,Laser Temp,Laser Intensity,amplification,NL,ND,Sinal,SNR,PEAK,Best Piont')
config.add_section('Quick_config')
config.set('Quick_config', 'Button00', 'write 0,2024100101|序列号')
config.set('Quick_config', 'Button01', 'write 1,65000|激光温度')
config.set('Quick_config', 'Button02', 'write 2,1000|K*1000')
config.set('Quick_config', 'Button03', 'write 3,0|B*1000')
config.set('Quick_config', 'Button04', 'write 4,0|可调电阻')
config.set('Quick_config', 'Button05', 'write 5,30|电阻抽头')
config.set('Quick_config', 'Button06', 'write 6,0|输出温度')
config.set('Quick_config', 'Button07', 'write 7,0|输出激光')
config.set('Quick_config', 'Button08', 'write 8,1|输出状态')
config.set('Quick_config', 'Button09', 'write 9,0|激光温补')
config.set('Quick_config', 'Button10', 'write 10,100|噪声长度')
config.set('Quick_config', 'Button11', 'write 11,600|扫描长度')
config.set('Quick_config', 'Button12', '')
config.set('Quick_config', 'Button13', 'write 13,30500|气温校准')
config.set('Quick_config', 'Button14', 'write 14,1|滑动开关')
config.set('Quick_config', 'Button15', 'write 15,10|滑动标准差')
config.set('Quick_config', 'Button16', 'write 16,1|浓度温补')
config.set('Quick_config', 'Button17', '')
config.set('Quick_config', 'Button18', '')
config.set('Quick_config', 'Button19', '')
with open(self.regularIniPath, 'w' ,encoding='utf-8') as f:
config.write(f)
config = ConfigParser()
config.read(self.regularIniPath, encoding='utf-8')
try:
self.headStr = config.get('TF_config', 'headStr')
self.regex = re.compile(config.get('TF_config', 'regular'))
self.rowTitleStr = config.get('TF_config', 'rowTitle')
self.rowTitle = self.rowTitleStr.split(',')
print(type(self.rowTitle))
print(f"Configuration read successfully: {self.headStr}, {self.regex}, {self.rowTitle}")
# 创建一个空字典来存储按钮名称和对应的配置
# 循环遍历按钮编号从0到19
for i in range(20):
button_name = f'Button{i:02}' # 格式化按钮名称,确保两位数
# 使用 get 方法安全地获取配置,如果不存在则返回空字符串
config_value = config.get('Quick_config', button_name, fallback='')
config_value_split = config_value.split('|')
# 将按钮名称和配置信息存储在字典中
self.buttons_config[i][0] = button_name
if len(config_value_split) == 2:
self.buttons_config[i][1] = config_value_split[0]
self.buttons_config[i][2] = config_value_split[1]
# 打印字典查看结果
for i in range(20):
print(f'{self.buttons_config[i][0]}: {self.buttons_config[i][1]}|{self.buttons_config[i][2]}')
except Exception as e:
print(f"Error reading configuration: {e}")
def SetCfgIniData(self,button_name,set_text):
config = ConfigParser()
config.read(self.regularIniPath, encoding='utf-8')
config.set('Quick_config', button_name, set_text)
with open(self.regularIniPath, 'w' ,encoding='utf-8') as f:
config.write(f)
class GetDataOther(): #读取费加罗或者自定义数据
def __init__(self, parent=None):
super().__init__()
self.indOfReturn =0
#self.regex = re.compile(r'(A\+|B\+|\s)+') # 编译正则表达式
self.TIME_FORMAT = "%Y-%m-%d %H:%M:%S"
self.OtherIniPath = "OtherData.ini" # 配置文件默认路径
self.headStr = ""
self.rowTitle=[]
self.CheckCfgIniData() # 初始化配置文件
def Transdata(self,data):
if data[:2] ==self.headStr:
self.data2csv = self.regex.findall(data)
returnData = float(self.data2csv[self.indOfReturn])
print("returnData",returnData)
return returnData
else:
return "noNum"
def SaveCsv(self,filenameCsv):
# 打开一个文件用于写入,如果文件不存在则创建
if os.path.isfile(filenameCsv) == 0:
# 文件为空,需要写入表头
with open(filenameCsv, mode='w', newline='') as file:
writer = csv.writer(file)
#writer.writerow(('time', 'Methane', 'Air Temp', 'Laser Temp', 'Laser Intensity'))
writer.writerow(self.rowTitle)
else:
with open(filenameCsv, mode='a', newline='') as file:
# 创建一个写入器对象
writer = csv.writer(file)
# 写入数据行
timeCrvt=time.strftime(self.TIME_FORMAT, time.localtime())
self.data2csv.insert(0, timeCrvt)
print(self.data2csv)
writer.writerows([self.data2csv])
def IndOfReturn(self,ind):
self.indOfReturn = ind
def CheckCfgIniData(self):
if not os.path.exists(self.OtherIniPath):
config = ConfigParser()
config.add_section('OtherData_config')
config.set('OtherData_config', 'regular', '\+?-?\d+(?:\.\d+)?')
# config.set('TF_config', 'regular', '(A\+|B\+|\s)+')
config.set('OtherData_config', 'headStr', 'A+')
config.set('OtherData_config', 'rowTitle', 'time,DATA1,DATA2')
with open(self.OtherIniPath, 'w') as f:
config.write(f)
config = ConfigParser()
config.read(self.OtherIniPath, encoding='utf-8')
try:
self.headStr = config.get('OtherData_config', 'headStr')
self.regex = re.compile(config.get('OtherData_config', 'regular'))
self.rowTitleStr = config.get('OtherData_config', 'rowTitle')
self.rowTitle = self.rowTitleStr.split(',')
print(type(self.rowTitle))
print(f"Configuration read successfully: {self.headStr}, {self.regex}, {self.rowTitle}")
except Exception as e:
print(f"Error reading configuration: {e}")