134 lines
5.2 KiB
Python
Raw Normal View History

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