2025-03-14 16:15:51 +08:00
|
|
|
|
from datetime import datetime
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
from PyQt5.QtWidgets import QMessageBox
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class DataProcessor:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.log_buffer = {}
|
|
|
|
|
self.log_time = 10
|
|
|
|
|
self.position = 5
|
|
|
|
|
self.funcode = 'F4'
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def encode_data(data):
|
|
|
|
|
"""编码数据"""
|
|
|
|
|
try:
|
|
|
|
|
encoded_data = data.encode('utf-8')
|
|
|
|
|
encoded_data = re.sub(b'(?<!\r)\n', b'\r\n', encoded_data) # 替换换行符
|
|
|
|
|
return encoded_data
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return f"编码失败: {e}"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def decode_data(data):
|
|
|
|
|
"""解码数据"""
|
|
|
|
|
try:
|
|
|
|
|
decoded_data = data.decode('utf-8', errors='replace')
|
|
|
|
|
|
|
|
|
|
return decoded_data
|
|
|
|
|
except Exception as e:
|
|
|
|
|
return f"解码失败: {e}"
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def format_bytes_to_hexstr_space(data_bytes):
|
|
|
|
|
"""格式化数据为十六进制字符串"""
|
|
|
|
|
out_str = ' '.join(f'{byte:02X}' for byte in data_bytes)
|
|
|
|
|
return out_str
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def format_bytes_to_hexstr(data_bytes):
|
|
|
|
|
"""格式化数据为十六进制字符串"""
|
|
|
|
|
out_str = ''.join(f'{byte:02X}' for byte in data_bytes)
|
|
|
|
|
return out_str
|
|
|
|
|
@staticmethod
|
|
|
|
|
def format_hexstr_space_to_bytes(hexstr_space):
|
|
|
|
|
"""将十六进制字符串转换为字节数组"""
|
|
|
|
|
send_list = []
|
|
|
|
|
input_s = hexstr_space.strip() # 移除所有空格
|
|
|
|
|
# 将输入字符串转换为十六进制数值列表
|
|
|
|
|
while input_s != '':
|
|
|
|
|
try:
|
|
|
|
|
# 尝试将字符串的前两个字符转换为十六进制数
|
|
|
|
|
num = int(input_s[0:2], 16)
|
|
|
|
|
except ValueError:
|
|
|
|
|
# 如果转换失败,弹出错误提示并返回None
|
|
|
|
|
msg_box = QMessageBox()
|
|
|
|
|
msg_box.setIcon(QMessageBox.Critical)
|
|
|
|
|
msg_box.setWindowTitle('串口异常')
|
|
|
|
|
msg_box.setText('请输入规范十六进制数据,以空格分开!')
|
|
|
|
|
msg_box.exec_()
|
|
|
|
|
return None
|
|
|
|
|
# 更新输入字符串,移除已经处理的前两个字符,并去除前导空格
|
|
|
|
|
input_s = input_s[2:].strip()
|
|
|
|
|
# 将转换后的十六进制数添加到发送列表中
|
|
|
|
|
send_list.append(num)
|
|
|
|
|
out_bytes = bytes(send_list) # 将字符串转换为字节串
|
|
|
|
|
return out_bytes
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def crc_rtu(data):
|
|
|
|
|
crc = 0xFFFF
|
|
|
|
|
for pos in data:
|
|
|
|
|
crc ^= pos
|
|
|
|
|
for _ in range(8):
|
|
|
|
|
if (crc & 0x0001) != 0:
|
|
|
|
|
crc >>= 1
|
|
|
|
|
crc ^= 0xA001
|
|
|
|
|
else:
|
|
|
|
|
crc >>= 1
|
|
|
|
|
return crc.to_bytes(2, byteorder='little') # 返回低字节在前
|
|
|
|
|
|
|
|
|
|
def auto_save_log_asc(self, port_name, decoded_data):
|
|
|
|
|
# 根据功能码保存数据
|
|
|
|
|
line = decoded_data.split(',')
|
|
|
|
|
if len(line) == 2:
|
|
|
|
|
sav_name = line[0] + '_' + datetime.now().strftime("%Y-%m-%d") + '.txt'
|
|
|
|
|
sav_str = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + line[1]
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
sav_name = port_name + '_' + datetime.now().strftime("%Y-%m-%d") + '.log'
|
|
|
|
|
sav_str = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + decoded_data
|
|
|
|
|
self.auto_save_Log(sav_name, sav_str)
|
|
|
|
|
|
|
|
|
|
def auto_save_log_hex(self, port_name, data_bytes):
|
|
|
|
|
data_hex_str = self.format_bytes_to_hexstr(data_bytes)
|
|
|
|
|
out_str = self.format_bytes_to_hexstr_space(data_bytes)
|
|
|
|
|
if data_hex_str[2 * self.position:2 * self.position + 2] == self.funcode:
|
|
|
|
|
sav_name = data_hex_str[0:8] + '_' + datetime.now().strftime("%Y-%m-%d") + '.txt'
|
|
|
|
|
sav_str = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_str[12:] + "\r\n"
|
|
|
|
|
# 当表示浓度的字符不为0时 将数据单独记录
|
|
|
|
|
if data_hex_str[14:18] != '0000':
|
|
|
|
|
sav_name_out = 'alarm_' + data_hex_str[0:8] + '_' + datetime.now().strftime("%Y-%m-%d") + '.txt'
|
|
|
|
|
sav_str_out = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_str[12:] + "\r\n"
|
|
|
|
|
with open(sav_name_out, mode='a', newline='', encoding='utf-8', errors='replace') as file:
|
|
|
|
|
file.writelines(sav_str_out)
|
|
|
|
|
else:
|
|
|
|
|
sav_name = port_name + '_' + datetime.now().strftime("%Y-%m-%d") + '.log'
|
|
|
|
|
sav_str = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%f")[:23] + " " + out_str + "\r\n"
|
|
|
|
|
self.auto_save_Log(sav_name, sav_str)
|
|
|
|
|
|
|
|
|
|
def auto_save_Log(self, sav_name, sav_str):
|
|
|
|
|
|
|
|
|
|
# 将日志信息添加到缓冲区
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_log_time(self, log_time):
|
|
|
|
|
self.log_time = log_time
|
|
|
|
|
|
|
|
|
|
def update_position(self, position):
|
|
|
|
|
self.position = position
|
|
|
|
|
|
|
|
|
|
def update_funcode(self, funcode):
|
|
|
|
|
self.funcode = funcode
|