From a8c4a929ff98acdc354fde4f6b032c2c3f96ea68 Mon Sep 17 00:00:00 2001 From: zhu-mengmeng <15588200382@163.com> Date: Thu, 17 Jul 2025 11:01:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E6=96=B0=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E4=BB=A5=E5=90=AF=E7=94=A8=E7=94=B5=E5=8A=9B?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=90=AF=E5=8A=A8=EF=BC=9B=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E7=BA=BF=E5=BE=84=E6=95=B0=E6=8D=AE=E5=A4=84=E7=90=86=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=A2=9E=E5=8A=A0=E6=B5=8B=E9=87=8F=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E8=AE=B0=E5=BD=95=E5=92=8C=E7=A8=B3=E5=AE=9A=E6=80=A7?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/app_config.json | 2 +- utils/serial_manager.py | 43 ++++---- widgets/main_window.py | 238 ++++++++++++++++++++++------------------ 3 files changed, 157 insertions(+), 126 deletions(-) diff --git a/config/app_config.json b/config/app_config.json index 27e282e..921f301 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -116,7 +116,7 @@ } }, "electricity": { - "auto_start": false, + "auto_start": true, "interval_minutes": 30 } } \ No newline at end of file diff --git a/utils/serial_manager.py b/utils/serial_manager.py index d5289cc..8bd781b 100644 --- a/utils/serial_manager.py +++ b/utils/serial_manager.py @@ -1160,27 +1160,32 @@ class SerialManager: # 转换为浮点数 xj_value = float(number_str) logging.info(f"线径数据: {xj_value}") + if xj_value/10000 > 10 or xj_value/10000 == 0: + # 过滤无效值:>10 或 =0 的值直接跳过 + # if xj_value/10000 > 10 or xj_value/10000 == 0: + # logging.info(f"过滤无效线径值: {xj_value} (超出有效范围或为零)") + # return False # 更新数据 - self.data['xj'] = xj_value - self._write_data_to_file() - - # 构建MainWindow.on_diameter_data_received期望的格式 - callback_data_str = f"线径数据: {xj_value}" - if 'xj_data' in self.callbacks: - try: - # 与米电阻类似,传递实际的串口名称 - logging.info(f"线径回调开始调用,回调对象: {self.callbacks['xj_data'].__self__.__class__.__name__}, 数据: {xj_value}") - self.callbacks['xj_data'](port_name, callback_data_str.encode('utf-8')) - logging.info(f"通知 'xj_data' 回调成功. 值: {xj_value}, 串口: {port_name}") - except Exception as e: - logging.error(f"调用 'xj_data' 回调失败: {e}") - else: - # 如果未注册回调,仍然使用通用方法通知 - logging.warning(f"未找到xj_data回调,使用通用_notify_callbacks方法") - self._notify_callbacks('xj_data', {"type": "xj", "value": self.data['xj'], "source": f"serial ({port_name})"}) - - return True + self.data['xj'] = xj_value + self._write_data_to_file() + + # 构建MainWindow.on_diameter_data_received期望的格式 + callback_data_str = f"线径数据: {xj_value}" + if 'xj_data' in self.callbacks: + try: + # 与米电阻类似,传递实际的串口名称 + logging.info(f"线径回调开始调用,回调对象: {self.callbacks['xj_data'].__self__.__class__.__name__}, 数据: {xj_value}") + self.callbacks['xj_data'](port_name, callback_data_str.encode('utf-8')) + logging.info(f"通知 'xj_data' 回调成功. 值: {xj_value}, 串口: {port_name}") + except Exception as e: + logging.error(f"调用 'xj_data' 回调失败: {e}") + else: + # 如果未注册回调,仍然使用通用方法通知 + logging.warning(f"未找到xj_data回调,使用通用_notify_callbacks方法") + self._notify_callbacks('xj_data', {"type": "xj", "value": self.data['xj'], "source": f"serial ({port_name})"}) + + return True except ValueError: logging.warning(f"线径数据字符串 '{number_str}' 无法转换为浮点数") else: diff --git a/widgets/main_window.py b/widgets/main_window.py index 3329fd2..f8b87c0 100644 --- a/widgets/main_window.py +++ b/widgets/main_window.py @@ -2732,122 +2732,148 @@ class MainWindow(MainWindowUI): # 更新UI显示,实时回显最新测量值 self.statusBar().showMessage(f"线径数据: {xj_value:.3f}", 2000) - # 实时更新到微丝产线表格中 - try: - # 查找线径对应的检验项配置 - xj_config = None - xj_column = None - enabled_configs = self.inspection_manager.get_enabled_configs() - - # 查找线径配置和对应的列索引 - for i, config in enumerate(enabled_configs): - if config.get('name') == 'xj' or config.get('display_name') == '线径': - xj_config = config - xj_column = 2 + i # 检验列从第3列开始 - break - - 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')) - - # 如果当前值不为0,设置为临时值颜色(灰色) - if xj_value > 0: - item.setForeground(QBrush(QColor("#666666"))) - item.setToolTip("临时测量值,产品取走后将保存最终值") - - # 更新表格单元格 - 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("未找到线径对应的检验项配置或列索引") - except Exception as e: - logging.error(f"更新线径值到表格失败: {str(e)}") + # 初始化线径测量历史记录(如果不存在) + if not hasattr(self, '_diameter_measurements'): + self._diameter_measurements = [] + self._diameter_measurement_count = 0 - # 如果当前值不为0,记录为最后一次有效值 + # 如果当前值不为0,添加到测量历史 if xj_value > 0: - self._last_diameter_value = xj_value - logging.info(f"更新最后一次有效线径值: {xj_value:.3f}") + 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_column = None + enabled_configs = self.inspection_manager.get_enabled_configs() + + # 查找线径配置和对应的列索引 + for i, config in enumerate(enabled_configs): + if config.get('name') == 'xj' or config.get('display_name') == '线径': + xj_config = config + xj_column = 2 + i # 检验列从第3列开始 + break + + 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("未找到线径对应的检验项配置或列索引") + except Exception as e: + logging.error(f"更新线径值到表格失败: {str(e)}") - # 如果当前值为0,并且之前有非零值,说明产品已拿开,保存最后一次有效值 - elif xj_value == 0 and hasattr(self, '_last_diameter_value') and self._last_diameter_value > 0: - final_value = self._last_diameter_value - logging.info(f"检测到线径值变为0,使用最后一次有效值 {final_value:.3f} 作为最终结果") + # 如果当前值为0,并且有足够的测量历史,检查是否可以保存最终值 + elif xj_value == 0 and len(self._diameter_measurements) >= 5: + logging.info(f"检测到线径值变为0,使用最后一次有效值 {self._diameter_measurements[-1]:.3f} 作为最终结果") - # 查找线径对应的检验项配置 - xj_config = None - enabled_configs = self.inspection_manager.get_enabled_configs() - for config in enabled_configs: - if config.get('name') == 'xj' or config.get('display_name') == '线径': - xj_config = config - break + # 计算测量值的稳定性 + measurements = self._diameter_measurements[-5:] # 取最后5次测量 + min_value = min(measurements) + max_value = max(measurements) + avg_value = sum(measurements) / len(measurements) - if xj_config: - from dao.inspection_dao import InspectionDAO - inspection_dao = InspectionDAO() - bccd, tccd = inspection_dao.get_xj_range(self._current_order_code) + # 计算误差范围(4%) + error_range = avg_value * 0.04 + + # 检查是否在4%误差范围内 + 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}") + + # 查找线径对应的检验项配置 + xj_config = None + enabled_configs = self.inspection_manager.get_enabled_configs() + for config in enabled_configs: + if config.get('name') == 'xj' or config.get('display_name') == '线径': + xj_config = config + break + + if xj_config: + from dao.inspection_dao import InspectionDAO + inspection_dao = InspectionDAO() + bccd, tccd = inspection_dao.get_xj_range(self._current_order_code) - if bccd is not None and tccd is not None: - if bccd - 0.5 <= final_value <= tccd + 0.5: # 允许±0.5的误差范围 - self.set_inspection_value('xj', xj_config, final_value) - else: - logging.warning(f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd}),误差超过±0.5") - reply = QMessageBox.question( - self, - '确认保存', - f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd}),\n是否继续保存?", - QMessageBox.Yes | QMessageBox.No, - QMessageBox.No - ) - if reply == QMessageBox.Yes: + if bccd is not None and tccd is not None: + if bccd - 0.5 <= final_value <= tccd + 0.5: # 允许±0.5的误差范围 self.set_inspection_value('xj', xj_config, final_value) else: - logging.info(f"用户取消保存超出范围的线径值: {final_value:.3f}") + logging.warning(f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd}),误差超过±0.5") + reply = QMessageBox.question( + self, + '确认保存', + f"线径 {final_value:.3f} 不在公差范围内 ({bccd} - {tccd}),\n是否继续保存?", + QMessageBox.Yes | QMessageBox.No, + QMessageBox.No + ) + if reply == QMessageBox.Yes: + self.set_inspection_value('xj', xj_config, final_value) + else: + logging.info(f"用户取消保存超出范围的线径值: {final_value:.3f}") + else: + logging.info(f"未找到订单 {self._current_order_code} 的线径公差范围,直接保存值 {final_value:.3f}") + self.set_inspection_value('xj', xj_config, final_value) else: - logging.info(f"未找到订单 {self._current_order_code} 的线径公差范围,直接保存值 {final_value:.3f}") - self.set_inspection_value('xj', xj_config, final_value) - - # 重置最后一次有效值,避免重复处理 - self._last_diameter_value = 0 + logging.warning("未找到线径对应的检验项配置") else: - logging.warning("未找到线径对应的检验项配置") + logging.warning(f"连续5次测量,误差范围: {min_value:.3f} - {max_value:.3f}, 平均: {avg_value:.3f}, 超出4%误差范围") + + # 重置测量历史 + self._diameter_measurements = [] + self._diameter_measurement_count = 0 + except ValueError: logging.warning(f"线径数据格式错误: {value_str}") else: