feat: 更新SDK初始化逻辑,添加异常处理以增强稳定性;在设置界面中新增Modbus配置功能,包含主机地址和端口输入框及连接测试按钮;优化Modbus工具类以支持动态主机和端口配置;增强设置窗口信号连接功能以处理设置变更。

This commit is contained in:
zhu-mengmeng 2025-06-26 10:44:15 +08:00
parent 99bca76e08
commit 77c6f9f480
5 changed files with 250 additions and 22 deletions

View File

@ -47,9 +47,13 @@ class MvCamera():
# ch:初始化SDK | en: Initialize SDK # ch:初始化SDK | en: Initialize SDK
@staticmethod @staticmethod
def MV_CC_Initialize(): def MV_CC_Initialize():
try:
MvCamCtrldll.MV_CC_Initialize.restype = c_int MvCamCtrldll.MV_CC_Initialize.restype = c_int
# C原型int __stdcall MV_CC_Initialize(); # C原型int __stdcall MV_CC_Initialize();
return MvCamCtrldll.MV_CC_Initialize() return MvCamCtrldll.MV_CC_Initialize()
except Exception as e:
print(f"初始化SDK失败: {e}")
return -1
# ch:反初始化SDK | en: Finalize SDK # ch:反初始化SDK | en: Finalize SDK
@staticmethod @staticmethod

View File

@ -3,7 +3,7 @@ from PySide6.QtWidgets import (
QTabWidget, QFrame, QFormLayout, QGroupBox, QRadioButton, QSpacerItem, QSizePolicy, QTabWidget, QFrame, QFormLayout, QGroupBox, QRadioButton, QSpacerItem, QSizePolicy,
QTableWidget, QTableWidgetItem, QHeaderView, QSlider, QCheckBox, QButtonGroup QTableWidget, QTableWidgetItem, QHeaderView, QSlider, QCheckBox, QButtonGroup
) )
from PySide6.QtGui import QFont, QBrush, QColor from PySide6.QtGui import QFont, QBrush, QColor, QIntValidator
from PySide6.QtCore import Qt, Signal, QSize from PySide6.QtCore import Qt, Signal, QSize
class SettingsUI(QWidget): class SettingsUI(QWidget):
@ -354,11 +354,71 @@ class SettingsUI(QWidget):
self.plc_layout = QVBoxLayout(self.plc_tab) self.plc_layout = QVBoxLayout(self.plc_tab)
self.plc_layout.setContentsMargins(20, 20, 20, 20) self.plc_layout.setContentsMargins(20, 20, 20, 20)
# 占位标签 # 创建Modbus配置组
self.plc_placeholder = QLabel("PLC设置待实现") self.modbus_group = QGroupBox("Modbus 配置")
self.plc_placeholder.setFont(self.normal_font) self.modbus_group.setFont(self.normal_font)
self.plc_placeholder.setAlignment(Qt.AlignCenter) self.modbus_layout = QFormLayout(self.modbus_group)
self.plc_layout.addWidget(self.plc_placeholder) self.modbus_layout.setContentsMargins(15, 20, 15, 15)
self.modbus_layout.setSpacing(15)
# 主机地址输入框
self.modbus_host_input = QLineEdit()
self.modbus_host_input.setFont(self.normal_font)
self.modbus_host_input.setPlaceholderText("请输入Modbus主机地址")
self.modbus_layout.addRow(QLabel("主机地址:"), self.modbus_host_input)
# 端口输入框
self.modbus_port_input = QLineEdit()
self.modbus_port_input.setFont(self.normal_font)
self.modbus_port_input.setPlaceholderText("请输入Modbus端口")
self.modbus_port_input.setValidator(QIntValidator(1, 65535))
self.modbus_layout.addRow(QLabel("端口:"), self.modbus_port_input)
# 测试连接按钮
self.modbus_test_button = QPushButton("测试连接")
self.modbus_test_button.setFont(self.normal_font)
self.modbus_test_button.setStyleSheet("""
QPushButton {
background-color: #2196f3;
color: white;
border: none;
border-radius: 3px;
padding: 5px 15px;
}
QPushButton:hover {
background-color: #1e88e5;
}
""")
self.modbus_layout.addRow("", self.modbus_test_button)
# 添加Modbus配置组到布局
self.plc_layout.addWidget(self.modbus_group)
# 添加保存按钮
self.plc_save_button = QPushButton("保存配置")
self.plc_save_button.setFont(self.normal_font)
self.plc_save_button.setFixedSize(120, 40)
self.plc_save_button.setStyleSheet("""
QPushButton {
background-color: #4caf50;
color: white;
border: none;
border-radius: 5px;
}
QPushButton:hover {
background-color: #45a049;
}
QPushButton:pressed {
background-color: #3d8b40;
}
""")
# 添加按钮布局
button_layout = QHBoxLayout()
button_layout.addStretch(1)
button_layout.addWidget(self.plc_save_button)
self.plc_layout.addLayout(button_layout)
self.plc_layout.addStretch(1) self.plc_layout.addStretch(1)
self.tab_widget.addTab(self.plc_tab, "PLC设置") self.tab_widget.addTab(self.plc_tab, "PLC设置")

