diff --git a/PyMaiHak/.idea/PyMaiHak.iml b/PyMaiHak/.idea/PyMaiHak.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/PyMaiHak/.idea/PyMaiHak.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/.gitignore b/PyNetAssistant_Sever/.idea/.gitignore
new file mode 100644
index 0000000..35410ca
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/.gitignore
@@ -0,0 +1,8 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/PyNetAssistant_Sever/.idea/PyNetAssistant.iml b/PyNetAssistant_Sever/.idea/PyNetAssistant.iml
new file mode 100644
index 0000000..909438d
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/PyNetAssistant.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/inspectionProfiles/Project_Default.xml b/PyNetAssistant_Sever/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..3dce9c6
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/inspectionProfiles/profiles_settings.xml b/PyNetAssistant_Sever/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/misc.xml b/PyNetAssistant_Sever/.idea/misc.xml
new file mode 100644
index 0000000..a6218fe
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/misc.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/modules.xml b/PyNetAssistant_Sever/.idea/modules.xml
new file mode 100644
index 0000000..17c958b
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/.idea/vcs.xml b/PyNetAssistant_Sever/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/PyNetAssistant_Sever/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/NetDataSplit.py b/PyNetAssistant_Sever/NetDataSplit.py
new file mode 100644
index 0000000..80a1a81
--- /dev/null
+++ b/PyNetAssistant_Sever/NetDataSplit.py
@@ -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__()
+
+
+
diff --git a/PyNetAssistant_Sever/PyNet.ini b/PyNetAssistant_Sever/PyNet.ini
new file mode 100644
index 0000000..e72be59
--- /dev/null
+++ b/PyNetAssistant_Sever/PyNet.ini
@@ -0,0 +1,220 @@
+[UI_config]
+port = 10086
+hex_send = 0
+hex_receive = 0
+add_date = 0
+cr_lf = 2
+auto_sav_log = 2
+send_sever = 2
+
+[Modbus_config]
+funcode = F4
+position = 5
+alarm_lim = 0
+
+[Server_config]
+nir_offset = 0
+
+[DisHex_config]
+row00 = |||||0
+row01 = |||||0
+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 = 10
+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 = |
+
diff --git a/PyNetAssistant_Sever/PyNetSever.build.zip b/PyNetAssistant_Sever/PyNetSever.build.zip
new file mode 100644
index 0000000..884eba0
Binary files /dev/null and b/PyNetAssistant_Sever/PyNetSever.build.zip differ
diff --git a/PyNetAssistant_Sever/PyNetSever.py b/PyNetAssistant_Sever/PyNetSever.py
new file mode 100644
index 0000000..71159cd
--- /dev/null
+++ b/PyNetAssistant_Sever/PyNetSever.py
@@ -0,0 +1,761 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sun Sep 29 09:01:22 2024
+
+@author: WANGXIBAO
+"""
+import csv
+import datetime
+import os
+import threading
+
+from flask import Flask, render_template
+from flask_socketio import SocketIO
+
+os.environ['QT_OPENGL'] = 'software' # 强制使用软件渲染
+import re
+import socket
+import sys
+import time
+
+from configparser import ConfigParser
+
+from PyQt5 import QtWidgets
+from PyQt5.QtCore import QTimer
+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__()
+ self.setupUi(self)
+ self.quick_num = 99
+ 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 = {} #定义成一个字典,键--文件名,值--对于收到的字符串列表
+
+ # 设置Logo和标题
+ #self.setWindowIcon(QIcon('favicon.ico'))
+ self.setWindowTitle("网口调试助手【服务版】")
+ # 设置禁止拉伸窗口大小
+ #self.setFixedSize(self.width(), self.height())
+
+ # 发送数据和接收数据数目置零
+ self.data_num_sended = 0
+ self.lineEditSendNum.setText(str(self.data_num_sended))
+ self.data_num_received = 0
+ self.lineEditReceiveNum.setText(str(self.data_num_received))
+
+ # 串口关闭按钮使能关闭
+ self.pushButton_closeNet.setEnabled(False)
+
+ # 发送框、文本框清除
+ self.textEditReceive.setPlainText("")
+ self.textEditReceive.setMaximumBlockCount(5000)
+
+ self.textEditSend.setText("")
+
+ self.get_all_local_ips()
+
+ # 定时器接收数据
+ #self.timer = QTimer()
+ self.timer: QTimer = QTimer()
+ #self.timer.timeout.connect(self.data_receive)
+ timeout_signal = self.timer
+ timeout_signal.timeout.connect(self.data_receive)
+
+ #加载快捷指令
+ self.widget_6.hide()
+ #加载快捷指令的按键值
+
+ # self.init_flask() #flask
+ # 初始化 Flask 在后台线程中
+ threading.Thread(target=self.init_flask, daemon=True).start()
+ self.methane = 0 # 用于缓存
+ self.co2 = 0 # 用于缓存
+ self.ethane = 0 # 用于缓存
+ self.temperature = 0 # 用于缓存
+ self.nir_offset = 0 # 用于平移数据
+ #建立信号与槽
+ 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.pushButtonClearSend.clicked.connect(self.send_data_clear)
+ # 清除接收按钮
+ self.pushButtonClearReceive.clicked.connect(self.receive_data_clear)
+
+ #
+
+ # 定时发送数据
+ self.timer_send = QTimer()
+ self.timer_send.timeout.connect(self.data_send)
+ self.checkBoxReapitSend.stateChanged.connect(self.data_send_timer)
+ # 快捷指令扩展区域
+ self.pushButton_expend.clicked.connect(self.adjust_sidebar)
+ # 清空网络通道列表
+ self.pushButtonClearChannel.clicked.connect(self.channel_clear)
+ # 动态创建控件并存储引用
+ for i in range(self.quick_num): # 从0到20
+ index_str = f"{i:02}" # 确保编号为两位数字形式
+ horizontalLayoutName = f"horizontalLayoutQuick_{index_str}"
+ horizontalLayout = QtWidgets.QHBoxLayout()
+ horizontalLayout.setObjectName(horizontalLayoutName)
+
+ # 创建 QLineEdit 并设置动态属性
+ lineEditName = f"lineEditQuick_{index_str}"
+ setattr(self, lineEditName, QtWidgets.QLineEdit(self.layoutWidget1))
+ getattr(self, lineEditName).setObjectName(lineEditName)
+ horizontalLayout.addWidget(getattr(self, lineEditName))
+ # 创建 QPushButton 并设置动态属性
+ buttonName = f"pushButtonQuick_{index_str}"
+ setattr(self, buttonName, QtWidgets.QPushButton(self.layoutWidget1))
+ getattr(self, buttonName).setObjectName(buttonName)
+ horizontalLayout.addWidget(getattr(self, buttonName))
+ self.verticalLayout_8.addLayout(horizontalLayout)
+ # 连接按钮点击事件到槽函数
+ button = getattr(self, buttonName)
+ if button:
+ button.clicked.connect(lambda checked, idx=i: self.onButtonClick(idx))
+ # 建立表格解析并显示hex
+ self.tableWidget.setRowCount(self.quick_num)
+ for i in range(self.quick_num): # 从0到20
+ item = QtWidgets.QTableWidgetItem()
+ item.setCheckState(0)
+ self.tableWidget.setItem(i, 0, item)
+
+ self.double_click_timers = {} # 存储双击定时器
+
+ #%% 重写关闭按钮
+ def closeEvent(self, event):
+
+ self.SavConfig()
+ self.close_net()
+
+
+ # 调用父类的关闭事件处理函数
+ super().closeEvent(event)
+
+ #加载本地网络地址
+ def get_all_local_ips(self):
+ ip_addresses = []
+ for interface in socket.getaddrinfo(socket.gethostname(), None):
+ address = interface[4][0]
+ if ':' not in address: # IPv6地址包含冒号
+ ip_addresses.append(address)
+ print(ip_addresses)
+ for ip in ip_addresses:
+ self.comboBox_localAddr.insertItem(0, ip)
+ self.comboBox_localAddr.setCurrentIndex(0)
+
+ # 打开网络连接
+ def open_net(self):
+ IP = self.comboBox_localAddr.currentText()
+ port = self.lineEdit_port.text()
+ udp_addr = (IP, int(port))
+ self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #创建接收空socket
+ print("绑定地址", udp_addr)
+ try:
+ self.udp_socket.bind(udp_addr)
+ print("开始监听。。。")
+ # 设置套接字为非阻塞模式
+ self.udp_socket.setblocking(False)
+ except Exception as e:
+ 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()
+ self.udp_socket.close()
+ #使能相关按钮
+ self.pushButton_closeNet.setEnabled(False)
+ self.pushButton_openNet.setEnabled(True)
+ print("关闭网络连接")
+
+ def set_textEditReceive_cursor(self):
+ # 获取到text光标
+ textCursor = self.textEditReceive.textCursor()
+ # 滚动到底部
+ textCursor.movePosition(textCursor.End)
+ # 设置光标到text中去
+ self.textEditReceive.setTextCursor(textCursor)
+
+ #接收数据
+ def data_receive(self):
+ try:
+ recv_data = self.udp_socket.recvfrom(1024) # 1024表示本次接收的最大字节数
+ out_s = ''
+ # 打印接收到的数据
+ if self.checkBoxHexReceive.checkState():
+ 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')
+
+ 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])
+ if not self.is_in_comboBox_channel(recv_addr):
+ self.comboBox_channel.addItem(recv_addr)
+ # 在接收窗口显示
+ # 获取到text光标
+ self.set_textEditReceive_cursor()
+ #选择要显示的通道
+ if recv_addr == self.comboBox_channel.currentText() or self.comboBox_channel.currentText() == "ALL":
+ #self.textEditReceive.insertPlainText('<' + recv_addr+ '> ' )
+
+ if self.checkBoxAddDate.isChecked():
+ nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
+ nowTime = nowTime[:-3]
+ self.textEditReceive.insertPlainText(nowTime + " ")
+ #self.add_line_to_textedit(nowTime + " ")
+ # HEX显示数据
+ if self.checkBoxHexReceive.checkState():
+ # line_utf8_bytes = line_utf8.hex() # 编码为 UTF-8 字节串
+
+ # for byte in line_utf8_bytes:
+ # out_s += '{:02X} '.format(byte) # 使用大写字母 X
+
+ # self.textEditReceive.insertPlainText(out_s)
+ self.textEditReceive.insertPlainText('<' + 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('<' + 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光标
+ self.set_textEditReceive_cursor()
+ # 统计接收字符的数量
+ self.data_num_received += num
+ self.lineEditReceiveNum.setText(str(self.data_num_received))
+
+ # 自动保存日志
+ if self.checkBoxAutoSaveLog.isChecked():
+ if self.checkBoxHexReceive.checkState():
+ #根据功能码保存数据
+ 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"
+ #当表示浓度的字符不为0时 将数据单独记录
+ if int(line_utf8[14:18], 16) > self.alarm_lim:
+ sav_name_alarm = 'alarm_' + line_utf8[0:8] + '_' + datetime.datetime.now().strftime(
+ "%Y-%m-%d") + '.txt'
+ sav_str_alarm = datetime.datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_s[
+ 12:] + "\r\n"
+ with open(sav_name_alarm, mode='a', newline='', encoding='utf-8', errors='replace') as file:
+ file.writelines(sav_str_alarm)
+
+ 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] + " " + out_s + "\r\n"
+ # Ascii 数据保存
+ 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]
+
+ if self.checkBoxSendSever.isChecked():
+ self.send_data_to_server(line)
+
+ 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] = []
+ self.log_buffer[sav_name].append(sav_str)
+
+ # 当缓冲区中的记录达到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:
+ file.writelines(self.log_buffer[sav_name])
+ self.log_buffer[sav_name].clear()
+
+ except socket.error as e:
+ #print(f"Socket error: {e}")
+ pass
+
+ def data_send(self, text_quick=None):
+ if text_quick == None:
+ input_s = self.textEditSend.toPlainText()
+ else:
+ input_s = text_quick
+
+ try:
+
+ if input_s != "":
+ # 时间显示
+ if self.checkBoxAddDate.isChecked():
+ self.textEditReceive.insertPlainText((time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + " ")
+
+ # HEX发送
+ if self.checkBoxHexSend.isChecked():
+ input_s = input_s.strip()
+ send_list = []
+ while input_s != '':
+ try:
+ num = int(input_s[0:2], 16)
+ except ValueError:
+ QMessageBox.critical(self, '串口异常', '请输入规范十六进制数据,以空格分开!')
+ return None
+
+ input_s = input_s[2:].strip()
+ send_list.append(num)
+
+ input_s = bytes(send_list)
+ # ASCII发送
+ else:
+ input_s = (input_s).encode('utf-8')
+ input_s = re.sub(b'(? 1000:
+ current_lines = current_lines[-1000:] # 只保留最新的100行
+ # 将更新后的行列表转换回字符串并设置为textEdit的内容
+ self.textEditReceive.setPlainText('\n'.join(current_lines))
+
+ #检查是否在comboBox_channel中
+ 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
+ return False
+
+ def channel_clear(self):
+ self.comboBox_channel.lineEdit().clear()
+ for i in range(self.comboBox_channel.count() - 1):
+ self.comboBox_channel.removeItem(1)
+ self.comboBox_channel.setCurrentIndex(0)
+
+ #开关快捷指令栏
+ def adjust_sidebar(self):
+ if self.widget_6.isHidden():
+ self.widget_6.show()
+ else:
+ self.widget_6.hide()
+
+ def onPushButtonQuickClicked(self, line_edit):
+ text = getattr(self, line_edit).text()
+ #print(f"Button clicked: {text}")
+ if self.checkBox_return.isChecked():
+ text = text + "\r\n"
+ self.data_send(text)
+
+ 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', 'send_sever', '0')
+
+ # Modbus_config
+ config.add_section('Modbus_config')
+ config.set('Modbus_config', 'funcode', 'F4') #识别码
+ config.set('Modbus_config', 'position', '5') #识别码所在位置
+ config.set('Modbus_config', 'alarm_lim', '0')
+ # Server_config
+ config.add_section('Server_config')
+ config.set('Server_config', 'nir_offset','0')
+ #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:
+ config.write(f)
+
+ # 读取数据
+ try:
+ config = ConfigParser()
+ config.read(self.IniPath, encoding='utf-8')
+ # 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'))
+ send_sever = int(config.get('UI_config', 'send_sever'))
+ 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.checkBoxSendSever.setChecked(send_sever)
+
+ # Modbus_config
+ self.funcode = config.get('Modbus_config', 'funcode')
+ self.position = int(config.get('Modbus_config', 'position'))
+ self.alarm_lim = int(config.get('Modbus_config', 'alarm_lim'))
+
+ # Server_config
+ self.nir_offset = int(config.get('Server_config', 'nir_offset'))
+
+ # 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
+ for i in range(self.quick_num):
+ idx = f'{i:02}'
+ button_name = f'Button{idx}' # 格式化按钮名称,确保两位数
+ # 使用 get 方法安全地获取配置,如果不存在则返回空字符串
+ config_value = config.get('Quick_config', button_name, fallback='')
+ config_value_split = config_value.split('|')
+ # 将按钮名称和配置信息存储在字典中
+ if len(config_value_split) == 2:
+ # 打印字典查看结果,并赋值
+ 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}")
+ QMessageBox.critical(self, "Error", f"Error reading configuration: {e}")
+
+ def SavConfig(self):
+ #关闭界面前保存快捷区域的命令和名称
+ config = ConfigParser()
+ config.read(self.IniPath, encoding='utf-8')
+ # 保存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', 'send_sever', str(self.checkBoxSendSever.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):
+ # 槽函数处理按钮点击事件
+
+ if idx not in self.double_click_timers:
+ self.double_click_timers[idx] = None
+
+ if self.double_click_timers[idx] is None:
+ self.double_click_timers[idx] = True
+ QTimer.singleShot(200, lambda: self.onButtonSigleClick(idx))
+ else:
+ self.onButtonDoubleClick(idx)
+
+ def onButtonSigleClick(self, idx):
+ index_str = f"{idx:02}"
+ if self.double_click_timers[idx]:
+ self.double_click_timers[idx] = None
+ lineEdit = getattr(self, f"lineEditQuick_{index_str}")
+ print(f"Text in lineEdit_{idx}: {lineEdit.text()}")
+ text = lineEdit.text()
+ if self.checkBox_return.isChecked():
+ text = text + "\r\n"
+ self.data_send(text)
+
+ def onButtonDoubleClick(self, idx):
+ # 槽函数处理按钮双击事件
+ self.double_click_timers[idx] = None
+ index_str = f"{idx:02}"
+ print(f"Double click detected on Button {index_str}.")
+ button = getattr(self, f"pushButtonQuick_{index_str}")
+ new_name, ok = QInputDialog.getText(self, 'Button Rename', 'Enter new button name:')
+ if ok and new_name:
+ button.setText(new_name)
+
+
+
+
+ def init_flask(self):
+ # 创建Flask应用
+ self.app = Flask(__name__) # 修改为实例变量
+ self.app.config['SECRET_KEY'] = 'secret!'
+ self.socketio = SocketIO(self.app)
+
+ # 主页路由
+ @self.app.route('/')
+ def index():
+ return render_template('index.html')
+
+ # 启动Flask-SocketIO服务器
+ self.socketio.run(self.app, host='0.0.0.0', port=8000, allow_unsafe_werkzeug=True)
+
+ def send_data_to_server(self, data: list[str]):
+
+
+ if data[0] == 'Z02':
+ numbers = re.findall(r'-?\d+\.?\d*', data[1])
+ if numbers:
+ # 假设我们只发送第一个数字,如果有多个数字可以根据需要处理
+ self.co2 = float(numbers[0])
+ self.socketio.emit('co2_data', {'value': self.co2})
+ print(f"发送二氧化碳数据: {self.co2}")
+ else:
+ print("未找到有效的数字")
+ if data[0] == 'Z03':
+ numbers = re.findall(r'-?\d+\.?\d*', data[1])
+ if len(numbers) > 1:
+ # 假设我们只发送第一个数字,如果有多个数字可以根据需要处理
+ self.methane = int(float(numbers[0]) * 10000)
+ self.socketio.emit('methane_data', {'value': self.methane})
+ print(f"发送甲烷数据: {self.methane}")
+ self.temperature = float(numbers[1])
+ self.socketio.emit('temperature_data', {'value': self.temperature})
+ print(f"发送温度数据: {self.temperature}")
+ else:
+ print("未找到有效的数字")
+ if data[0] == 'Z01':
+ numbers = re.findall(r'-?\d+\.?\d*', data[1])
+ if numbers:
+ # 假设我们只发送第一个数字,如果有多个数字可以根据需要处理 0.6457 0.8
+ methane_nir = float(numbers[0])
+ delta = int((methane_nir*0.55 + 2000 - self.methane) /4 + self.nir_offset)
+ if delta <= 600:
+ self.ethane = 0
+ else:
+ self.ethane = delta
+
+ self.socketio.emit('ethane_data', {'value': self.ethane})
+ print(f"发送乙烷数据: {self.ethane}")
+ self.sav_multi_csv() # 乙烷数据更新时保存一次数据
+ else:
+ print("未找到有效的数字")
+
+ def sav_multi_csv(self):
+ filename = f"{datetime.datetime.now().strftime('%Y-%m-%d')}.csv"
+ timestamp = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%S.%f')[:23]
+
+ with open(filename, mode='a', newline='', encoding='utf-8') as file:
+ writer = csv.writer(file)
+ # 写入表头
+ if file.tell() == 0:
+ writer.writerow(['time', 'Temperature', 'Methane', 'Ethane', 'CO2'])
+ # 写入数据
+ writer.writerow([timestamp, self.temperature, self.methane, self.ethane, self.co2])
+
+#执行
+if __name__ == '__main__':
+ app = QtWidgets.QApplication(sys.argv)
+ myshow = Pyqt5Net()
+ myshow.show()
+ sys.exit(app.exec_())
diff --git a/PyNetAssistant_Sever/PyNetUi.py b/PyNetAssistant_Sever/PyNetUi.py
new file mode 100644
index 0000000..40601a3
--- /dev/null
+++ b/PyNetAssistant_Sever/PyNetUi.py
@@ -0,0 +1,418 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'PyNetUi.ui'
+#
+# Created by: PyQt5 UI code generator 5.15.10
+#
+# WARNING: Any manual changes made to this file will be lost when pyuic5 is
+# run again. Do not edit this file unless you know what you are doing.
+
+
+from PyQt5 import QtCore, QtGui, QtWidgets
+
+
+class Ui_UartAssistant(object):
+ def setupUi(self, UartAssistant):
+ UartAssistant.setObjectName("UartAssistant")
+ UartAssistant.resize(956, 650)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
+ sizePolicy.setHorizontalStretch(2)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(UartAssistant.sizePolicy().hasHeightForWidth())
+ UartAssistant.setSizePolicy(sizePolicy)
+ UartAssistant.setAcceptDrops(True)
+ icon = QtGui.QIcon()
+ icon.addPixmap(QtGui.QPixmap("favicon.ico"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
+ UartAssistant.setWindowIcon(icon)
+ 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)
+ self.horizontalLayout_14.setObjectName("horizontalLayout_14")
+ self.splitter = QtWidgets.QSplitter(self.widget_7)
+ self.splitter.setMaximumSize(QtCore.QSize(16777215, 16777215))
+ self.splitter.setOrientation(QtCore.Qt.Horizontal)
+ self.splitter.setHandleWidth(5)
+ self.splitter.setObjectName("splitter")
+ self.widget_4 = QtWidgets.QWidget(self.splitter)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.widget_4.sizePolicy().hasHeightForWidth())
+ self.widget_4.setSizePolicy(sizePolicy)
+ self.widget_4.setMinimumSize(QtCore.QSize(230, 0))
+ self.widget_4.setObjectName("widget_4")
+ self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_4)
+ self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout.setSpacing(0)
+ self.horizontalLayout.setObjectName("horizontalLayout")
+ self.widget = QtWidgets.QWidget(self.widget_4)
+ self.widget.setObjectName("widget")
+ self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.widget)
+ self.verticalLayout_5.setObjectName("verticalLayout_5")
+ self.groupBox = QtWidgets.QGroupBox(self.widget)
+ self.groupBox.setMinimumSize(QtCore.QSize(0, 0))
+ self.groupBox.setBaseSize(QtCore.QSize(271, 291))
+ self.groupBox.setObjectName("groupBox")
+ self.layoutWidget = QtWidgets.QWidget(self.groupBox)
+ self.layoutWidget.setGeometry(QtCore.QRect(10, 20, 201, 201))
+ self.layoutWidget.setObjectName("layoutWidget")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget)
+ self.verticalLayout.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.label = QtWidgets.QLabel(self.layoutWidget)
+ self.label.setObjectName("label")
+ self.verticalLayout.addWidget(self.label)
+ self.comboBox_protocol = QtWidgets.QComboBox(self.layoutWidget)
+ self.comboBox_protocol.setObjectName("comboBox_protocol")
+ self.comboBox_protocol.addItem("")
+ self.verticalLayout.addWidget(self.comboBox_protocol)
+ self.label_2 = QtWidgets.QLabel(self.layoutWidget)
+ self.label_2.setObjectName("label_2")
+ self.verticalLayout.addWidget(self.label_2)
+ self.comboBox_localAddr = QtWidgets.QComboBox(self.layoutWidget)
+ self.comboBox_localAddr.setToolTipDuration(0)
+ self.comboBox_localAddr.setEditable(True)
+ self.comboBox_localAddr.setObjectName("comboBox_localAddr")
+ self.comboBox_localAddr.addItem("")
+ self.comboBox_localAddr.addItem("")
+ self.verticalLayout.addWidget(self.comboBox_localAddr)
+ self.label_3 = QtWidgets.QLabel(self.layoutWidget)
+ self.label_3.setObjectName("label_3")
+ self.verticalLayout.addWidget(self.label_3)
+ self.lineEdit_port = QtWidgets.QLineEdit(self.layoutWidget)
+ self.lineEdit_port.setObjectName("lineEdit_port")
+ self.verticalLayout.addWidget(self.lineEdit_port)
+ self.pushButton_openNet = QtWidgets.QPushButton(self.layoutWidget)
+ self.pushButton_openNet.setStyleSheet("background-color: rgb(0, 255, 0);")
+ self.pushButton_openNet.setObjectName("pushButton_openNet")
+ self.verticalLayout.addWidget(self.pushButton_openNet)
+ self.pushButton_closeNet = QtWidgets.QPushButton(self.layoutWidget)
+ self.pushButton_closeNet.setObjectName("pushButton_closeNet")
+ self.verticalLayout.addWidget(self.pushButton_closeNet)
+ self.verticalLayout_5.addWidget(self.groupBox)
+ self.groupBox_2 = QtWidgets.QGroupBox(self.widget)
+ self.groupBox_2.setMinimumSize(QtCore.QSize(0, 0))
+ self.groupBox_2.setBaseSize(QtCore.QSize(271, 165))
+ self.groupBox_2.setObjectName("groupBox_2")
+ self.layoutWidget_5 = QtWidgets.QWidget(self.groupBox_2)
+ self.layoutWidget_5.setGeometry(QtCore.QRect(10, 20, 197, 79))
+ self.layoutWidget_5.setObjectName("layoutWidget_5")
+ self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.layoutWidget_5)
+ self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout_6.setObjectName("verticalLayout_6")
+ self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_10.setObjectName("horizontalLayout_10")
+ self.checkBoxHexSend = QtWidgets.QCheckBox(self.layoutWidget_5)
+ self.checkBoxHexSend.setObjectName("checkBoxHexSend")
+ self.horizontalLayout_10.addWidget(self.checkBoxHexSend)
+ self.checkBoxHexReceive = QtWidgets.QCheckBox(self.layoutWidget_5)
+ self.checkBoxHexReceive.setObjectName("checkBoxHexReceive")
+ self.horizontalLayout_10.addWidget(self.checkBoxHexReceive)
+ self.verticalLayout_6.addLayout(self.horizontalLayout_10)
+ self.horizontalLayout_12 = QtWidgets.QHBoxLayout()
+ self.horizontalLayout_12.setObjectName("horizontalLayout_12")
+ self.checkBoxAddDate = QtWidgets.QCheckBox(self.layoutWidget_5)
+ self.checkBoxAddDate.setObjectName("checkBoxAddDate")
+ self.horizontalLayout_12.addWidget(self.checkBoxAddDate)
+ self.checkBoxCRLF = QtWidgets.QCheckBox(self.layoutWidget_5)
+ self.checkBoxCRLF.setObjectName("checkBoxCRLF")
+ self.horizontalLayout_12.addWidget(self.checkBoxCRLF)
+ self.verticalLayout_6.addLayout(self.horizontalLayout_12)
+ self.layoutWidget_6 = QtWidgets.QWidget(self.groupBox_2)
+ self.layoutWidget_6.setGeometry(QtCore.QRect(10, 130, 195, 30))
+ self.layoutWidget_6.setObjectName("layoutWidget_6")
+ self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.layoutWidget_6)
+ self.horizontalLayout_13.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_13.setObjectName("horizontalLayout_13")
+ self.pushButtonLogSave = QtWidgets.QPushButton(self.layoutWidget_6)
+ self.pushButtonLogSave.setObjectName("pushButtonLogSave")
+ self.horizontalLayout_13.addWidget(self.pushButtonLogSave)
+ self.pushButtonLogLoad = QtWidgets.QPushButton(self.layoutWidget_6)
+ self.pushButtonLogLoad.setObjectName("pushButtonLogLoad")
+ self.horizontalLayout_13.addWidget(self.pushButtonLogLoad)
+ 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.checkBoxSendSever = QtWidgets.QCheckBox(self.layoutWidget1)
+ self.checkBoxSendSever.setChecked(False)
+ self.checkBoxSendSever.setObjectName("checkBoxSendSever")
+ self.horizontalLayout_4.addWidget(self.checkBoxSendSever)
+ self.verticalLayout_5.addWidget(self.groupBox_2)
+ self.groupBox_3 = QtWidgets.QGroupBox(self.widget)
+ self.groupBox_3.setMinimumSize(QtCore.QSize(0, 0))
+ self.groupBox_3.setBaseSize(QtCore.QSize(271, 80))
+ self.groupBox_3.setObjectName("groupBox_3")
+ self.checkBoxReapitSend = QtWidgets.QCheckBox(self.groupBox_3)
+ self.checkBoxReapitSend.setGeometry(QtCore.QRect(10, 30, 91, 19))
+ self.checkBoxReapitSend.setObjectName("checkBoxReapitSend")
+ self.label_7 = QtWidgets.QLabel(self.groupBox_3)
+ self.label_7.setGeometry(QtCore.QRect(170, 30, 51, 16))
+ self.label_7.setObjectName("label_7")
+ self.lineEditTime = QtWidgets.QLineEdit(self.groupBox_3)
+ self.lineEditTime.setGeometry(QtCore.QRect(110, 30, 51, 21))
+ self.lineEditTime.setObjectName("lineEditTime")
+ self.verticalLayout_5.addWidget(self.groupBox_3)
+ spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
+ self.verticalLayout_5.addItem(spacerItem)
+ self.groupBox_6 = QtWidgets.QGroupBox(self.widget)
+ self.groupBox_6.setMinimumSize(QtCore.QSize(0, 0))
+ self.groupBox_6.setBaseSize(QtCore.QSize(281, 80))
+ self.groupBox_6.setTitle("")
+ self.groupBox_6.setObjectName("groupBox_6")
+ self.label_9 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_9.setGeometry(QtCore.QRect(120, 20, 72, 15))
+ self.label_9.setObjectName("label_9")
+ self.lineEditSendNum = QtWidgets.QLineEdit(self.groupBox_6)
+ self.lineEditSendNum.setGeometry(QtCore.QRect(40, 20, 61, 21))
+ self.lineEditSendNum.setObjectName("lineEditSendNum")
+ self.lineEditReceiveNum = QtWidgets.QLineEdit(self.groupBox_6)
+ self.lineEditReceiveNum.setGeometry(QtCore.QRect(140, 20, 61, 21))
+ self.lineEditReceiveNum.setObjectName("lineEditReceiveNum")
+ self.label_10 = QtWidgets.QLabel(self.groupBox_6)
+ self.label_10.setGeometry(QtCore.QRect(20, 40, 131, 16))
+ self.label_10.setObjectName("label_10")
+ self.label_SendNum = QtWidgets.QLabel(self.groupBox_6)
+ self.label_SendNum.setGeometry(QtCore.QRect(20, 20, 72, 15))
+ self.label_SendNum.setObjectName("label_SendNum")
+ self.verticalLayout_5.addWidget(self.groupBox_6)
+ self.verticalLayout_5.setStretch(0, 8)
+ self.verticalLayout_5.setStretch(1, 6)
+ self.verticalLayout_5.setStretch(2, 2)
+ self.verticalLayout_5.setStretch(4, 2)
+ self.horizontalLayout.addWidget(self.widget)
+ self.widget_5 = QtWidgets.QWidget(self.splitter)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(1)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.widget_5.sizePolicy().hasHeightForWidth())
+ self.widget_5.setSizePolicy(sizePolicy)
+ self.widget_5.setMinimumSize(QtCore.QSize(400, 0))
+ self.widget_5.setObjectName("widget_5")
+ self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.widget_5)
+ self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
+ self.verticalLayout_3.setObjectName("verticalLayout_3")
+ 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.QPlainTextEdit(self.tab1)
+ self.textEditReceive.setSizeIncrement(QtCore.QSize(0, 0))
+ self.textEditReceive.setObjectName("textEditReceive")
+ 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(6)
+ 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()
+ self.tableWidget.setHorizontalHeaderItem(4, item)
+ item = QtWidgets.QTableWidgetItem()
+ item.setBackground(QtGui.QColor(172, 172, 172))
+ self.tableWidget.setHorizontalHeaderItem(5, 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")
+ self.comboBox_channel = QtWidgets.QComboBox(self.groupBox_7)
+ self.comboBox_channel.setEditable(True)
+ self.comboBox_channel.setObjectName("comboBox_channel")
+ self.comboBox_channel.addItem("")
+ self.horizontalLayout_3.addWidget(self.comboBox_channel)
+ self.pushButtonClearChannel = QtWidgets.QPushButton(self.groupBox_7)
+ self.pushButtonClearChannel.setObjectName("pushButtonClearChannel")
+ self.horizontalLayout_3.addWidget(self.pushButtonClearChannel)
+ 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.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")
+ font.setPointSize(12)
+ self.pushButtonSend.setFont(font)
+ self.pushButtonSend.setAutoFillBackground(False)
+ self.pushButtonSend.setStyleSheet("background-color: rgb(0, 255, 0);")
+ self.pushButtonSend.setCheckable(False)
+ self.pushButtonSend.setFlat(False)
+ self.pushButtonSend.setObjectName("pushButtonSend")
+ self.gridLayout.addWidget(self.pushButtonSend, 4, 1, 1, 1)
+ self.verticalLayout_3.addWidget(self.groupBox_5)
+ self.verticalLayout_3.setStretch(0, 7)
+ self.verticalLayout_3.setStretch(1, 1)
+ self.verticalLayout_3.setStretch(2, 2)
+ self.widget_6 = QtWidgets.QWidget(self.splitter)
+ self.widget_6.setEnabled(True)
+ sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
+ sizePolicy.setHorizontalStretch(0)
+ sizePolicy.setVerticalStretch(0)
+ sizePolicy.setHeightForWidth(self.widget_6.sizePolicy().hasHeightForWidth())
+ self.widget_6.setSizePolicy(sizePolicy)
+ self.widget_6.setMinimumSize(QtCore.QSize(280, 0))
+ self.widget_6.setObjectName("widget_6")
+ self.horizontalLayout_16 = QtWidgets.QHBoxLayout(self.widget_6)
+ self.horizontalLayout_16.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_16.setSpacing(0)
+ self.horizontalLayout_16.setObjectName("horizontalLayout_16")
+ self.scrollArea = QtWidgets.QScrollArea(self.widget_6)
+ self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOn)
+ self.scrollArea.setWidgetResizable(False)
+ self.scrollArea.setObjectName("scrollArea")
+ self.scrollAreaWidgetContents = QtWidgets.QWidget()
+ 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))
+ self.widget_8.setObjectName("widget_8")
+ self.horizontalLayout_17 = QtWidgets.QHBoxLayout(self.widget_8)
+ self.horizontalLayout_17.setContentsMargins(0, 0, 0, 0)
+ self.horizontalLayout_17.setObjectName("horizontalLayout_17")
+ self.label_8 = QtWidgets.QLabel(self.widget_8)
+ self.label_8.setObjectName("label_8")
+ self.horizontalLayout_17.addWidget(self.label_8)
+ self.checkBox_return = QtWidgets.QCheckBox(self.widget_8)
+ self.checkBox_return.setChecked(True)
+ self.checkBox_return.setObjectName("checkBox_return")
+ self.horizontalLayout_17.addWidget(self.checkBox_return)
+ self.widget_9 = QtWidgets.QWidget(self.scrollAreaWidgetContents)
+ self.widget_9.setGeometry(QtCore.QRect(10, 40, 231, 3000))
+ self.widget_9.setObjectName("widget_9")
+ 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_2.addWidget(self.widget_7)
+
+ self.retranslateUi(UartAssistant)
+ self.comboBox_localAddr.setCurrentIndex(0)
+ self.tabWidget.setCurrentIndex(0)
+ QtCore.QMetaObject.connectSlotsByName(UartAssistant)
+
+ def retranslateUi(self, UartAssistant):
+ _translate = QtCore.QCoreApplication.translate
+ UartAssistant.setWindowTitle(_translate("UartAssistant", "串口助手py版"))
+ self.groupBox.setTitle(_translate("UartAssistant", "网络设置"))
+ self.label.setText(_translate("UartAssistant", "协议类型"))
+ self.comboBox_protocol.setItemText(0, _translate("UartAssistant", "UDP"))
+ self.label_2.setText(_translate("UartAssistant", "本地主机地址"))
+ self.comboBox_localAddr.setCurrentText(_translate("UartAssistant", "127.0.0.1"))
+ self.comboBox_localAddr.setItemText(0, _translate("UartAssistant", "127.0.0.1"))
+ self.comboBox_localAddr.setItemText(1, _translate("UartAssistant", "0.0.0.0"))
+ self.label_3.setText(_translate("UartAssistant", "本地主机端口"))
+ self.lineEdit_port.setText(_translate("UartAssistant", "9000"))
+ self.pushButton_openNet.setText(_translate("UartAssistant", "打开网络"))
+ self.pushButton_closeNet.setText(_translate("UartAssistant", "关闭网络"))
+ self.groupBox_2.setTitle(_translate("UartAssistant", "收发设置"))
+ self.checkBoxHexSend.setText(_translate("UartAssistant", "HEX发送"))
+ self.checkBoxHexReceive.setText(_translate("UartAssistant", "HEX接收"))
+ self.checkBoxAddDate.setText(_translate("UartAssistant", "收/发时间"))
+ self.checkBoxCRLF.setText(_translate("UartAssistant", "收发换行"))
+ self.pushButtonLogSave.setText(_translate("UartAssistant", "保存日志"))
+ self.pushButtonLogLoad.setText(_translate("UartAssistant", "加载日志"))
+ self.checkBoxAutoSaveLog.setText(_translate("UartAssistant", "自动保存日志"))
+ self.checkBoxSendSever.setText(_translate("UartAssistant", "启动服务"))
+ self.groupBox_3.setTitle(_translate("UartAssistant", "定时发送"))
+ self.checkBoxReapitSend.setText(_translate("UartAssistant", "定时发送"))
+ self.label_7.setText(_translate("UartAssistant", "ms/次"))
+ self.lineEditTime.setText(_translate("UartAssistant", "1000"))
+ self.label_9.setText(_translate("UartAssistant", "Rx"))
+ self.label_10.setText(_translate("UartAssistant", "Powerd by Byan"))
+ self.label_SendNum.setText(_translate("UartAssistant", "Tx"))
+ 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", "hex"))
+ item = self.tableWidget.horizontalHeaderItem(5)
+ 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.pushButton_expend.setText(_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\""))
diff --git a/PyNetAssistant_Sever/PyNetUi.ui b/PyNetAssistant_Sever/PyNetUi.ui
new file mode 100644
index 0000000..a8faa40
--- /dev/null
+++ b/PyNetAssistant_Sever/PyNetUi.ui
@@ -0,0 +1,853 @@
+
+
+ UartAssistant
+
+
+
+ 0
+ 0
+ 956
+ 650
+
+
+
+
+ 2
+ 0
+
+
+
+ true
+
+
+ 串口助手py版
+
+
+
+ favicon.icofavicon.ico
+
+
+ -
+
+
+
-
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Qt::Horizontal
+
+
+ 5
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 230
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 271
+ 291
+
+
+
+ 网络设置
+
+
+
+
+ 10
+ 20
+ 201
+ 201
+
+
+
+
-
+
+
+ 协议类型
+
+
+
+ -
+
+
-
+
+ UDP
+
+
+
+
+ -
+
+
+ 本地主机地址
+
+
+
+ -
+
+
+ 0
+
+
+ true
+
+
+ 127.0.0.1
+
+
+ 0
+
+
-
+
+ 127.0.0.1
+
+
+ -
+
+ 0.0.0.0
+
+
+
+
+ -
+
+
+ 本地主机端口
+
+
+
+ -
+
+
+ 9000
+
+
+
+ -
+
+
+ background-color: rgb(0, 255, 0);
+
+
+ 打开网络
+
+
+
+ -
+
+
+ 关闭网络
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 271
+ 165
+
+
+
+ 收发设置
+
+
+
+
+ 10
+ 20
+ 197
+ 79
+
+
+
+
-
+
+
-
+
+
+ HEX发送
+
+
+
+ -
+
+
+ HEX接收
+
+
+
+
+
+ -
+
+
-
+
+
+ 收/发时间
+
+
+
+ -
+
+
+ 收发换行
+
+
+
+
+
+
+
+
+
+
+ 10
+ 130
+ 195
+ 30
+
+
+
+ -
+
+
+ 保存日志
+
+
+
+ -
+
+
+ 加载日志
+
+
+
+
+
+
+
+
+ 12
+ 100
+ 191
+ 31
+
+
+
+ -
+
+
+ 自动保存日志
+
+
+ true
+
+
+
+ -
+
+
+ 启动服务
+
+
+ false
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 271
+ 80
+
+
+
+ 定时发送
+
+
+
+
+ 10
+ 30
+ 91
+ 19
+
+
+
+ 定时发送
+
+
+
+
+
+ 170
+ 30
+ 51
+ 16
+
+
+
+ ms/次
+
+
+
+
+
+ 110
+ 30
+ 51
+ 21
+
+
+
+ 1000
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 281
+ 80
+
+
+
+
+
+
+
+
+ 120
+ 20
+ 72
+ 15
+
+
+
+ Rx
+
+
+
+
+
+ 40
+ 20
+ 61
+ 21
+
+
+
+
+
+
+ 140
+ 20
+ 61
+ 21
+
+
+
+
+
+
+ 20
+ 40
+ 131
+ 16
+
+
+
+ Powerd by Byan
+
+
+
+
+
+ 20
+ 20
+ 72
+ 15
+
+
+
+ Tx
+
+
+
+
+
+
+
+
+
+
+
+
+ 1
+ 0
+
+
+
+
+ 400
+ 0
+
+
+
+ -
+
+
+ 0
+
+
+
+ Qt::TabFocus
+
+
+ 数据
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+ true
+
+
+ Qt::NoFocus
+
+
+ 解析
+
+
+ -
+
+
+ Qt::SolidLine
+
+
+ 10
+
+
+ 6
+
+
+ false
+
+
+ 20
+
+
+ 50
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+ false
+
+
+ 25
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select
+
+
+
+ 172
+ 172
+ 172
+
+
+
+
+
+ start
+
+
+
+ 172
+ 172
+ 172
+
+
+
+
+
+ num
+
+
+
+ 172
+ 172
+ 172
+
+
+
+
+
+ scale
+
+
+
+
+ hex
+
+
+
+
+ value
+
+
+
+ 172
+ 172
+ 172
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 选择通道
+
+
+
-
+
+
+ true
+
+
-
+
+ ALL
+
+
+
+
+ -
+
+
+ 清空
+
+
+
+
+
+
+ -
+
+
+ 数据发送区
+
+
+
-
+
+
+ -
+
+
+ 快捷指令
+
+
+
+ -
+
+
+ 清除接收
+
+
+
+ -
+
+
+ 清除发送
+
+
+
+ -
+
+
+
-
+
+
+ 发送全部通道
+
+
+
+ -
+
+
+ 附加校验
+
+
+
+
+
+
+ -
+
+
+
+ 3ds
+ 12
+
+
+
+ false
+
+
+ background-color: rgb(0, 255, 0);
+
+
+ 发送
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 280
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::ScrollBarAlwaysOn
+
+
+ false
+
+
+
+
+ 0
+ 0
+ 241
+ 3000
+
+
+
+
+
+ 12
+ 2
+ 221
+ 34
+
+
+
+
-
+
+
+ 快捷指令
+
+
+
+ -
+
+
+ 添加"\r\n"
+
+
+ true
+
+
+
+
+
+
+
+
+ 10
+ 40
+ 231
+ 3000
+
+
+
+
+
+ 12
+ 12
+ 218
+ 2941
+
+
+
+
+ QLayout::SetMaximumSize
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/PyNetAssistant_Sever/PyUart.py b/PyNetAssistant_Sever/PyUart.py
new file mode 100644
index 0000000..24cbfba
--- /dev/null
+++ b/PyNetAssistant_Sever/PyUart.py
@@ -0,0 +1,670 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon May 27 14:31:38 2024
+
+@author: WANGXIBAO
+"""
+
+import sys
+import serial,re
+import serial.tools.list_ports
+import time,datetime
+
+from PyQt5 import QtWidgets
+from PyQt5.QtWidgets import QMessageBox ,QFileDialog,QInputDialog
+from PyQt5.QtCore import QTimer
+from PyUartUi import Ui_UartAssistant
+from PyQt5.QtGui import QIcon
+
+
+class PyQt5Serial(QtWidgets.QWidget,Ui_UartAssistant):
+ # %%初始化程序
+ def __init__(self):
+ super(PyQt5Serial, self).__init__()
+ self.setupUi(self)
+
+
+
+
+
+ self.init()
+ self.ser = serial.Serial() #创建一个空对象
+ self.port_check()
+
+ # 设置Logo和标题
+ self.setWindowIcon(QIcon('./favicon.ico'))
+ self.setWindowTitle("调试助手")
+ # 设置禁止拉伸窗口大小
+ #self.setFixedSize(self.width(), self.height())
+
+ # 发送数据和接收数据数目置零
+ self.data_num_sended = 0
+ self.lineEditSendNum.setText(str(self.data_num_sended))
+ self.data_num_received = 0
+ self.lineEditReceiveNum.setText(str(self.data_num_received))
+
+ # 串口关闭按钮使能关闭
+ self.pushButtonCloseSerial.setEnabled(False)
+
+ # 发送框、文本框清除
+ self.textEditReceive.setText("")
+ self.textEditSend.setText("")
+ # %%第二个TAB 初始化画图页面表格
+
+
+ # 加载Qchart波形界面
+
+
+ #加载快捷指令
+ self.widget_6.hide()
+ #加载快捷指令的按键值
+
+
+
+
+ # 用于暂存接收的串口数据
+ self.buffer = b''
+ # 用于暂存解码数据
+ self.lineUtf8 = ""
+ # 用于标志是否开始存CSV
+ self.CsvFlag = 0
+ # =============================================================================
+# def wheelEvent(self, event):
+# if self.plot_view.underMouse:
+# # 鼠标滚轮:缩放Qchart波形
+# if event.angleDelta().y() >= 0:
+# # 鼠标滚轮向上
+# if event.x() < (
+# self.plot_view.width() + self.plot_view.x()) and event.x() > self.plot_view.x():
+# if event.y() < (
+# self.plot_view.height() + self.plot_view.y()) and event.y() > self.plot_view.y():
+# self.plot_qchart.zoomIn()
+# else:
+# # 鼠标滚轮向下
+# if event.x() < (
+# self.plot_view.width() + self.plot_view.x()) and event.x() > self.plot_view.x():
+# if event.y() < (
+# self.plot_view.height() + self.plot_view.y()) and event.y() > self.plot_view.y():
+# self.plot_qchart.zoomOut()
+# =============================================================================
+ #%% 重写关闭按钮
+ def closeEvent(self, event):
+ self.update_data_thread.stop()
+ # 可选:加入超时判断,防止线程未能正常退出导致程序无法关闭
+ if not self.update_data_thread.wait(1000): # 等待5秒
+ print("线程未在指定时间内退出,可能需要进一步处理")
+
+
+ # 如果串口已经打开,则关闭串口
+ if self.ser.is_open:
+ self.port_close()
+
+ #关闭界面前保存快捷区域的命令和名称
+ for i in range(20): # 假设有20个按钮
+ button_name = f'Button{i:02}' # 格式化按钮名称,确保两位数
+ set_text = getattr(self, f'lineEditQuick_{i+1}').text()+ "|" + getattr(self, f'pushButtonQuick_{i+1}').text()
+ self.get_data_tf.SetCfgIniData(button_name, set_text)
+
+
+
+
+ # 调用父类的关闭事件处理函数
+ super().closeEvent(event)
+
+
+
+
+ # %%建立控件信号与槽关系
+ def init(self):
+ # 串口检测按钮
+ self.pushButtonTestSerial.clicked.connect(self.port_check)
+ # 串口打开按钮
+ self.pushButtonOpenSerial.clicked.connect(self.port_open)
+ # 串口关闭按钮
+ self.pushButtonCloseSerial.clicked.connect(self.port_close)
+
+ # 定时发送数据
+ self.timer_send = QTimer()
+ self.timer_send.timeout.connect(self.data_send)
+ self.checkBoxReapitSend.stateChanged.connect(self.data_send_timer)
+
+ # 发送数据按钮
+ self.pushButtonSend.clicked.connect(lambda:self.data_send(text_quick= None))
+
+ # 保存日志
+ self.pushButtonLogSave.clicked.connect(self.savefiles)
+ # 加载日志
+ self.pushButtonLogLoad.clicked.connect(self.openfiles)
+
+ # 跳转链接
+ #self.commandLinkButton1.clicked.connect(self.link)
+
+ # 清除发送按钮
+ self.pushButtonClearSend.clicked.connect(self.send_data_clear)
+
+ # 清除接收按钮
+ self.pushButtonClearReceive.clicked.connect(self.receive_data_clear)
+
+
+
+
+ # 快捷指令扩展区域
+ self.pushButton_expend.clicked.connect(self.adjust_sidebar)
+ # 创建一个通用的槽函数来处理所有按钮
+# 例如,使用lambda表达式传递额外的参数
+ for i in range(1, 21): # 假设有20个按钮
+ # getattr(self, f'pushButtonQuick_{i}').clicked.connect(
+ # lambda checked, line_edit=f'lineEditQuick_{i}': self.onPushButtonQuickClicked(line_edit)
+ # )
+ # 连接左键点击事件
+ button = getattr(self, f'pushButtonQuick_{i}')
+ line_edit = f'lineEditQuick_{i}'
+ button.clicked.connect(lambda checked, line_edit=line_edit: self.onPushButtonQuickClicked(line_edit))
+
+ # 连接右键点击事件
+ # button_id = f'pushButtonQuick_{i}'
+ # button.setContextMenuPolicy(Qt.CustomContextMenu)
+ # button.customContextMenuRequested.connect(lambda position, button_id=button_id: self.onButtonRightClicked(button_id))
+
+ # %% 串口检测
+ def port_check(self):
+ # 检测所有存在的串口,将信息存储在字典中
+ self.Com_Dict = {}
+ port_list = list(serial.tools.list_ports.comports())
+
+ self.comboBoxSerial.clear()
+ for port in port_list:
+ self.Com_Dict["%s" % port[0]] = "%s" % port[1]
+ self.comboBoxSerial.addItem(port[0])
+
+ # 无串口判断
+ if len(self.Com_Dict) == 0:
+ self.comboBoxSerial.addItem("无串口")
+ # %%打开串口
+ def port_open(self):
+ self.ser.port = self.comboBoxSerial.currentText() # 串口号
+ self.ser.baudrate = int(self.comboBoxBaudrate.currentText()) # 波特率
+ self.ser.timeout = 0.01
+
+
+
+ flag_data = int(self.comboBoxDataBits.currentText()) # 数据位
+ if flag_data == 5:
+ self.ser.bytesize = serial.FIVEBITS
+ elif flag_data == 6:
+ self.ser.bytesize = serial.SIXBITS
+ elif flag_data == 7:
+ self.ser.bytesize = serial.SEVENBITS
+ else:
+ self.ser.bytesize = serial.EIGHTBITS
+
+ flag_data = self.comboBoxCheckBit.currentText() # 校验位
+ if flag_data == "None":
+ self.ser.parity = serial.PARITY_NONE
+ elif flag_data == "Odd":
+ self.ser.parity = serial.PARITY_ODD
+ else:
+ self.ser.parity = serial.PARITY_EVEN
+
+ flag_data = int(self.comboBoxStopBit.currentText()) # 停止位
+ if flag_data == 1:
+ self.ser.stopbits = serial.STOPBITS_ONE
+ else:
+ self.ser.stopbits = serial.STOPBITS_TWO
+
+ flag_data = self.comboBoxFlow.currentText() # 流控
+ if flag_data == "No Ctrl Flow":
+ self.ser.xonxoff = False #软件流控
+ self.ser.dsrdtr = False #硬件流控 DTR
+ self.ser.rtscts = False #硬件流控 RTS
+ elif flag_data == "SW Ctrl Flow":
+ self.ser.xonxoff = True #软件流控
+ else:
+ if self.checkBoxDTR.isChecked():
+ self.ser.dsrdtr = True #硬件流控 DTR
+ if self.checkBoxRTS.isChecked():
+ self.ser.rtscts = True #硬件流控 RTS
+ try:
+ time.sleep(0.1)
+ if self.ser.is_open:
+ self.ser.close()
+ self.ser.open()
+ except:
+ QMessageBox.critical(self, "串口异常", "此串口不能被打开!")
+ return None
+
+ # 串口打开后,切换开关串口按钮使能状态,防止失误操作
+ if self.ser.isOpen():
+ self.pushButtonOpenSerial.setEnabled(False)
+ self.pushButtonCloseSerial.setEnabled(True)
+ self.comboBoxBaudrate.setEnabled(False)
+ self.comboBoxSerial.setEnabled(False)
+ self.pushButton_expend.setEnabled(True)
+ #self.formGroupBox1.setTitle("串口状态(开启)")
+
+ #日志保存
+ # 格式化日期时间字符串,用于文件名
+ # 例如:2024-05-28_12-34-56.txt
+ self.file = self.ser.port+"-"+time.strftime("%Y%m%d%H%M%S", time.localtime())
+ self.filename = self.file + ".txt"
+
+
+ # 定时器接收数据
+ self.timer = QTimer()
+ self.timer.timeout.connect(self.data_receive)
+ # 打开串口接收定时器,周期为1ms
+ self.timer.start(20)
+
+ # %%接收数据
+ def data_receive(self):
+
+ try:
+ num = self.ser.inWaiting()
+
+
+ if num>0 :
+ #print("接收数据",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
+ try:
+ data = self.ser.read(num)
+ except:
+ QMessageBox.critical(self, '串口异常')
+ self.buffer+=data
+
+ #print("接收完成",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
+
+ if self.checkBoxAddDate.isChecked():
+ nowTime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
+ nowTime = nowTime[:-3]
+ self.textEditReceive.insertPlainText(nowTime + " ")
+
+ # HEX显示数据
+ if self.checkBoxHexReceive.checkState():
+ out_s = ''
+ for i in range(0, len(data)):
+ out_s = out_s + '{:02X}'.format(data[i]) + ' '
+
+ self.textEditReceive.insertPlainText(out_s)
+ # ASCII显示数据
+ else:
+ #print("解码前",datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
+ self.textEditReceive.insertPlainText(data.decode('utf-8',errors='replace'))
+ #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()
+ # 滚动到底部
+ textCursor.movePosition(textCursor.End)
+ # 设置光标到text中去
+ self.textEditReceive.setTextCursor(textCursor)
+
+ # 统计接收字符的数量
+ self.data_num_received += num
+ self.lineEditReceiveNum.setText(str(self.data_num_received))
+
+ # 自动保存日志
+ if self.checkBoxAutoSaveLog.isChecked():
+ self.AutoSaveLog()
+
+
+
+ except:
+ # QMessageBox.critical(self, '串口异常', '串口接收数据异常,请重新连接设备!')
+ # 获取到text光标
+ textCursor = self.textEditReceive.textCursor()
+ # 滚动到底部
+ textCursor.movePosition(textCursor.End)
+ # 设置光标到text中去
+ self.textEditReceive.setTextCursor(textCursor)
+ self.textEditReceive.insertPlainText("串口断开,重连中...\r\n")
+ self.ser.close()
+
+ try:
+ print("重连中...")
+ time.sleep(1)
+ if not self.ser.is_open:
+ self.ser.open()
+ print("重连成功")
+ else:
+ print("串口已连接,无需重连")
+ except Exception as e:
+
+ print(f"重连失败{e}")
+
+
+
+ # %%定时发送数据
+ def data_send_timer(self):
+ try:
+ 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)
+ else:
+ self.timer_send.stop()
+ self.lineEditTime.setEnabled(True)
+ else:
+ QMessageBox.critical(self, '定时发送数据异常', '定时发送数据周期仅可设置在30秒内!')
+ except:
+ QMessageBox.critical(self, '定时发送数据异常', '请设置正确的数值类型!')
+
+ # %%发送数据
+ def data_send(self,text_quick = None):
+ if self.ser.isOpen():
+ if text_quick== None:
+ input_s = self.textEditSend.toPlainText()
+ else:
+ input_s = text_quick
+
+ # 判断是否为非空字符串
+ if input_s != "":
+ # 时间显示
+ if self.checkBoxAddDate.isChecked():
+ self.textEditReceive.insertPlainText((time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) + " ")
+
+ # HEX发送
+ if self.checkBoxHexSend.isChecked():
+ input_s = input_s.strip()
+ send_list = []
+ while input_s != '':
+ try:
+ num = int(input_s[0:2], 16)
+ except ValueError:
+ QMessageBox.critical(self, '串口异常', '请输入规范十六进制数据,以空格分开!')
+ return None
+
+ input_s = input_s[2:].strip()
+ send_list.append(num)
+
+ input_s = bytes(send_list)
+ # ASCII发送
+ else:
+ input_s = (input_s).encode('utf-8')
+ input_s = re.sub(b'(?
+
+
+
+ 气体浓度和温度实时显示
+
+
+
+ 气体浓度和温度实时显示
+
+
+
+
+
+
\ No newline at end of file
diff --git a/PyNetAssistant_Sever/udp.ini b/PyNetAssistant_Sever/udp.ini
new file mode 100644
index 0000000..4d9046f
--- /dev/null
+++ b/PyNetAssistant_Sever/udp.ini
@@ -0,0 +1,4 @@
+[NetConfig]
+ip = 127.0.0.1
+port = 9000
+
diff --git a/PyNetAssistant_Sever/untitled0.py b/PyNetAssistant_Sever/untitled0.py
new file mode 100644
index 0000000..1b79a82
--- /dev/null
+++ b/PyNetAssistant_Sever/untitled0.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sun Sep 29 21:35:04 2024
+
+@author: wxb51
+"""
+
+import sys
+from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QVBoxLayout, QLineEdit, QPushButton
+
+class Example(QWidget):
+ def __init__(self):
+ super().__init__()
+
+ self.initUI()
+
+ def initUI(self):
+ # 创建一个垂直布局
+ self.verticalLayout = QVBoxLayout()
+
+ # 创建一个放置布局的小部件
+ self.layoutWidget = QWidget(self)
+
+ # 循环创建水平布局、文本输入框和按钮
+ for i in range(21): # 从0到20
+ horizontalLayout = QHBoxLayout()
+ horizontalLayout.setObjectName(f"horizontalLayout_{i}")
+
+ lineEdit = QLineEdit(self.layoutWidget)
+ lineEdit.setObjectName(f"lineEdit_{i}")
+ horizontalLayout.addWidget(lineEdit)
+
+ pushButton = QPushButton(self.layoutWidget)
+ pushButton.setObjectName(f"pushButton_{i}")
+ horizontalLayout.addWidget(pushButton)
+
+ self.verticalLayout.addLayout(horizontalLayout)
+
+ # 将垂直布局设置为主布局
+ self.setLayout(self.verticalLayout)
+
+ # 设置窗口标题
+ self.setWindowTitle('Multiple Layouts Example')
+
+if __name__ == '__main__':
+ app = QApplication(sys.argv)
+ ex = Example()
+ ex.show()
+ sys.exit(app.exec_())
\ No newline at end of file
diff --git a/test/pythonProject1/.idea/pythonProject1.iml b/test/pythonProject1/.idea/pythonProject1.iml
new file mode 100644
index 0000000..6f1ddae
--- /dev/null
+++ b/test/pythonProject1/.idea/pythonProject1.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file