feat: 更新README文档,增加项目概述和系统特点;修改配置文件以禁用电力自动启动;在主窗口中实现线径值的实时更新到表格功能
This commit is contained in:
parent
32740b7229
commit
848ba31c6b
238
README.md
238
README.md
@ -1,16 +1,20 @@
|
|||||||
# 腾智微丝产线包装系统
|
# 腾智微丝产线包装系统
|
||||||
|
|
||||||
## 项目架构分析
|
## 项目概述
|
||||||
|
|
||||||
这是一个基于PySide6(Qt for Python)开发的腾智微丝产线包装系统,采用了典型的MVC(模型-视图-控制器)架构:
|
腾智微丝产线包装系统是一个基于PySide6(Qt for Python)开发的工业自动化控制系统,用于管理和监控微丝产线的包装过程。该系统集成了相机监控、称重、条码扫描、PLC通信等功能,为微丝产品的质量控制与包装提供全面的解决方案。
|
||||||
|
|
||||||
|
## 项目架构
|
||||||
|
|
||||||
|
系统采用典型的MVC(模型-视图-控制器)架构:
|
||||||
|
|
||||||
1. **模型层(Model)**:
|
1. **模型层(Model)**:
|
||||||
- 使用DAO(数据访问对象)模式访问数据库
|
- 采用DAO(数据访问对象)模式访问数据库
|
||||||
- 支持多种数据库(SQLite、PostgreSQL、MySQL)
|
- 支持多种数据库(SQLite、PostgreSQL、MySQL)
|
||||||
- 主要数据表包括用户表、检验配置表、检验数据表、电力消耗表等
|
- 主要数据表包括用户表、检验配置表、检验数据表、电力消耗表等
|
||||||
|
|
||||||
2. **视图层(View)**:
|
2. **视图层(View)**:
|
||||||
- 使用PySide6构建UI界面
|
- 基于PySide6构建UI界面
|
||||||
- 主要界面包括登录界面、主窗口、设置界面等
|
- 主要界面包括登录界面、主窗口、设置界面等
|
||||||
- 采用分离的UI类设计,如LoginUI、MainWindowUI等
|
- 采用分离的UI类设计,如LoginUI、MainWindowUI等
|
||||||
|
|
||||||
@ -25,11 +29,9 @@
|
|||||||
|
|
||||||
5. **硬件集成层**:
|
5. **硬件集成层**:
|
||||||
- **相机子系统**:基于海康威视SDK进行集成
|
- **相机子系统**:基于海康威视SDK进行集成
|
||||||
- 相机管理器(CameraManager):单例模式,管理相机生命周期
|
|
||||||
- 相机显示组件(CameraDisplayWidget):用于实时显示相机画面
|
|
||||||
- 相机设置控制器(CameraSettingsWidget):管理相机参数设置
|
|
||||||
- **串口通信**:与称重设备、扫描器等外设通信
|
- **串口通信**:与称重设备、扫描器等外设通信
|
||||||
- **Modbus通信**:与PLC设备通信
|
- **Modbus通信**:与PLC设备通信
|
||||||
|
- **本地图像模式**:支持离线使用本地图像序列进行模拟测试
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
@ -38,18 +40,18 @@
|
|||||||
- 使用Qt的信号槽机制实现组件间通信
|
- 使用Qt的信号槽机制实现组件间通信
|
||||||
|
|
||||||
2. **后端技术**:
|
2. **后端技术**:
|
||||||
- Python作为主要开发语言
|
- Python 3.7+作为主要开发语言
|
||||||
- SQLite作为默认数据库,支持PostgreSQL和MySQL
|
- 支持SQLite、PostgreSQL和MySQL数据库
|
||||||
- Modbus协议用于与设备通信
|
- Modbus协议用于与PLC设备通信
|
||||||
- 多线程处理耗时操作
|
- 多线程处理耗时操作
|
||||||
|
|
||||||
3. **通信技术**:
|
3. **通信技术**:
|
||||||
- Modbus TCP用于与PLC设备通信
|
- Modbus TCP用于与PLC设备通信
|
||||||
- 串口通信用于与称重设备、条码扫描器等外设通信
|
- 串口通信用于与称重设备、条码扫描器等外设通信
|
||||||
- 海康威视SDK用于相机图像采集和处理
|
- 支持键盘监听用于扫码枪等输入设备
|
||||||
|
|
||||||
4. **设计模式**:
|
4. **设计模式**:
|
||||||
- 单例模式(配置加载器、监控器、相机管理器等)
|
- 单例模式(配置加载器、电力监控器、相机管理器等)
|
||||||
- DAO模式(数据访问)
|
- DAO模式(数据访问)
|
||||||
- 观察者模式(信号槽)
|
- 观察者模式(信号槽)
|
||||||
- 工厂模式(数据库连接)
|
- 工厂模式(数据库连接)
|
||||||
@ -65,122 +67,158 @@
|
|||||||
- `config/`:包含配置文件
|
- `config/`:包含配置文件
|
||||||
- `logs/`:包含日志文件
|
- `logs/`:包含日志文件
|
||||||
- `camera/`:包含相机模块和SDK接口类
|
- `camera/`:包含相机模块和SDK接口类
|
||||||
|
- `apis/`:API接口(用于接口模式)
|
||||||
|
|
||||||
2. **核心文件**:
|
2. **核心文件**:
|
||||||
- `main.py`:程序入口点
|
- `main.py`:程序入口点
|
||||||
- `widgets/login_widget.py`:登录窗口控制器
|
- `modbus_server.py`:Modbus服务器模拟
|
||||||
- `widgets/main_window.py`:主窗口控制器
|
|
||||||
- `widgets/camera_manager.py`:相机管理器
|
|
||||||
- `widgets/camera_display_widget.py`:相机显示组件
|
|
||||||
- `widgets/camera_settings_widget.py`:相机设置控制器
|
|
||||||
- `utils/config_loader.py`:配置加载器
|
- `utils/config_loader.py`:配置加载器
|
||||||
- `utils/modbus_utils.py`:Modbus通信工具
|
|
||||||
- `utils/sql_utils.py`:数据库工具
|
|
||||||
- `camera/CamOperation_class.py`:相机操作类
|
|
||||||
- `camera/MvCameraControl_class.py`:海康威视相机控制SDK
|
|
||||||
- `utils/local_image_player.py`:本地图像序列播放器
|
- `utils/local_image_player.py`:本地图像序列播放器
|
||||||
|
- `widgets/camera_manager.py`:相机管理器
|
||||||
|
- `dao/login_dao.py`:用户认证数据访问
|
||||||
|
|
||||||
3. **应用流程**:
|
## 系统特点与功能
|
||||||
- 程序启动后初始化日志系统和配置
|
|
||||||
- 创建和初始化各子系统(数据库、电力监控器等)
|
|
||||||
- 显示登录窗口
|
|
||||||
- 验证登录后显示主窗口
|
|
||||||
- 主窗口中进行产线包装系统的操作,包括:
|
|
||||||
- 产品检测和包装
|
|
||||||
- 实时相机监控
|
|
||||||
- 数据采集和报表生成
|
|
||||||
- 设备状态监控和控制
|
|
||||||
|
|
||||||
## 相机子系统详解
|
1. **两种运行模式**:
|
||||||
|
- 单机模式(standalone):完整的独立系统
|
||||||
|
- 接口模式(api):作为其他系统的接口组件运行
|
||||||
|
|
||||||
1. **架构设计**:
|
2. **本地图像模式**:
|
||||||
- 采用分层设计,将相机SDK封装在底层,提供简洁API供上层使用
|
- 支持本地图像序列播放,模拟相机实时画面
|
||||||
- 相机管理采用单例模式,确保全局只有一个相机实例
|
|
||||||
- 使用信号槽机制实现相机状态与UI的松耦合通信
|
|
||||||
|
|
||||||
2. **核心组件**:
|
|
||||||
- `CameraManager`:单例类,负责相机设备枚举、开关、参数设置等
|
|
||||||
- `CameraDisplayWidget`:显示组件,负责在UI中显示相机画面
|
|
||||||
- `CameraSettingsWidget`:设置控制器,负责参数调整界面交互
|
|
||||||
- `CamOperation_class`:相机操作封装类,直接与海康SDK交互
|
|
||||||
- `LocalImagePlayer`:本地图像序列播放器,提供基于本地图片序列的视频模拟功能
|
|
||||||
|
|
||||||
3. **工作流程**:
|
|
||||||
- 系统启动时初始化相机SDK
|
|
||||||
- 用户界面显示时枚举并连接可用的相机设备
|
|
||||||
- 启动相机图像采集并在UI中显示
|
|
||||||
- 用户可通过设置界面调整相机参数(曝光、增益、帧率等)
|
|
||||||
- 系统关闭时正确释放相机资源
|
|
||||||
|
|
||||||
4. **配置管理**:
|
|
||||||
- 相机参数保存在`config/app_config.json`的`camera`部分
|
|
||||||
- 包括默认曝光时间、增益、帧率等参数
|
|
||||||
- 用户调整的参数可保存至配置文件持久化
|
|
||||||
|
|
||||||
5. **本地图像模式**:
|
|
||||||
- 支持本地图像序列播放,可用于模拟相机实时画面
|
|
||||||
- 用户可选择包含图像序列的文件夹,系统自动按时间顺序播放
|
|
||||||
- 可调整播放帧率、设置循环播放等参数
|
|
||||||
- 适用于开发测试和演示场景,无需连接实际相机设备
|
- 适用于开发测试和演示场景,无需连接实际相机设备
|
||||||
- 配置参数保存在`config/app_config.json`的`camera.local_mode`部分
|
- 可调整播放帧率、设置循环播放等参数
|
||||||
|
|
||||||
## 功能特点
|
3. **相机管理**:
|
||||||
|
- 支持海康威视相机设备管理
|
||||||
|
- 自动发现和枚举可用相机设备
|
||||||
|
- 相机参数设置和保存(曝光、增益、帧率等)
|
||||||
|
|
||||||
1. **用户认证**:支持用户登录和权限控制
|
4. **Modbus通信**:
|
||||||
2. **产线监控**:实时监控产线状态、电力消耗等
|
- 与PLC设备进行Modbus TCP通信
|
||||||
3. **数据采集**:采集称重数据、检验数据等
|
- 支持自动模式和手动模式切换
|
||||||
4. **相机集成**:支持实时图像采集、显示和参数调整
|
- 内置Modbus服务器模拟功能,便于开发测试
|
||||||
5. **报表生成**:生成各类统计报表
|
|
||||||
6. **设备通信**:与PLC、称重设备等通信
|
|
||||||
7. **多模式支持**:支持单机模式和接口模式
|
|
||||||
|
|
||||||
## 运行环境
|
5. **电力监控**:
|
||||||
|
- 实时监控和记录电力消耗数据
|
||||||
|
- 数据可视化和统计分析
|
||||||
|
|
||||||
|
6. **数据管理**:
|
||||||
|
- 支持用户认证和权限控制
|
||||||
|
- 检验数据的采集、存储和分析
|
||||||
|
- 托盘类型管理
|
||||||
|
|
||||||
|
7. **日志系统**:
|
||||||
|
- 详细的日志记录
|
||||||
|
- 自动日志轮换
|
||||||
|
- 支持多级日志级别
|
||||||
|
|
||||||
|
## 安装与运行
|
||||||
|
|
||||||
|
### 系统要求
|
||||||
- Python 3.7+
|
- Python 3.7+
|
||||||
- PySide6
|
- 支持Windows、macOS、Linux操作系统
|
||||||
- 支持的数据库:SQLite、PostgreSQL、MySQL
|
|
||||||
- 操作系统:Windows、macOS、Linux
|
|
||||||
|
|
||||||
## 安装与配置
|
### 安装步骤
|
||||||
|
|
||||||
1. 安装依赖:
|
1. 安装依赖:
|
||||||
```
|
```
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
```
|
```
|
||||||
|
|
||||||
2. 配置数据库:
|
2. 配置应用:
|
||||||
|
- 配置文件位于`config/app_config.json`
|
||||||
- 默认使用SQLite数据库,位于`db/jtDB.db`
|
- 默认使用SQLite数据库,位于`db/jtDB.db`
|
||||||
- 可在`config/app_config.json`中配置其他数据库
|
- 可配置数据库连接、相机参数、Modbus设置等
|
||||||
|
|
||||||
3. 配置相机:
|
3. 运行应用:
|
||||||
- 在`config/app_config.json`中的`camera`部分调整相机参数
|
|
||||||
- 默认参数:
|
|
||||||
```json
|
|
||||||
"camera": {
|
|
||||||
"enabled": false,
|
|
||||||
"default_exposure": 20000,
|
|
||||||
"default_gain": 10,
|
|
||||||
"default_framerate": 30,
|
|
||||||
"local_mode": {
|
|
||||||
"enabled": false,
|
|
||||||
"folder_path": "",
|
|
||||||
"framerate": 15,
|
|
||||||
"loop": true,
|
|
||||||
"file_patterns": [".jpg", ".jpeg", ".png", ".bmp"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
4. 运行程序:
|
|
||||||
```
|
```
|
||||||
python main.py
|
python main.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 配置说明
|
||||||
|
|
||||||
|
1. **数据库配置**:
|
||||||
|
```json
|
||||||
|
"database": {
|
||||||
|
"default": "sqlite",
|
||||||
|
"sources": {
|
||||||
|
"sqlite": {
|
||||||
|
"path": "db/jtDB.db",
|
||||||
|
"description": "默认SQLite数据库"
|
||||||
|
},
|
||||||
|
"postgresql": {
|
||||||
|
"host": "localhost",
|
||||||
|
"port": "5432",
|
||||||
|
"user": "postgres",
|
||||||
|
"password": "",
|
||||||
|
"name": "jtDB"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **本地图像模式配置**:
|
||||||
|
```json
|
||||||
|
"local_image_mode": {
|
||||||
|
"enabled": true,
|
||||||
|
"folder_path": "/path/to/images",
|
||||||
|
"framerate": 15,
|
||||||
|
"loop": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **应用模式配置**:
|
||||||
|
```json
|
||||||
|
"app": {
|
||||||
|
"mode": "standalone", // 或 "api"
|
||||||
|
"features": {
|
||||||
|
"enable_serial_ports": false,
|
||||||
|
"enable_keyboard_listener": false,
|
||||||
|
"enable_camera": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 开发与扩展
|
## 开发与扩展
|
||||||
|
|
||||||
系统采用模块化设计,可以方便地进行功能扩展:
|
系统采用模块化设计,可以方便地进行功能扩展:
|
||||||
|
|
||||||
1. 添加新的数据源:扩展`utils/sql_utils.py`
|
1. **添加新的数据源**:扩展DAO层,实现对应的数据访问对象
|
||||||
2. 添加新的设备通信协议:参考`utils/modbus_utils.py`
|
|
||||||
3. 添加新的UI界面:在`ui/`目录下创建新的UI类,在`widgets/`目录下创建对应的控制器类
|
2. **添加新的硬件支持**:
|
||||||
4. 扩展相机功能:修改`widgets/camera_manager.py`和`camera/CamOperation_class.py`
|
- 参考`widgets/camera_manager.py`添加新的硬件管理器
|
||||||
|
- 参考`utils/local_image_player.py`添加新的设备模拟器
|
||||||
|
|
||||||
|
3. **扩展UI界面**:
|
||||||
|
- 在`ui/`目录下创建新的UI类
|
||||||
|
- 在`widgets/`目录下创建对应的控制器类
|
||||||
|
|
||||||
|
4. **添加新的通信协议**:参考`modbus_server.py`实现新的通信接口
|
||||||
|
|
||||||
|
## 注意事项
|
||||||
|
|
||||||
|
1. 首次运行时,系统将自动创建默认配置和数据库
|
||||||
|
|
||||||
|
2. 日志文件位于`logs/`目录,按日期自动轮换
|
||||||
|
|
||||||
|
3. 如果使用相机功能,需确保已安装海康威视SDK
|
||||||
|
|
||||||
|
4. 在测试环境中,可使用本地图像模式替代实际相机
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
1. **日志查看**:
|
||||||
|
- 检查`logs/`目录下的日志文件
|
||||||
|
- 日志格式为`app_YYYY-MM-DD.log`
|
||||||
|
|
||||||
|
2. **数据库问题**:
|
||||||
|
- 确认数据库配置正确
|
||||||
|
- 查看数据库连接错误日志
|
||||||
|
|
||||||
|
3. **相机连接问题**:
|
||||||
|
- 确认相机驱动已正确安装
|
||||||
|
- 尝试启用本地图像模式进行测试
|
||||||
|
|
||||||
|
4. **Modbus通信问题**:
|
||||||
|
- 检查PLC设备IP和端口配置
|
||||||
|
- 使用`modbus_server.py`进行通信测试
|
||||||
@ -115,6 +115,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"electricity": {
|
"electricity": {
|
||||||
"auto_start": true
|
"auto_start": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2744,6 +2744,75 @@ class MainWindow(MainWindowUI):
|
|||||||
# 更新UI显示,实时回显最新测量值
|
# 更新UI显示,实时回显最新测量值
|
||||||
self.statusBar().showMessage(f"线径数据: {xj_value:.3f}", 2000)
|
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)}")
|
||||||
|
|
||||||
# 如果当前值不为0,记录为最后一次有效值
|
# 如果当前值不为0,记录为最后一次有效值
|
||||||
if xj_value > 0:
|
if xj_value > 0:
|
||||||
self._last_diameter_value = xj_value
|
self._last_diameter_value = xj_value
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user