View File

@ -12,11 +12,11 @@ log.setLevel(logging.WARNING)
class ModbusUtils: class ModbusUtils:
def __init__(self) -> None: def __init__(self, host=None, port=None) -> None:
# 初始化 modbus 配置 # 初始化 modbus 配置
config = ConfigLoader.get_instance() config = ConfigLoader.get_instance()
self.MODBUS_HOST = config.get_value("modbus.host") self.MODBUS_HOST = host if host is not None else config.get_value("modbus.host")
self.MODBUS_PORT = config.get_value("modbus.port") self.MODBUS_PORT = port if port is not None else int(config.get_value("modbus.port"))
def get_client(self): def get_client(self):
# 创建Modbus TCP客户端实例指定服务器的IP地址和端口号 # 创建Modbus TCP客户端实例指定服务器的IP地址和端口号
@ -35,7 +35,6 @@ class ModbusUtils:
return None # Or raise an exception return None # Or raise an exception
return client return client
def close_client(self, client): def close_client(self, client):
# 关闭客户端连接 # 关闭客户端连接
if client: if client:

View File

@ -0,0 +1,141 @@
import logging
import json
import os
from PySide6.QtWidgets import QWidget, QMessageBox
from PySide6.QtCore import Signal
from utils.config_loader import ConfigLoader
class PLCSettingsWidget(QWidget):
"""PLC设置控制器"""
# 定义信号
settings_changed = Signal() # 设置变更信号
def __init__(self, parent=None):
"""初始化控制器
Args:
parent: 父窗口
"""
super().__init__(parent)
self.parent = parent
self.config = ConfigLoader.get_instance()
# 获取UI控件引用
self.modbus_host_input = parent.modbus_host_input
self.modbus_port_input = parent.modbus_port_input
self.modbus_test_button = parent.modbus_test_button
self.plc_save_button = parent.plc_save_button
# 连接信号和槽
self.connect_signals()
# 加载配置
self.load_config()
def connect_signals(self):
"""连接信号和槽"""
self.modbus_test_button.clicked.connect(self.test_modbus_connection)
self.plc_save_button.clicked.connect(self.save_config)
def load_config(self):
"""加载配置"""
try:
# 加载Modbus配置
host = self.config.get_value("modbus.host")
port = self.config.get_value("modbus.port")
self.modbus_host_input.setText(host if host else "localhost")
self.modbus_port_input.setText(str(port) if port else "502")
logging.info("已加载PLC配置")
except Exception as e:
logging.error(f"加载PLC配置失败: {str(e)}")
QMessageBox.critical(self, "错误", f"加载PLC配置失败: {str(e)}")
def save_config(self):
"""保存配置"""
try:
# 获取输入值
host = self.modbus_host_input.text().strip()
port = self.modbus_port_input.text().strip()
# 验证输入
if not host:
QMessageBox.warning(self, "警告", "请输入Modbus主机地址")
return
if not port:
QMessageBox.warning(self, "警告", "请输入Modbus端口")
return
try:
port_int = int(port)
if port_int < 1 or port_int > 65535:
QMessageBox.warning(self, "警告", "端口号必须在1-65535之间")
return
except ValueError:
QMessageBox.warning(self, "警告", "端口号必须是整数")
return
# 更新配置
self.config.set_value("modbus.host", host)
self.config.set_value("modbus.port", port)
self.config.save_config()
# 发送信号
self.settings_changed.emit()
# 提示成功
QMessageBox.information(self, "成功", "PLC配置已保存")
logging.info(f"已保存PLC配置: host={host}, port={port}")
except Exception as e:
logging.error(f"保存PLC配置失败: {str(e)}")
QMessageBox.critical(self, "错误", f"保存PLC配置失败: {str(e)}")
def test_modbus_connection(self):
"""测试Modbus连接"""
try:
# 获取输入值
host = self.modbus_host_input.text().strip()
port = self.modbus_port_input.text().strip()
# 验证输入
if not host:
QMessageBox.warning(self, "警告", "请输入Modbus主机地址")
return
if not port:
QMessageBox.warning(self, "警告", "请输入Modbus端口")
return
try:
port_int = int(port)
except ValueError:
QMessageBox.warning(self, "警告", "端口号必须是整数")
return
# 导入ModbusUtils
from utils.modbus_utils import ModbusUtils
# 创建Modbus连接
modbus = ModbusUtils(host=host, port=port_int)
client = modbus.get_client()
if client:
QMessageBox.information(self, "成功", f"Modbus连接成功: {host}:{port}")
logging.info(f"Modbus连接测试成功: {host}:{port}")
else:
QMessageBox.warning(self, "警告", f"Modbus连接失败: {host}:{port}")
logging.warning(f"Modbus连接测试失败: {host}:{port}")
# 关闭连接
modbus.close_client(client)
except Exception as e:
logging.error(f"测试Modbus连接失败: {str(e)}")
QMessageBox.critical(self, "错误", f"测试Modbus连接失败: {str(e)}")
def on_settings_changed(self):
"""设置变更处理"""
# 重新加载配置
self.load_config()

