feat: 新增急停信号
This commit is contained in:
parent
6d60e77743
commit
92905294aa
@ -49,8 +49,8 @@
|
||||
"default_framerate": 30
|
||||
},
|
||||
"modbus": {
|
||||
"host": "localhost",
|
||||
"port": "5020"
|
||||
"host": "192.168.2.88",
|
||||
"port": "502"
|
||||
},
|
||||
"serial": {
|
||||
"keyboard": {
|
||||
|
||||
BIN
db/jtDB.db
BIN
db/jtDB.db
Binary file not shown.
@ -16,6 +16,6 @@ client.write_registers(address=3, values=[0])
|
||||
# client.write_registers(address=13, values=[1])
|
||||
|
||||
|
||||
result = client.read_holding_registers(address=3, count=1)
|
||||
result = client.read_holding_registers(address=109, count=1)
|
||||
print(result.registers[0],"123===")
|
||||
client.close()
|
||||
@ -77,7 +77,7 @@ class ModbusMonitor(QObject):
|
||||
def _initialize_registers(self):
|
||||
"""初始化要监控的寄存器列表"""
|
||||
# 默认监控的寄存器地址
|
||||
register_addresses = [5, 6, 11, 13, 20, 21, 22, 23, 24, 30] # 添加寄存器30用于电力监控
|
||||
register_addresses = [5, 6, 11, 13, 20, 21, 22, 23, 24, 25, 30]
|
||||
for address in register_addresses:
|
||||
self.registers[address] = RegisterValue(address)
|
||||
|
||||
|
||||
@ -243,4 +243,23 @@ class NGHandler(RegisterHandler):
|
||||
|
||||
#如果有回调函数,则调用
|
||||
if self.callback:
|
||||
self.callback(value)
|
||||
self.callback(value)
|
||||
|
||||
|
||||
class EmergencyStopHandler(RegisterHandler):
|
||||
"""寄存器D25处理器,处理急停信号"""
|
||||
def __init__(self, callback=None):
|
||||
super().__init__()
|
||||
self.callback = callback
|
||||
self.status_map = {
|
||||
0: "正常",
|
||||
1: "急停触发"
|
||||
}
|
||||
|
||||
def handle_change(self, value):
|
||||
status = self.status_map.get(value, f"未知状态({value})")
|
||||
logging.info(f"急停信号: {status}")
|
||||
|
||||
# 如果有回调函数,则调用
|
||||
if self.callback and value == 1:
|
||||
self.callback(value, "监听到急停信号")
|
||||
@ -19,7 +19,8 @@ from utils.register_handlers import (
|
||||
Error2Handler,
|
||||
Error3Handler,
|
||||
UnloadingLevelHandler,
|
||||
UnloadingPositionHandler
|
||||
UnloadingPositionHandler,
|
||||
EmergencyStopHandler
|
||||
)
|
||||
from utils.electricity_monitor import ElectricityHandler
|
||||
# 导入PySide6
|
||||
@ -53,6 +54,7 @@ class MainWindow(MainWindowUI):
|
||||
unloading_feedback_signal = Signal(str, str) # 参数:status_type, desc
|
||||
unloading_level_ui_signal = Signal(int) # 用于在主线程中更新下料层数UI
|
||||
unloading_position_ui_signal = Signal(int) # 用于在主线程中更新下料位置UI
|
||||
emergency_stop_signal = Signal(int, str) # 用于在主线程中处理急停信号
|
||||
|
||||
def __init__(self, user_id=None, user_name=None, corp_name=None, corp_id=None):
|
||||
"""初始化主窗口"""
|
||||
@ -75,12 +77,7 @@ class MainWindow(MainWindowUI):
|
||||
self._loading_info = None # 存储上料对话框的信息
|
||||
self._is_loading_active = False # 标识上料任务是否正在进行
|
||||
|
||||
# 连接信号到槽
|
||||
self.loading_feedback_signal.connect(self._handle_loading_feedback_ui)
|
||||
self.unloading_feedback_signal.connect(self._handle_unloading_feedback_ui)
|
||||
# 连接新增的信号
|
||||
self.unloading_level_ui_signal.connect(self.handle_unloading_level_ui)
|
||||
self.unloading_position_ui_signal.connect(self.handle_unloading_position_ui)
|
||||
# 信号的连接在connect_signals方法中统一处理,不在这里连接
|
||||
|
||||
# 称重相关变量
|
||||
self._current_weight = None # 当前称重值(千克)
|
||||
@ -109,17 +106,12 @@ class MainWindow(MainWindowUI):
|
||||
self.output_form_layout = QFormLayout()
|
||||
self.output_content_layout.addLayout(self.output_form_layout)
|
||||
|
||||
# 只有在相机启用时创建相机显示组件
|
||||
if self.camera_enabled:
|
||||
# 创建相机显示组件并添加到上料区
|
||||
self.camera_display = CameraDisplayWidget()
|
||||
self.material_content_layout.addWidget(self.camera_display)
|
||||
else:
|
||||
# 在上料区添加占位标签
|
||||
self.material_placeholder = QLabel("相机功能已禁用")
|
||||
self.material_placeholder.setAlignment(Qt.AlignCenter)
|
||||
self.material_placeholder.setStyleSheet("color: #888888; background-color: #f0f0f0;")
|
||||
self.material_content_layout.addWidget(self.material_placeholder)
|
||||
# 创建相机显示组件和占位标签
|
||||
self.camera_display = None
|
||||
self.material_placeholder = None
|
||||
|
||||
# 初始化上料区显示
|
||||
self.init_camera_display()
|
||||
|
||||
# 为下料区添加占位标签,确保它保持为空
|
||||
self.output_placeholder = QWidget()
|
||||
@ -266,6 +258,19 @@ class MainWindow(MainWindowUI):
|
||||
|
||||
# 连接报表按钮点击事件
|
||||
self.report_button.clicked.connect(self.on_report)
|
||||
|
||||
# 连接加载反馈信号
|
||||
self.loading_feedback_signal.connect(self._handle_loading_feedback_ui)
|
||||
|
||||
# 连接下料反馈信号
|
||||
self.unloading_feedback_signal.connect(self._handle_unloading_feedback_ui)
|
||||
|
||||
# 连接下料层数和位置UI更新信号
|
||||
self.unloading_level_ui_signal.connect(self.handle_unloading_level_ui)
|
||||
self.unloading_position_ui_signal.connect(self.handle_unloading_position_ui)
|
||||
|
||||
# 连接急停信号
|
||||
self.emergency_stop_signal.connect(self._handle_emergency_stop_ui)
|
||||
|
||||
def update_inspection_columns(self):
|
||||
"""更新检验列配置 - 使用检验配置管理器获取启用的列数和标题"""
|
||||
@ -300,12 +305,25 @@ class MainWindow(MainWindowUI):
|
||||
# 加载未完成的检验数据
|
||||
self._safe_load_data()
|
||||
|
||||
# 只有在相机启用时处理相机显示
|
||||
if self.camera_enabled and hasattr(self, 'camera_display'):
|
||||
# 如果相机已连接,直接开始显示相机画面
|
||||
if self.camera_display.camera_manager.isOpen:
|
||||
if not self.camera_display.camera_manager.isGrabbing:
|
||||
self.camera_display.start_display()
|
||||
# 处理相机显示
|
||||
if self.camera_enabled and self.camera_display:
|
||||
from widgets.camera_manager import CameraManager
|
||||
camera_manager = CameraManager.get_instance()
|
||||
|
||||
# 检查相机是否已打开
|
||||
if camera_manager.isOpen:
|
||||
# 更新UI显示相机画面
|
||||
self.update_camera_ui(True)
|
||||
|
||||
# 如果相机未在采集,则开始采集
|
||||
if not camera_manager.isGrabbing:
|
||||
# 使用内部方法启动相机显示
|
||||
QTimer.singleShot(100, self._start_camera_display)
|
||||
logging.info("主页面显示:启动相机显示")
|
||||
else:
|
||||
# 如果相机未打开,尝试重新初始化
|
||||
QTimer.singleShot(100, self.initialize_camera)
|
||||
logging.info("主页面显示:尝试初始化相机")
|
||||
|
||||
# 加载托盘号列表
|
||||
self.load_pallet_codes()
|
||||
@ -660,8 +678,13 @@ class MainWindow(MainWindowUI):
|
||||
"""处理相机状态变化"""
|
||||
if is_connected:
|
||||
logging.info("相机已连接并显示")
|
||||
self.update_camera_ui(True)
|
||||
else:
|
||||
logging.warning(f"相机显示问题: {message}")
|
||||
# 更新占位符文本
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setText(f"相机错误: {message}" if message else "相机未连接")
|
||||
self.update_camera_ui(False)
|
||||
|
||||
def handle_camera_connection(self, is_connected, message):
|
||||
"""处理相机连接状态变化"""
|
||||
@ -695,10 +718,20 @@ class MainWindow(MainWindowUI):
|
||||
logging.info("停止Modbus监控")
|
||||
self.modbus_monitor.stop()
|
||||
|
||||
# 只有在相机启用时处理相机关闭
|
||||
if self.camera_enabled and hasattr(self, 'camera_display'):
|
||||
# 处理相机关闭
|
||||
if self.camera_enabled and self.camera_display:
|
||||
# 停止相机显示
|
||||
self.camera_display.stop_display()
|
||||
|
||||
# 关闭相机设备
|
||||
try:
|
||||
from widgets.camera_manager import CameraManager
|
||||
camera_manager = CameraManager.get_instance()
|
||||
if camera_manager.isOpen:
|
||||
camera_manager.close_device()
|
||||
logging.info("相机设备已关闭")
|
||||
except Exception as e:
|
||||
logging.error(f"关闭相机设备失败: {str(e)}")
|
||||
|
||||
# 停止串口监听
|
||||
self.serial_manager.stop_keyboard_listener()
|
||||
@ -1637,6 +1670,9 @@ class MainWindow(MainWindowUI):
|
||||
monitor.register_handler(23, Error2Handler(self.machine_handlers.handle_error_2))
|
||||
monitor.register_handler(24, Error3Handler(self.machine_handlers.handle_error_3))
|
||||
|
||||
# 注册急停信号处理器
|
||||
monitor.register_handler(25, EmergencyStopHandler(self.handle_emergency_stop))
|
||||
|
||||
# 注册下料层数和位置处理器
|
||||
monitor.register_handler(4, UnloadingLevelHandler(self.handle_unloading_level))
|
||||
monitor.register_handler(5, UnloadingPositionHandler(self.handle_unloading_position))
|
||||
@ -2188,8 +2224,7 @@ class MainWindow(MainWindowUI):
|
||||
# 如果有故障,显示提示
|
||||
if error_code in (2, 3):
|
||||
QMessageBox.warning(self, "机器人视觉报警", f"机器人视觉报警: {detailed_desc}")
|
||||
# error_1 属于上料故障
|
||||
self.show_operation_status("异常", "", detailed_desc)
|
||||
# 移除在下料区域显示异常信息的代码
|
||||
|
||||
|
||||
@Slot(int, str)
|
||||
@ -2204,9 +2239,8 @@ class MainWindow(MainWindowUI):
|
||||
self._update_error_status()
|
||||
|
||||
# 如果有故障,显示提示
|
||||
if error_code > 0:
|
||||
# error_2 属于下料故障
|
||||
self.show_operation_status("异常", "", detailed_desc)
|
||||
# 移除在下料区域显示异常信息的代码
|
||||
|
||||
@Slot(int, str)
|
||||
def handle_error_3(self, error_code, error_desc):
|
||||
"""拆码垛报警"""
|
||||
@ -2224,11 +2258,11 @@ class MainWindow(MainWindowUI):
|
||||
QMessageBox.warning(self, "异常", f"异常: {detailed_desc}")
|
||||
modbus.write_register_until_success(client, 2, 0)
|
||||
modbus.close_client(client)
|
||||
self.show_operation_status("异常", "", detailed_desc)
|
||||
# 移除在下料区域显示异常信息的代码
|
||||
elif error_code == 2:
|
||||
QMessageBox.warning(self, "异常", f"异常: {detailed_desc}")
|
||||
modbus.write_register_until_success(client, 3, 0)
|
||||
modbus.close_client(client)
|
||||
modbus.close_client(client)
|
||||
@Slot(int)
|
||||
def handle_unloading_level(self, level):
|
||||
"""处理下料层数信息(来自Modbus)"""
|
||||
@ -2661,4 +2695,200 @@ class MainWindow(MainWindowUI):
|
||||
dialog.exec_()
|
||||
except Exception as e:
|
||||
logging.error(f"打开报表对话框失败: {str(e)}")
|
||||
QMessageBox.warning(self, "错误", f"打开报表对话框失败: {str(e)}")
|
||||
QMessageBox.warning(self, "错误", f"打开报表对话框失败: {str(e)}")
|
||||
|
||||
def init_camera_display(self):
|
||||
"""初始化相机显示区域"""
|
||||
try:
|
||||
# 清理之前的组件(如果有)
|
||||
if self.camera_display:
|
||||
self.material_content_layout.removeWidget(self.camera_display)
|
||||
self.camera_display.deleteLater()
|
||||
self.camera_display = None
|
||||
|
||||
if self.material_placeholder:
|
||||
self.material_content_layout.removeWidget(self.material_placeholder)
|
||||
self.material_placeholder.deleteLater()
|
||||
self.material_placeholder = None
|
||||
|
||||
# 清空布局中的所有项目
|
||||
while self.material_content_layout.count():
|
||||
item = self.material_content_layout.takeAt(0)
|
||||
if item.widget():
|
||||
item.widget().deleteLater()
|
||||
|
||||
# 创建占位标签
|
||||
self.material_placeholder = QLabel("相机初始化中..." if self.camera_enabled else "相机功能已禁用")
|
||||
self.material_placeholder.setAlignment(Qt.AlignCenter)
|
||||
self.material_placeholder.setStyleSheet("color: #888888; background-color: #f0f0f0;")
|
||||
self.material_content_layout.addWidget(self.material_placeholder)
|
||||
|
||||
# 创建相机显示组件
|
||||
self.camera_display = CameraDisplayWidget()
|
||||
self.camera_display.signal_camera_status.connect(self.handle_camera_status)
|
||||
|
||||
# 先隐藏相机组件,直到确认相机可用
|
||||
self.material_content_layout.addWidget(self.camera_display)
|
||||
self.camera_display.hide()
|
||||
|
||||
# 如果相机功能已启用,尝试初始化相机
|
||||
if self.camera_enabled:
|
||||
# 启动相机初始化过程
|
||||
QTimer.singleShot(500, self.initialize_camera)
|
||||
logging.info("相机初始化已安排")
|
||||
else:
|
||||
logging.info("相机功能已禁用,不进行初始化")
|
||||
self.material_placeholder.show()
|
||||
self.camera_display.hide()
|
||||
except Exception as e:
|
||||
logging.error(f"初始化相机显示区域失败: {str(e)}")
|
||||
|
||||
def initialize_camera(self):
|
||||
"""初始化相机并显示画面"""
|
||||
try:
|
||||
if not self.camera_enabled:
|
||||
return
|
||||
|
||||
logging.info("开始初始化相机...")
|
||||
|
||||
# 获取相机管理器实例
|
||||
from widgets.camera_manager import CameraManager
|
||||
camera_manager = CameraManager.get_instance()
|
||||
|
||||
# 枚举设备
|
||||
devices = camera_manager.enum_devices()
|
||||
if not devices or len(devices) == 0:
|
||||
self.material_placeholder.setText("未检测到相机设备")
|
||||
logging.warning("未检测到相机设备")
|
||||
return
|
||||
|
||||
# 打开第一个相机设备
|
||||
device_index = 0
|
||||
success = camera_manager.open_device(device_index)
|
||||
|
||||
if success:
|
||||
logging.info(f"相机已成功打开,设备索引: {device_index}")
|
||||
# 更新UI
|
||||
self.update_camera_ui(True)
|
||||
|
||||
# 立即开始显示相机画面
|
||||
QTimer.singleShot(100, lambda: self._start_camera_display())
|
||||
else:
|
||||
self.material_placeholder.setText("相机打开失败")
|
||||
logging.error("相机打开失败")
|
||||
|
||||
except Exception as e:
|
||||
self.material_placeholder.setText("相机初始化错误")
|
||||
logging.error(f"初始化相机失败: {str(e)}")
|
||||
|
||||
def _start_camera_display(self):
|
||||
"""开始显示相机画面(内部方法)"""
|
||||
try:
|
||||
if self.camera_display and self.camera_enabled:
|
||||
# 确保相机组件可见
|
||||
self.camera_display.setVisible(True)
|
||||
self.camera_display.raise_()
|
||||
|
||||
# 开始显示
|
||||
success = self.camera_display.start_display()
|
||||
|
||||
if success:
|
||||
# 确保占位符隐藏
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setVisible(False)
|
||||
logging.info("相机显示已成功启动")
|
||||
else:
|
||||
# 如果启动失败,显示占位符
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setText("相机显示启动失败")
|
||||
self.material_placeholder.setVisible(True)
|
||||
logging.error("相机显示启动失败")
|
||||
except Exception as e:
|
||||
logging.error(f"启动相机显示失败: {str(e)}")
|
||||
|
||||
def update_camera_ui(self, is_camera_ready):
|
||||
"""更新相机UI显示
|
||||
|
||||
Args:
|
||||
is_camera_ready: 相机是否准备就绪
|
||||
"""
|
||||
try:
|
||||
if is_camera_ready and self.camera_enabled:
|
||||
# 显示相机画面,隐藏占位符
|
||||
if self.camera_display:
|
||||
self.camera_display.setVisible(True)
|
||||
self.camera_display.raise_() # 确保相机组件在最上层
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setVisible(False)
|
||||
logging.info("相机UI已更新:显示相机画面")
|
||||
else:
|
||||
# 隐藏相机画面,显示占位符
|
||||
if self.camera_display:
|
||||
self.camera_display.setVisible(False)
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setVisible(True)
|
||||
self.material_placeholder.raise_() # 确保占位符在最上层
|
||||
if not self.camera_enabled:
|
||||
self.material_placeholder.setText("相机功能已禁用")
|
||||
elif not is_camera_ready:
|
||||
self.material_placeholder.setText("相机未就绪")
|
||||
logging.info(f"相机UI已更新:显示占位符 (相机启用={self.camera_enabled}, 相机就绪={is_camera_ready})")
|
||||
except Exception as e:
|
||||
logging.error(f"更新相机UI失败: {str(e)}")
|
||||
|
||||
def handle_camera_status(self, is_connected, message):
|
||||
"""处理相机状态变化"""
|
||||
if is_connected:
|
||||
logging.info("相机已连接并显示")
|
||||
self.update_camera_ui(True)
|
||||
else:
|
||||
logging.warning(f"相机显示问题: {message}")
|
||||
# 更新占位符文本
|
||||
if self.material_placeholder:
|
||||
self.material_placeholder.setText(f"相机错误: {message}" if message else "相机未连接")
|
||||
self.update_camera_ui(False)
|
||||
|
||||
@Slot(int, str)
|
||||
def handle_emergency_stop(self, value, desc):
|
||||
"""处理急停信号"""
|
||||
logging.info(f"[处理] 急停信号: {desc}")
|
||||
|
||||
# 保存一个急停状态变量
|
||||
self.emergency_stop = value
|
||||
|
||||
# 当急停信号为1时,重置D2和D3寄存器
|
||||
if value == 1:
|
||||
try:
|
||||
modbus = ModbusUtils()
|
||||
client = modbus.get_client()
|
||||
|
||||
# 重置D2和D3寄存器
|
||||
modbus.write_register_until_success(client, 2, 0)
|
||||
modbus.write_register_until_success(client, 3, 0)
|
||||
|
||||
# 通过信号在主线程中处理UI更新
|
||||
self.emergency_stop_signal.emit(value, desc)
|
||||
|
||||
modbus.close_client(client)
|
||||
except Exception as e:
|
||||
logging.error(f"处理急停信号失败: {str(e)}")
|
||||
else:
|
||||
# 急停信号解除,在主线程中恢复错误状态显示
|
||||
self.emergency_stop_signal.emit(value, desc)
|
||||
|
||||
def _handle_emergency_stop_ui(self, value, desc):
|
||||
"""在主线程中处理急停信号UI更新"""
|
||||
try:
|
||||
if value == 1:
|
||||
# 显示警告对话框
|
||||
QMessageBox.warning(self, "急停警告", "监听到急停信号")
|
||||
|
||||
# 更新错误状态标签
|
||||
self.error_status_label.setText("故障: 急停")
|
||||
self.error_status_label.setToolTip("急停按钮被触发")
|
||||
self.error_status_label.setStyleSheet("color: red; font-weight: bold;")
|
||||
else:
|
||||
# 急停信号解除,恢复错误状态显示
|
||||
self._update_error_status()
|
||||
except Exception as e:
|
||||
logging.error(f"处理急停UI更新失败: {str(e)}")
|
||||
Loading…
Reference in New Issue
Block a user