diff --git a/dao/pallet_type_dao.py b/dao/pallet_type_dao.py index ac03425..e4cc523 100644 --- a/dao/pallet_type_dao.py +++ b/dao/pallet_type_dao.py @@ -61,23 +61,22 @@ class PalletTypeDAO: logging.error(f"获取托盘类型失败: {str(e)}") return [] - def get_pallet_type_by_pallet_id(self, pallet_id): + def get_pallet_type_by_pallet_id(self, pallet_code): """根据托盘号获取托盘类型 Args: - pallet_id: 托盘号 + pallet_code: 托盘号 Returns: dict: 托盘类型信息,未找到则返回None """ try: sql = """ - SELECT DISTINCT sort_order + SELECT DISTINCT tier FROM wsbz_pallet_archives t1 - LEFT JOIN wsbz_pallet_types t2 ON t1.type_id = t2.id - WHERE pallet_id = ? AND t1.is_deleted = FALSE + WHERE pallet_code = ? AND t1.is_deleted = FALSE """ - params = (pallet_id,) + params = (pallet_code,) self.db.cursor.execute(sql, params) row = self.db.cursor.fetchone() if row: diff --git a/db/jtDB.db b/db/jtDB.db index 3c0d654..137181b 100644 Binary files a/db/jtDB.db and b/db/jtDB.db differ diff --git a/from pymodbus.py b/from pymodbus.py index 257e237..fa3471e 100644 --- a/from pymodbus.py +++ b/from pymodbus.py @@ -6,10 +6,10 @@ client.connect() # client.write_registers(address=6, values=[1]) # client.write_registers(address=5, values=[16]) # 贴标完成 -client.write_registers(address=13, values=[1]) +# client.write_registers(address=13, values=[1]) # client.write_registers(address=24, values=[1]) -result = client.read_holding_registers(address=24, count=1) +result = client.read_holding_registers(address=4, count=1) print(result.registers[0],"123===") client.close() \ No newline at end of file diff --git a/ui/unloading_dialog_ui.py b/ui/unloading_dialog_ui.py new file mode 100644 index 0000000..e367f40 --- /dev/null +++ b/ui/unloading_dialog_ui.py @@ -0,0 +1,237 @@ +from PySide6.QtWidgets import ( + QDialog, QLabel, QLineEdit, QComboBox, QPushButton, + QVBoxLayout, QHBoxLayout, QFrame +) +from PySide6.QtCore import Qt +from PySide6.QtGui import QFont + +class UnloadingDialogUI(QDialog): + def __init__(self): + super().__init__() + self.setWindowTitle("下料操作") + self.setFixedSize(600, 250) # 减小高度,因为移除了第一行 + + # 设置字体 + self.normal_font = QFont("微软雅黑", 12) + + # 初始化UI + self.init_ui() + + def init_ui(self): + """初始化UI""" + # 主布局 + self.main_layout = QVBoxLayout(self) + self.main_layout.setContentsMargins(20, 20, 20, 20) + self.main_layout.setSpacing(0) # 移除布局间距 + + # 创建内容区域 + self.create_content_frame() + + # 创建按钮 + self.create_buttons() + + def create_content_frame(self): + """创建内容区域""" + # 创建一个带边框的容器 + container = QFrame() + container.setStyleSheet(""" + QFrame { + border: 1px solid #e0e0e0; + background-color: white; + } + """) + + # 容器的垂直布局 + container_layout = QVBoxLayout(container) + container_layout.setContentsMargins(0, 0, 0, 0) + container_layout.setSpacing(0) + + # 通用样式 + label_style = """ + QLabel { + background-color: #f5f5f5; + color: #333333; + font-weight: bold; + border: none; + border-right: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + padding: 0 8px; + } + """ + + input_style = """ + QLineEdit { + border: none; + border-right: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + background-color: white; + selection-background-color: #0078d4; + padding: 0 8px; + } + QLineEdit:focus { + background-color: #f8f8f8; + } + """ + + value_style = """ + QLabel { + background-color: white; + border: none; + border-right: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + padding: 0 8px; + } + """ + + # 第一行:托盘号 + row1 = QHBoxLayout() + row1.setSpacing(0) + + self.tray_label = QLabel("托盘号") + self.tray_label.setFont(self.normal_font) + self.tray_label.setStyleSheet(label_style) + self.tray_label.setFixedWidth(100) + self.tray_label.setFixedHeight(45) + + self.tray_input = QLineEdit() + self.tray_input.setFont(self.normal_font) + self.tray_input.setPlaceholderText("请扫描托盘号") + self.tray_input.setStyleSheet(input_style) + self.tray_input.setFixedHeight(45) + + row1.addWidget(self.tray_label) + row1.addWidget(self.tray_input, 1) + container_layout.addLayout(row1) + + # 第二行:轴型和托盘料 + row2 = QHBoxLayout() + row2.setSpacing(0) + + axis_layout = QHBoxLayout() + axis_layout.setSpacing(0) + self.axis_label = QLabel("轴型") + self.axis_label.setFont(self.normal_font) + self.axis_label.setStyleSheet(label_style) + self.axis_label.setFixedWidth(100) + self.axis_label.setFixedHeight(40) + + self.axis_value = QLabel("--") + self.axis_value.setFont(self.normal_font) + self.axis_value.setStyleSheet(value_style) + self.axis_value.setFixedHeight(40) + + axis_layout.addWidget(self.axis_label) + axis_layout.addWidget(self.axis_value, 1) + + material_layout = QHBoxLayout() + material_layout.setSpacing(0) + self.pallet_material_label = QLabel("托盘料") + self.pallet_material_label.setFont(self.normal_font) + self.pallet_material_label.setStyleSheet(label_style) + self.pallet_material_label.setFixedWidth(100) + self.pallet_material_label.setFixedHeight(40) + + self.pallet_material_value = QLabel("--") + self.pallet_material_value.setFont(self.normal_font) + self.pallet_material_value.setStyleSheet(value_style) + self.pallet_material_value.setFixedHeight(40) + + material_layout.addWidget(self.pallet_material_label) + material_layout.addWidget(self.pallet_material_value, 1) + + row2.addLayout(axis_layout, 1) + row2.addLayout(material_layout, 1) + container_layout.addLayout(row2) + + # 第三行:数量和重量 + row3 = QHBoxLayout() + row3.setSpacing(0) + + quantity_layout = QHBoxLayout() + quantity_layout.setSpacing(0) + self.quantity_label = QLabel("数量") + self.quantity_label.setFont(self.normal_font) + self.quantity_label.setStyleSheet(label_style) + self.quantity_label.setFixedWidth(100) + self.quantity_label.setFixedHeight(40) + + self.quantity_value = QLabel("--") + self.quantity_value.setFont(self.normal_font) + self.quantity_value.setStyleSheet(value_style) + self.quantity_value.setFixedHeight(40) + + quantity_layout.addWidget(self.quantity_label) + quantity_layout.addWidget(self.quantity_value, 1) + + weight_layout = QHBoxLayout() + weight_layout.setSpacing(0) + self.weight_label = QLabel("重量") + self.weight_label.setFont(self.normal_font) + self.weight_label.setStyleSheet(label_style) + self.weight_label.setFixedWidth(100) + self.weight_label.setFixedHeight(40) + + self.weight_value = QLabel("--") + self.weight_value.setFont(self.normal_font) + self.weight_value.setStyleSheet(value_style) + self.weight_value.setFixedHeight(40) + + weight_layout.addWidget(self.weight_label) + weight_layout.addWidget(self.weight_value, 1) + + row3.addLayout(quantity_layout, 1) + row3.addLayout(weight_layout, 1) + container_layout.addLayout(row3) + + # 添加弹性空间 + container_layout.addStretch() + + # 将容器添加到主布局 + self.main_layout.addWidget(container) + + def create_buttons(self): + """创建按钮""" + # 按钮布局 + button_layout = QHBoxLayout() + button_layout.setContentsMargins(0, 20, 0, 0) + button_layout.setSpacing(10) + + # 确认按钮 + self.confirm_button = QPushButton("确认") + self.confirm_button.setFont(self.normal_font) + self.confirm_button.setStyleSheet(""" + QPushButton { + background-color: #fff8e1; + border: 1px solid #ffc107; + padding: 8px 16px; + font-weight: bold; + border-radius: 4px; + } + QPushButton:hover { + background-color: #fff3e0; + } + """) + + # 取消按钮 + self.cancel_button = QPushButton("取消") + self.cancel_button.setFont(self.normal_font) + self.cancel_button.setStyleSheet(""" + QPushButton { + background-color: #f5f5f5; + border: 1px solid #e0e0e0; + padding: 8px 16px; + font-weight: bold; + border-radius: 4px; + } + QPushButton:hover { + background-color: #eeeeee; + } + """) + + # 添加按钮到布局 + button_layout.addStretch() + button_layout.addWidget(self.confirm_button) + button_layout.addWidget(self.cancel_button) + + # 将按钮布局添加到主布局 + self.main_layout.addLayout(button_layout) \ No newline at end of file diff --git a/utils/pallet_type_manager.py b/utils/pallet_type_manager.py index ad2bd23..aa4269e 100644 --- a/utils/pallet_type_manager.py +++ b/utils/pallet_type_manager.py @@ -199,13 +199,13 @@ class PalletTypeManager: else: return None - def get_pallet_type_by_pallet_id(self, pallet_id): + def get_pallet_type_by_pallet_id(self, pallet_code): """根据托盘号获取托盘类型 Args: - pallet_id: 托盘号 + pallet_code: 托盘号 """ - result = self.dao.get_pallet_type_by_pallet_id(pallet_id) + result = self.dao.get_pallet_type_by_pallet_id(pallet_code) if result: return result else: diff --git a/widgets/main_window.py b/widgets/main_window.py index 16e3766..91d1a68 100644 --- a/widgets/main_window.py +++ b/widgets/main_window.py @@ -396,67 +396,67 @@ class MainWindow(MainWindowUI): def handle_output(self): """处理下料按钮点击事件""" - # 创建对话框 - dialog = QDialog(self) - dialog.setWindowTitle("下料操作") - dialog.setFixedSize(300, 200) + # 获取托盘号 + tray_id = self.tray_edit.currentText() + if not tray_id: + QMessageBox.warning(self, "提示", "请先选择或输入托盘号") + return + + # 启动监听(不论后续是否确认下料) + # 启动Modbus监控 + if not hasattr(self, 'modbus_monitor') or not self.modbus_monitor.is_running(): + self.setup_modbus_monitor() + logging.info("已在下料操作前启动Modbus监控") - # 对话框布局 - layout = QVBoxLayout(dialog) + # 启动串口监听 + self.serial_manager.auto_open_configured_ports() - # 添加提示信息 - info_label = QLabel("请选择下料托盘类型:") - info_label.setFont(self.normal_font) - layout.addWidget(info_label) + # 启动键盘监听器 + self.serial_manager.start_keyboard_listener() + logging.info("已在下料操作前启动键盘监听器") - # 添加托盘类型选择 - pallet_combo = QComboBox() - pallet_combo.setFont(self.normal_font) - # 复制当前托盘类型选择器的内容 - for i in range(self.output_pallet_type_combo.count()): - pallet_combo.addItem(self.output_pallet_type_combo.itemText(i)) - layout.addWidget(pallet_combo) - - # 添加按钮 - button_layout = QHBoxLayout() - confirm_button = QPushButton("确认") - confirm_button.setFont(self.normal_font) - confirm_button.setStyleSheet("background-color: #fff8e1; border: 1px solid #ffc107; padding: 8px 16px; font-weight: bold; border-radius: 4px;") - - cancel_button = QPushButton("取消") - cancel_button.setFont(self.normal_font) - cancel_button.setStyleSheet("padding: 8px 16px; font-weight: bold; border-radius: 4px;") - - button_layout.addStretch() - button_layout.addWidget(confirm_button) - button_layout.addWidget(cancel_button) - layout.addLayout(button_layout) - - # 连接按钮信号 - confirm_button.clicked.connect(dialog.accept) - cancel_button.clicked.connect(dialog.reject) + # 创建下料对话框 + from widgets.unloading_dialog_widget import UnloadingDialog + dialog = UnloadingDialog(parent=self) # 显示对话框 result = dialog.exec() - + # 如果用户确认,则执行下料操作 if result == QDialog.Accepted: - selected_type = pallet_combo.currentText() - # 获取托盘的排序,该顺序影响着下料寄存器的写入值 切记,需要和 PLC 确认沟通完成后才能修改排序值 - pallets_dict = self.pallet_type_manager.get_pallet_type_by_type(selected_type) + # 获取托盘料值作为下料层数 + stow_num = dialog.pallet_material_value.text() + if stow_num == "--" or not stow_num: + QMessageBox.warning(self, "错误", "未获取到托盘料信息,请重试") + return + + # 获取托盘号对应的托盘类型 + pallet_type = self.pallet_type_manager.get_pallet_type_by_pallet_id(tray_id) + # 初始化托盘号对应的序号 + if tray_id not in self.init_seq: + self.init_seq[tray_id] = 1 + + if not pallet_type: + QMessageBox.warning(self, "错误", "未查到对应下料托盘类型") + return + # 执行Modbus操作 modbus = ModbusUtils() client = modbus.get_client() try: - #TODO: 下料 D3 寄存器写入 1 D1 寄存器写入托盘类型 - if modbus.write_register_until_success(client, 3, 1) and modbus.write_register_until_success(client, 1, pallets_dict.get(selected_type)): + # 下料 D3 寄存器写入 1 D1 寄存器写入托盘类型 + success0 = modbus.write_register_until_success(client, 0, int(stow_num)) + success1 = modbus.write_register_until_success(client, 1, int(pallet_type)) + success3 = modbus.write_register_until_success(client, 3, 1) + + if success0 and success1 and success3: # 创建状态标签并显示在右上角 - self.show_operation_status("下料托盘", "output", selected_type) + self.show_operation_status("码垛层数", "output", stow_num) else: - QMessageBox.information(self, "操作提示", "下料失败") + QMessageBox.information(self, "操作提示", "码垛层数") except Exception as e: - logging.error(f"下料操作失败: {str(e)}") - QMessageBox.critical(self, "错误", f"下料操作失败: {str(e)}") + logging.error(f"码垛层数操作失败: {str(e)}") + QMessageBox.critical(self, "错误", f"码垛失败: {str(e)}") finally: modbus.close_client(client) diff --git a/widgets/unloading_dialog_widget.py b/widgets/unloading_dialog_widget.py new file mode 100644 index 0000000..c880c1d --- /dev/null +++ b/widgets/unloading_dialog_widget.py @@ -0,0 +1,112 @@ +from ui.unloading_dialog_ui import UnloadingDialogUI +from apis.tary_api import TaryApi +from PySide6.QtCore import Qt, Signal +from PySide6.QtWidgets import QMessageBox, QDialog +import logging + +class UnloadingDialog(UnloadingDialogUI): + # 定义一个信号,用于向主窗口传递托盘号 + tray_code_signal = Signal(str, str, str, str) + + def __init__(self, parent=None): + """初始化下料对话框""" + super().__init__() + self.parent = parent + + # 初始化API + self.tary_api = TaryApi() + + # 彻底禁用对话框的回车键关闭功能 + self.setModal(True) + # 禁用所有按钮的默认行为 + self.confirm_button.setAutoDefault(False) + self.confirm_button.setDefault(False) + self.cancel_button.setAutoDefault(False) + self.cancel_button.setDefault(False) + + # 设置对话框特性,按下Escape键才能关闭 + self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) + + # 绑定事件 + self.setup_connections() + + def setup_connections(self): + """设置事件连接""" + # 托盘号输入框回车事件触发查询 + self.tray_input.returnPressed.connect(self.handle_tray_return_pressed) + self.tray_input.editingFinished.connect(self.on_tray_query) + + # 确认按钮点击事件 + self.confirm_button.clicked.connect(self.accept) + + # 取消按钮点击事件 + self.cancel_button.clicked.connect(self.reject) + + def handle_tray_return_pressed(self): + """处理托盘输入框的回车事件""" + # 阻止事件传播 + logging.info("托盘输入框回车事件触发") + self.on_tray_query() + + # 阻止事件继续传播 + return True + + def on_tray_query(self): + """查询托盘信息""" + try: + tray_code = self.tray_input.text().strip() + if not tray_code: + return + + logging.info(f"查询托盘号: {tray_code}") + + # 调用API获取托盘信息 + response = self.tary_api.get_tary_info(tray_code) + + logging.info(f"托盘信息响应: {response}") + logging.info(f"response.success={response.get('success')}, response.data存在={response.get('data') is not None}") + + if response.get("success", False) and response.get("data"): + tray_data = response.get("data", {}) + logging.info(f"托盘数据: {tray_data}") + + # 显示托盘相关信息 + axis_type = str(tray_data.get("axis_type", "--")) + material = str(tray_data.get("material", "--")) + weight = str(tray_data.get("weight", "--")) + + logging.info(f"显示托盘信息: 轴型={axis_type}, 托盘料={material}, 重量={weight}") + + # 设置显示值 + self.axis_value.setText(axis_type) + self.pallet_material_value.setText(material) + self.quantity_value.setText("") # 数量为空 + self.weight_value.setText(f"{weight} kg") + + # 发送托盘号到主窗口 + from widgets.main_window import MainWindow + main_window = self.parent + if main_window and isinstance(main_window, MainWindow): + # 检查托盘号是否已存在 + existed = False + for i in range(main_window.tray_edit.count()): + if main_window.tray_edit.itemText(i) == tray_code: + existed = True + break + + # 如果不存在,则添加 + if not existed: + logging.info(f"添加托盘号到主窗口: {tray_code}") + main_window.tray_edit.addItem(tray_code) + + # 设置当前选中的托盘号 + main_window.tray_edit.setCurrentText(tray_code) + logging.info(f"设置主窗口当前托盘号: {tray_code}") + else: + # 获取托盘信息失败 + error_msg = response.get("message", "获取托盘信息失败") + logging.warning(f"查询失败: {error_msg}") + QMessageBox.warning(self, "查询失败", error_msg) + except Exception as e: + logging.error(f"查询托盘信息异常: {str(e)}") + QMessageBox.critical(self, "查询异常", f"查询托盘信息时发生异常: {str(e)}") \ No newline at end of file