View File

@ -1,5 +1,5 @@
from PySide6.QtWidgets import QMessageBox, QVBoxLayout from PySide6.QtWidgets import QMessageBox, QVBoxLayout
from PySide6.QtCore import Qt from PySide6.QtCore import Qt, Signal
import logging import logging
import json import json
import os import os
@ -7,19 +7,29 @@ from ui.settings_ui import SettingsUI
from utils.sql_utils import SQLUtils from utils.sql_utils import SQLUtils
from widgets.inspection_settings_widget import InspectionSettingsWidget from widgets.inspection_settings_widget import InspectionSettingsWidget
from widgets.pallet_type_settings_widget import PalletTypeSettingsWidget from widgets.pallet_type_settings_widget import PalletTypeSettingsWidget
from widgets.plc_settings_widget import PLCSettingsWidget
from utils.config_loader import ConfigLoader from utils.config_loader import ConfigLoader
from utils.app_mode import AppMode from utils.app_mode import AppMode
from widgets.camera_settings_widget import CameraSettingsWidget
from widgets.serial_settings_widget import SerialSettingsWidget
class SettingsWidget(SettingsUI): class SettingsWidget(SettingsUI):
# 定义信号
settings_changed = Signal()
def __init__(self, parent=None): def __init__(self, parent=None):
"""初始化设置窗口"""
super().__init__(parent) super().__init__(parent)
self.parent = parent self.parent = parent
logging.info("正在初始化SettingsWidget") logging.info("正在初始化SettingsWidget")
# 创建检验设置部件 # 创建子设置控制器
logging.info("创建InspectionSettingsWidget实例") self.camera_settings = CameraSettingsWidget(self)
self.inspection_settings = InspectionSettingsWidget() self.serial_settings = SerialSettingsWidget(self)
self.inspection_settings = InspectionSettingsWidget(self)
self.pallet_type_settings = PalletTypeSettingsWidget(self)
self.plc_settings = PLCSettingsWidget(self)
# 移除临时占位符标签并添加检验设置部件 # 移除临时占位符标签并添加检验设置部件
if hasattr(self, 'inspection_placeholder'): if hasattr(self, 'inspection_placeholder'):
@ -60,7 +70,7 @@ class SettingsWidget(SettingsUI):
# 加载配置文件 # 加载配置文件
self.config_loader = ConfigLoader.get_instance() self.config_loader = ConfigLoader.get_instance()
# 连接信号和槽 # 连接信号
self.connect_signals() self.connect_signals()
# 初始化数据库类型UI状态 # 初始化数据库类型UI状态
@ -72,6 +82,14 @@ class SettingsWidget(SettingsUI):
logging.info("SettingsWidget初始化完成") logging.info("SettingsWidget初始化完成")
def connect_signals(self): def connect_signals(self):
"""连接信号和槽"""
# 连接子设置控制器的信号
self.camera_settings.settings_changed.connect(self.on_settings_changed)
self.serial_settings.settings_changed.connect(self.on_settings_changed)
self.inspection_settings.settings_changed.connect(self.on_settings_changed)
self.pallet_type_settings.settings_changed.connect(self.on_settings_changed)
self.plc_settings.settings_changed.connect(self.on_settings_changed)
# 数据库类型选择 # 数据库类型选择
self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state) self.db_type_combo.currentTextChanged.connect(self.update_db_ui_state)
@ -354,3 +372,9 @@ class SettingsWidget(SettingsUI):
"""返回主页""" """返回主页"""
if self.parent and hasattr(self.parent, 'show_main_page'): if self.parent and hasattr(self.parent, 'show_main_page'):
self.parent.show_main_page() self.parent.show_main_page()
def on_settings_changed(self):
"""处理设置变更信号"""
logging.info("设置已变更发送settings_changed信号")
# 发送信号
self.settings_changed.emit()