feat: 增强线径数据处理逻辑,新增会话管理和稳定性检查功能,优化数据保存流程
This commit is contained in:
parent
383e6d3aaa
commit
5a05bfe9a2
@ -1675,6 +1675,8 @@ class MainWindow(MainWindowUI):
|
|||||||
# 立即更新一次用电量数据
|
# 立即更新一次用电量数据
|
||||||
self.update_electricity_statistics()
|
self.update_electricity_statistics()
|
||||||
|
|
||||||
|
# 连接称重数据变化信号
|
||||||
|
self.machine_handlers.weight_changed.connect(self.handle_weight_data)
|
||||||
# 立即更新一次订单数量和产量统计数据
|
# 立即更新一次订单数量和产量统计数据
|
||||||
self.update_order_statistics()
|
self.update_order_statistics()
|
||||||
|
|
||||||
@ -2719,146 +2721,101 @@ class MainWindow(MainWindowUI):
|
|||||||
logging.error(f"处理米电阻数据失败: {str(e)}")
|
logging.error(f"处理米电阻数据失败: {str(e)}")
|
||||||
|
|
||||||
def on_diameter_data_received(self, port_name, data):
|
def on_diameter_data_received(self, port_name, data):
|
||||||
"""线径数据接收回调函数
|
"""线径数据接收回调函数 - 采用类似称重的逻辑,不使用会话机制"""
|
||||||
|
|
||||||
Args:
|
|
||||||
port_name: 串口名称
|
|
||||||
data: 接收到的数据
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
# 解析数据
|
|
||||||
data_str = data.decode('utf-8') if isinstance(data, bytes) else str(data)
|
data_str = data.decode('utf-8') if isinstance(data, bytes) else str(data)
|
||||||
logging.info(f"收到线径数据: {data_str} 来自 {port_name}")
|
logging.info(f"收到线径数据: {data_str} 来自 {port_name}")
|
||||||
|
|
||||||
# 提取线径值,格式为"线径数据: xxx"
|
# 提取线径值
|
||||||
if "线径数据:" in data_str:
|
if "线径数据:" in data_str:
|
||||||
value_str = data_str.split("线径数据:")[1].strip()
|
value_str = data_str.split("线径数据:")[1].strip()
|
||||||
try:
|
try:
|
||||||
# 转换为浮点数,除以10000并保留三位小数
|
|
||||||
xj_value = round(float(value_str)/10000, 3)
|
xj_value = round(float(value_str)/10000, 3)
|
||||||
|
|
||||||
# 更新UI显示,实时回显最新测量值
|
|
||||||
self.statusBar().showMessage(f"线径数据: {xj_value:.3f}", 2000)
|
self.statusBar().showMessage(f"线径数据: {xj_value:.3f}", 2000)
|
||||||
|
|
||||||
# 初始化线径测量历史记录(如果不存在)
|
# 查找线径对应的检验项配置和列
|
||||||
if not hasattr(self, '_diameter_measurements'):
|
|
||||||
self._diameter_measurements = []
|
|
||||||
self._diameter_measurement_count = 0
|
|
||||||
|
|
||||||
# 如果当前值不为0,添加到测量历史
|
|
||||||
if xj_value > 0:
|
|
||||||
self._diameter_measurements.append(xj_value)
|
|
||||||
self._diameter_measurement_count += 1
|
|
||||||
logging.info(f"添加线径测量值: {xj_value:.3}, 当前测量次数: {self._diameter_measurement_count}")
|
|
||||||
|
|
||||||
# 保持最多5次测量记录
|
|
||||||
if len(self._diameter_measurements) > 5:
|
|
||||||
self._diameter_measurements.pop(0)
|
|
||||||
|
|
||||||
# 实时更新到微丝产线表格中(显示为临时值)
|
|
||||||
try:
|
|
||||||
# 查找线径对应的检验项配置
|
|
||||||
xj_config = None
|
xj_config = None
|
||||||
xj_column = None
|
xj_column = None
|
||||||
enabled_configs = self.inspection_manager.get_enabled_configs()
|
enabled_configs = self.inspection_manager.get_enabled_configs()
|
||||||
|
|
||||||
# 查找线径配置和对应的列索引
|
|
||||||
for i, config in enumerate(enabled_configs):
|
for i, config in enumerate(enabled_configs):
|
||||||
if config.get('name') == 'xj' or config.get('display_name') == '线径':
|
if config.get('name') == 'xj' or config.get('display_name') == '线径':
|
||||||
xj_config = config
|
xj_config = config
|
||||||
xj_column = 2 + i # 检验列从第3列开始
|
xj_column = 2 + i
|
||||||
break
|
break
|
||||||
|
if not xj_config or xj_column is None:
|
||||||
if xj_config and xj_column is not None:
|
|
||||||
# 找到当前选中的行或第一个有效行
|
|
||||||
current_row = self.process_table.currentRow()
|
|
||||||
target_row = None
|
|
||||||
|
|
||||||
# 如果当前选中了有效行,优先使用
|
|
||||||
if current_row >= 2:
|
|
||||||
order_id_item = self.process_table.item(current_row, 1)
|
|
||||||
if order_id_item and order_id_item.text().strip():
|
|
||||||
target_row = current_row
|
|
||||||
|
|
||||||
# 如果没有选中行,查找第一个有效行
|
|
||||||
if target_row is None:
|
|
||||||
for row in range(2, self.process_table.rowCount()):
|
|
||||||
order_id_item = self.process_table.item(row, 1)
|
|
||||||
if order_id_item and order_id_item.text().strip():
|
|
||||||
target_row = row
|
|
||||||
break
|
|
||||||
|
|
||||||
# 如果找到了有效行,更新线径值
|
|
||||||
if target_row is not None:
|
|
||||||
# 暂时断开信号连接,避免触发cellChanged信号
|
|
||||||
try:
|
|
||||||
self.process_table.cellChanged.disconnect(self.handle_inspection_cell_changed)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# 创建显示项目并设置颜色
|
|
||||||
formatted_value = f"{xj_value:.3f}"
|
|
||||||
item = QTableWidgetItem(formatted_value)
|
|
||||||
item.setTextAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
# 设置单元格数据,包括配置ID
|
|
||||||
item.setData(Qt.UserRole, xj_config.get('id'))
|
|
||||||
|
|
||||||
# 设置为临时值颜色(灰色)
|
|
||||||
item.setForeground(QBrush(QColor("#666666")))
|
|
||||||
item.setToolTip(f"临时测量值 ({self._diameter_measurement_count}/5)")
|
|
||||||
|
|
||||||
# 更新表格单元格
|
|
||||||
self.process_table.setItem(target_row, xj_column, item)
|
|
||||||
|
|
||||||
# 高亮显示更新的单元格
|
|
||||||
self.process_table.setCurrentCell(target_row, xj_column)
|
|
||||||
|
|
||||||
# 重新连接单元格变更信号
|
|
||||||
self.process_table.cellChanged.connect(self.handle_inspection_cell_changed)
|
|
||||||
|
|
||||||
logging.info(f"已将线径值 {xj_value:.3f} 实时更新到表格 [行 {target_row}, 列 {xj_column}]")
|
|
||||||
else:
|
|
||||||
logging.warning("未找到线径对应的检验项配置或列索引")
|
logging.warning("未找到线径对应的检验项配置或列索引")
|
||||||
except Exception as e:
|
return
|
||||||
logging.error(f"更新线径值到表格失败: {str(e)}")
|
|
||||||
|
|
||||||
# 如果当前值为0,并且有足够的测量历史,检查是否可以保存最终值
|
# 忽略接近0的值或异常值
|
||||||
elif xj_value == 0 and len(self._diameter_measurements) >= 5:
|
if xj_value < 0.001 or xj_value > 10:
|
||||||
logging.info(f"检测到线径值变为0,使用最后一次有效值 {self._diameter_measurements[-1]:.3f} 作为最终结果")
|
logging.info(f"忽略异常线径值: {xj_value}")
|
||||||
|
return
|
||||||
|
|
||||||
# 计算测量值的稳定性
|
# 保存测量值到内部列表用于稳定性检测
|
||||||
measurements = self._diameter_measurements[-5:] # 取最后5次测量
|
# 使用类属性存储最近的测量值,用于稳定性检测
|
||||||
|
if not hasattr(self, '_diameter_measurements'):
|
||||||
|
self._diameter_measurements = []
|
||||||
|
self._diameter_measurements.append(xj_value)
|
||||||
|
if len(self._diameter_measurements) > 5:
|
||||||
|
self._diameter_measurements.pop(0)
|
||||||
|
|
||||||
|
# 显示临时值到状态栏
|
||||||
|
if len(self._diameter_measurements) < 5:
|
||||||
|
self.statusBar().showMessage(f"线径数据收集中: {xj_value:.3f} ({len(self._diameter_measurements)}/5)", 2000)
|
||||||
|
return
|
||||||
|
|
||||||
|
# 检查稳定性
|
||||||
|
measurements = self._diameter_measurements[-5:]
|
||||||
min_value = min(measurements)
|
min_value = min(measurements)
|
||||||
max_value = max(measurements)
|
max_value = max(measurements)
|
||||||
avg_value = sum(measurements) / len(measurements)
|
avg_value = sum(measurements) / len(measurements)
|
||||||
|
error_range = avg_value * 0.04 # 允许4%误差
|
||||||
|
|
||||||
# 计算误差范围(4%)
|
|
||||||
error_range = avg_value * 0.04
|
|
||||||
|
|
||||||
# 检查是否在4%误差范围内
|
|
||||||
if max_value - min_value <= error_range:
|
if max_value - min_value <= error_range:
|
||||||
final_value = measurements[-1]
|
# 数据稳定,可以保存
|
||||||
logging.info(f"连续5次测量稳定,误差范围: {min_value:.3f} - {max_value:.3f}, 平均: {avg_value:.3f}, 最终值: {final_value:.3f}")
|
final_value = avg_value # 使用平均值作为最终值
|
||||||
|
|
||||||
# 查找线径对应的检验项配置
|
# 查找第一个没有线径数据的行
|
||||||
xj_config = None
|
data_row = None
|
||||||
enabled_configs = self.inspection_manager.get_enabled_configs()
|
for row in range(2, self.process_table.rowCount()):
|
||||||
for config in enabled_configs:
|
cell_item = self.process_table.item(row, xj_column)
|
||||||
if config.get('name') == 'xj' or config.get('display_name') == '线径':
|
if not cell_item or not cell_item.text().strip() or cell_item.text().strip() == '0':
|
||||||
xj_config = config
|
data_row = row
|
||||||
break
|
break
|
||||||
|
|
||||||
if xj_config:
|
# 如果没找到空行,使用当前选中行或第一个数据行
|
||||||
|
if data_row is None:
|
||||||
|
current_row = self.process_table.currentRow()
|
||||||
|
data_row = current_row if current_row >= 2 else 2
|
||||||
|
logging.info(f"未找到没有线径数据的行,使用当前选中行或第一个数据行: {data_row}")
|
||||||
|
else:
|
||||||
|
logging.info(f"找到没有线径数据的行: {data_row}")
|
||||||
|
|
||||||
|
# 获取工程号
|
||||||
|
gc_note_item = self.process_table.item(data_row, 1)
|
||||||
|
if not gc_note_item:
|
||||||
|
logging.warning("无法获取工程号")
|
||||||
|
return
|
||||||
|
|
||||||
|
gc_note = gc_note_item.text().strip()
|
||||||
|
if not gc_note:
|
||||||
|
logging.warning("工程号为空")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 获取托盘号
|
||||||
|
tray_id = self.tray_edit.currentText()
|
||||||
|
|
||||||
|
# 公差校验
|
||||||
from dao.inspection_dao import InspectionDAO
|
from dao.inspection_dao import InspectionDAO
|
||||||
inspection_dao = InspectionDAO()
|
inspection_dao = InspectionDAO()
|
||||||
bccd, tccd = inspection_dao.get_xj_range(self._current_order_code)
|
bccd, tccd = inspection_dao.get_xj_range(self._current_order_code)
|
||||||
|
|
||||||
if bccd is not None and tccd is not None:
|
if bccd is not None and tccd is not None:
|
||||||
if bccd - 0.5 <= final_value <= tccd + 0.5: # 允许±0.5的误差范围
|
if bccd - 0.5 <= final_value <= tccd + 0.5:
|
||||||
|
# 使用set_inspection_value保存数据
|
||||||
self.set_inspection_value('xj', xj_config, final_value)
|
self.set_inspection_value('xj', xj_config, final_value)
|
||||||
|
logging.info(f"已将稳定的线径值 {final_value:.3f} 保存到工程号 {gc_note} (行 {data_row})")
|
||||||
else:
|
else:
|
||||||
logging.warning(f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd}),误差超过±0.5")
|
|
||||||
reply = QMessageBox.question(
|
reply = QMessageBox.question(
|
||||||
self,
|
self,
|
||||||
'确认保存',
|
'确认保存',
|
||||||
@ -2868,19 +2825,21 @@ class MainWindow(MainWindowUI):
|
|||||||
)
|
)
|
||||||
if reply == QMessageBox.Yes:
|
if reply == QMessageBox.Yes:
|
||||||
self.set_inspection_value('xj', xj_config, final_value)
|
self.set_inspection_value('xj', xj_config, final_value)
|
||||||
|
logging.info(f"已将超出公差范围的线径值 {final_value:.3f} 保存到工程号 {gc_note} (行 {data_row})")
|
||||||
else:
|
else:
|
||||||
logging.info(f"用户取消保存超出范围的线径值: {final_value:.3f}")
|
logging.info(f"用户取消保存超出范围的线径值: {final_value:.3f}")
|
||||||
else:
|
else:
|
||||||
logging.info(f"未找到订单 {self._current_order_code} 的线径公差范围,直接保存值 {final_value:.3f}")
|
# 无公差范围,直接保存
|
||||||
self.set_inspection_value('xj', xj_config, final_value)
|
self.set_inspection_value('xj', xj_config, final_value)
|
||||||
else:
|
logging.info(f"已将线径值 {final_value:.3f} 保存到工程号 {gc_note} (行 {data_row})")
|
||||||
logging.warning("未找到线径对应的检验项配置")
|
|
||||||
else:
|
|
||||||
logging.warning(f"连续5次测量,误差范围: {min_value:.3f} - {max_value:.3f}, 平均: {avg_value:.3f}, 超出4%误差范围")
|
|
||||||
|
|
||||||
# 重置测量历史
|
# 重置测量列表,准备下一次测量
|
||||||
self._diameter_measurements = []
|
self._diameter_measurements = []
|
||||||
self._diameter_measurement_count = 0
|
self.statusBar().showMessage(f"线径数据已保存: {final_value:.3f}", 2000)
|
||||||
|
else:
|
||||||
|
# 数据不稳定,继续收集
|
||||||
|
self.statusBar().showMessage(f"线径数据不稳定: {min_value:.3f} - {max_value:.3f}, 继续测量", 2000)
|
||||||
|
logging.warning(f"线径测量数据不稳定,范围: {min_value:.3f} - {max_value:.3f}, 平均值: {avg_value:.3f}")
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
logging.warning(f"线径数据格式错误: {value_str}")
|
logging.warning(f"线径数据格式错误: {value_str}")
|
||||||
@ -2889,6 +2848,34 @@ class MainWindow(MainWindowUI):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"处理线径数据失败: {str(e)}")
|
logging.error(f"处理线径数据失败: {str(e)}")
|
||||||
|
|
||||||
|
def _save_diameter_to_order(self, order_id, config, value):
|
||||||
|
"""基于工程号保存线径值,确保即使行号变化也能保存到正确的产品"""
|
||||||
|
try:
|
||||||
|
# 查找工程号对应的行
|
||||||
|
target_row = None
|
||||||
|
for row in range(2, self.process_table.rowCount()):
|
||||||
|
order_id_item = self.process_table.item(row, 1)
|
||||||
|
if order_id_item and order_id_item.text().strip() == order_id:
|
||||||
|
target_row = row
|
||||||
|
break
|
||||||
|
|
||||||
|
if target_row is not None:
|
||||||
|
# 使用set_inspection_value保存数据
|
||||||
|
self.set_inspection_value('xj', config, value)
|
||||||
|
logging.info(f"已将线径值 {value:.3f} 保存到工程号 {order_id} (行 {target_row})")
|
||||||
|
else:
|
||||||
|
logging.warning(f"找不到工程号 {order_id} 对应的行,无法保存线径值")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"保存线径值到工程号失败: {str(e)}")
|
||||||
|
|
||||||
|
def _reset_diameter_session(self):
|
||||||
|
"""重置线径测量会话状态"""
|
||||||
|
self._diameter_session_active = False
|
||||||
|
self._diameter_session_target_row = None
|
||||||
|
self._diameter_session_order_id = None
|
||||||
|
self._diameter_session_measurements = []
|
||||||
|
self._diameter_session_start_time = 0
|
||||||
|
|
||||||
def on_scanner_data_received(self, port_name, data):
|
def on_scanner_data_received(self, port_name, data):
|
||||||
"""扫码器数据接收回调函数
|
"""扫码器数据接收回调函数
|
||||||
|
|
||||||
@ -2977,8 +2964,28 @@ class MainWindow(MainWindowUI):
|
|||||||
logging.warning("无法添加新行,订单号为空")
|
logging.warning("无法添加新行,订单号为空")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 查找第一个没有该检测数据的行
|
# 对于线径数据,如果有活跃会话,优先使用会话锁定的工程号
|
||||||
|
if data_type == 'xj' and hasattr(self, '_diameter_session_active') and self._diameter_session_active and self._diameter_session_order_id:
|
||||||
|
# 查找会话工程号对应的行
|
||||||
data_row = None
|
data_row = None
|
||||||
|
for row in range(2, self.process_table.rowCount()):
|
||||||
|
order_id_item = self.process_table.item(row, 1)
|
||||||
|
if order_id_item and order_id_item.text().strip() == self._diameter_session_order_id:
|
||||||
|
data_row = row
|
||||||
|
break
|
||||||
|
|
||||||
|
if data_row is not None:
|
||||||
|
logging.info(f"使用线径会话锁定的工程号 {self._diameter_session_order_id} 对应的行 {data_row}")
|
||||||
|
else:
|
||||||
|
logging.warning(f"找不到线径会话锁定的工程号 {self._diameter_session_order_id} 对应的行,将使用默认行选择逻辑")
|
||||||
|
# 继续使用默认逻辑
|
||||||
|
data_row = None
|
||||||
|
else:
|
||||||
|
# 默认行选择逻辑
|
||||||
|
data_row = None
|
||||||
|
|
||||||
|
# 如果没有找到特定行,使用默认逻辑查找第一个没有该检测数据的行
|
||||||
|
if data_row is None:
|
||||||
for row in range(2, self.process_table.rowCount()):
|
for row in range(2, self.process_table.rowCount()):
|
||||||
cell_item = self.process_table.item(row, col_index)
|
cell_item = self.process_table.item(row, col_index)
|
||||||
if not cell_item or not cell_item.text().strip() or (data_type == 'xj' and cell_item.text().strip() == '0'):
|
if not cell_item or not cell_item.text().strip() or (data_type == 'xj' and cell_item.text().strip() == '0'):
|
||||||
@ -3039,13 +3046,13 @@ class MainWindow(MainWindowUI):
|
|||||||
# 保存到数据库,但只在非加载状态下
|
# 保存到数据库,但只在非加载状态下
|
||||||
if not self._loading_data_in_progress:
|
if not self._loading_data_in_progress:
|
||||||
tray_id = self.tray_edit.currentText()
|
tray_id = self.tray_edit.currentText()
|
||||||
self.save_inspection_data(order_id, tray_id, config_position, config_id, formatted_value, status)
|
self.save_inspection_data(self._current_order_code, order_id, tray_id, config_position, config_id, formatted_value, status)
|
||||||
# 不需要在这里主动触发数据重新加载,因为handle_inspection_cell_changed会处理
|
# 不需要在这里主动触发数据重新加载,因为handle_inspection_cell_changed会处理
|
||||||
|
|
||||||
# 重新连接信号
|
# 重新连接信号
|
||||||
self.process_table.cellChanged.connect(self.handle_inspection_cell_changed)
|
self.process_table.cellChanged.connect(self.handle_inspection_cell_changed)
|
||||||
|
|
||||||
logging.info(f"已将{data_type}数据 {formatted_value} 写入行 {data_row}, 列 {col_index}")
|
logging.info(f"已将{data_type}数据 {formatted_value} 写入工程号 {order_id} (行 {data_row}, 列 {col_index})")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"设置检验项值失败: {str(e)}")
|
logging.error(f"设置检验项值失败: {str(e)}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user