init project

This commit is contained in:
靳中伟 2025-04-30 16:57:46 +08:00
commit 0189b1f0b9
270 changed files with 539457 additions and 0 deletions

View File

@ -0,0 +1,143 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - API接口
## API接口概述
VWED任务模块使用FastAPI框架实现RESTful API接口提供任务管理、任务编辑、任务执行、模板管理和脚本管理等功能。
## 主要API路由
### 任务管理API
任务管理API提供任务的基本CRUD操作和执行控制。
**相关文件**: [routes/task_api.py](mdc:routes/task_api.py)
**主要接口**:
- `GET /api/tasks`: 获取任务列表
- `GET /api/tasks/{task_id}`: 获取任务详情
- `POST /api/tasks`: 创建新任务
- `PUT /api/tasks/{task_id}`: 更新任务信息
- `DELETE /api/tasks/{task_id}`: 删除任务
- `POST /api/tasks/{task_id}/execute`: 执行任务
- `GET /api/tasks/{task_id}/status`: 获取任务执行状态
- `POST /api/tasks/{task_id}/cancel`: 取消正在执行的任务
### 任务编辑API
任务编辑API提供任务流程和组件的编辑功能支持任务的可视化设计。
**相关文件**: [routes/task_edit_api.py](mdc:routes/task_edit_api.py)
**主要接口**:
- `GET /api/task-edit/{task_id}/blocks`: 获取任务的所有块
- `POST /api/task-edit/{task_id}/blocks`: 添加新块
- `PUT /api/task-edit/{task_id}/blocks/{block_id}`: 更新块信息
- `DELETE /api/task-edit/{task_id}/blocks/{block_id}`: 删除块
- `POST /api/task-edit/{task_id}/connections`: 创建块之间的连接
- `DELETE /api/task-edit/{task_id}/connections/{connection_id}`: 删除连接
- `POST /api/task-edit/{task_id}/validate`: 验证任务流程
### 模板管理API
模板管理API提供任务模板的管理功能用户可以基于模板快速创建任务。
**相关文件**: [routes/template_api.py](mdc:routes/template_api.py)
**主要接口**:
- `GET /api/templates`: 获取模板列表
- `GET /api/templates/{template_id}`: 获取模板详情
- `POST /api/templates`: 创建新模板
- `PUT /api/templates/{template_id}`: 更新模板信息
- `DELETE /api/templates/{template_id}`: 删除模板
- `POST /api/templates/{template_id}/create-task`: 基于模板创建任务
### 脚本管理API
脚本管理API提供自定义脚本的管理功能支持在任务中执行自定义脚本。
**相关文件**: [routes/script_api.py](mdc:routes/script_api.py)
**主要接口**:
- `GET /api/scripts`: 获取脚本列表
- `GET /api/scripts/{script_id}`: 获取脚本详情
- `POST /api/scripts`: 创建新脚本
- `PUT /api/scripts/{script_id}`: 更新脚本信息
- `DELETE /api/scripts/{script_id}`: 删除脚本
- `POST /api/scripts/{script_id}/test`: 测试执行脚本
### 数据库操作API
数据库操作API提供直接操作数据库的接口主要用于调试和管理目的。
**相关文件**: [routes/database.py](mdc:routes/database.py)
**主要接口**:
- `GET /api/db/tables`: 获取数据库表列表
- `GET /api/db/tables/{table_name}`: 获取表结构
- `GET /api/db/execute`: 执行SQL查询
### 通用API
通用API提供系统级功能如健康检查、版本信息等。
**相关文件**: [routes/common_api.py](mdc:routes/common_api.py)
**主要接口**:
- `GET /api/health`: 系统健康检查
- `GET /api/version`: 获取系统版本信息
- `GET /api/components`: 获取预设组件列表
## API响应格式
所有API接口返回统一的JSON格式:
```json
{
"code": 200, // 状态码
"message": "成功", // 状态消息
"data": { // 响应数据
// 具体数据内容
}
}
```
## 错误处理
系统实现了统一的错误处理机制将所有异常转换为标准格式的JSON响应:
```json
{
"code": 400, // 错误状态码
"message": "参数错误", // 错误消息
"data": { // 错误详情
"field": "name",
"message": "名称不能为空"
}
}
```
## 中间件
系统实现了多个中间件提供日志记录、CORS支持和异常处理等功能:
```python
# 添加CORS中间件
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
allow_methods=settings.CORS_ALLOW_METHODS,
allow_headers=settings.CORS_ALLOW_HEADERS,
)
# 请求日志中间件
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""记录请求日志的中间件"""
# 实现细节

View File

@ -0,0 +1,115 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - 数据模型
## 数据模型概述
VWED任务模块的数据模型层定义了系统中的各种实体和它们之间的关系。主要数据模型包括任务定义、任务记录、任务块记录、数据缓存和任务模板等。
## 核心数据模型
### 任务定义模型 (TaskDef)
任务定义模型存储任务的基本信息和配置,是系统中最基础的数据实体。
**核心字段**
- `id`: 任务定义ID
- `name`: 任务名称
- `description`: 任务描述
- `task_type`: 任务类型
- `config`: 任务配置JSON
- `status`: 任务状态
- `version`: 任务版本号
**相关文件**: [data/models/taskdef.py](mdc:data/models/taskdef.py)
### 任务记录模型 (TaskRecord)
任务记录模型记录任务的执行历史和状态,每次任务执行都会生成一条任务记录。
**核心字段**:
- `id`: 记录ID
- `task_def_id`: 关联的任务定义ID
- `status`: 执行状态
- `result`: 执行结果
- `start_time`: 开始时间
- `end_time`: 结束时间
- `error_message`: 错误信息
**相关文件**: [data/models/taskrecord.py](mdc:data/models/taskrecord.py)
### 任务块记录模型 (BlockRecord)
任务块记录模型记录任务中各个执行块的执行情况,提供更细粒度的执行信息。
**核心字段**:
- `id`: 记录ID
- `task_record_id`: 关联的任务记录ID
- `block_id`: 块ID
- `block_type`: 块类型
- `status`: 执行状态
- `input_data`: 输入数据
- `output_data`: 输出数据
- `start_time`: 开始时间
- `end_time`: 结束时间
**相关文件**: [data/models/blockrecord.py](mdc:data/models/blockrecord.py)
### 数据缓存模型 (DataCache)
数据缓存模型用于存储任务执行过程中的临时数据和中间结果。
**核心字段**:
- `id`: 缓存ID
- `task_record_id`: 关联的任务记录ID
- `key`: 缓存键
- `value`: 缓存值
- `type`: 数据类型
- `expire_time`: 过期时间
**相关文件**: [data/models/datacache.py](mdc:data/models/datacache.py)
### 任务模板模型 (TaskTemplate)
任务模板模型存储预定义的任务模板,用户可以基于模板快速创建任务。
**核心字段**:
- `id`: 模板ID
- `name`: 模板名称
- `description`: 模板描述
- `config`: 模板配置JSON
- `version`: 模板版本号
- `task_type`: 任务类型
**相关文件**: [data/models/tasktemplate.py](mdc:data/models/tasktemplate.py)
## 数据关系图
```
TaskDef (任务定义)
↓ 1:n
TaskRecord (任务记录)
↓ 1:n
BlockRecord (任务块记录)
TaskDef ← 基于 ← TaskTemplate (任务模板)
TaskRecord
↓ 1:n
DataCache (数据缓存)
```
## 数据库会话管理
系统使用SQLAlchemy作为ORM框架支持同步和异步两种数据库访问方式。
**相关文件**: [data/session.py](mdc:data/session.py)
## 缓存系统
系统使用Redis作为分布式缓存提供高性能的数据缓存和共享。
**相关文件**: [data/cache.py](mdc:data/cache.py)

View File

@ -0,0 +1,30 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块系统 - 项目概览
VWED任务模块是一个基于FastAPI的Python后端系统主要用于管理和执行任务流程。系统采用多层架构包括客户端层、业务逻辑层、数据访问层、数据存储层和集成服务层。
## 主要功能
- 任务管理:提供任务的创建、配置、编辑和执行功能
- 低代码编辑器:用于可视化设计任务流程
- 组件管理:管理预设组件集合,提供组件选择和参数配置
- 任务调度:处理任务的执行、调度和状态管理
- 模板配置:创建和管理任务模板,维护模板版本
## 核心文件
- [app.py](mdc:app.py) - 主应用文件包含FastAPI应用的配置和路由注册
- [routes](mdc:routes) - 包含所有API路由定义
- [services](mdc:services) - 包含所有业务逻辑服务
- [data](mdc:data) - 数据访问层和数据模型定义
- [config](mdc:config) - 系统配置和设置
- [utils](mdc:utils) - 通用工具函数和辅助类
## 项目特色
- 基于asyncio的增强版任务调度系统
- 模块化设计,支持扩展组件
- 高度可配置的任务定义和执行流程
- 完善的错误处理和状态管理机制

View File

@ -0,0 +1,68 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - 系统架构
## 架构概览
VWED任务模块采用分层架构设计共分为五层
1. **客户端层**:包括任务管理界面、任务创建界面、任务编辑界面和任务监控与执行界面
2. **业务逻辑层**:包括任务定义模块、任务执行模块、组件管理模块、参数配置模块和模板配置模块
3. **数据访问层**包括任务定义DAO、任务记录DAO、任务块记录DAO、数据缓存DAO和模板DAO
4. **数据存储层**包括vwed_taskdef、vwed_taskrecord、vwed_blockrecord、vwed_datacache和vwed_tasktemplate等数据表
5. **集成服务层**包括AGV控制接口、站点管理接口、设备接口、外部系统接口和认证服务
## 核心模块
### 任务调度系统
任务调度系统是VWED任务模块的核心负责任务的分配、执行和管理。系统采用增强版任务调度器设计主要组件包括
- **EnhancedTaskScheduler**:主调度器,协调各组件工作
- **PriorityQueueManager**:优先级队列管理,实现多级队列
- **WorkerManager**:工作线程管理和监控
- **TaskPersistenceManager**:任务队列持久化,故障恢复
- **PeriodicTaskManager**:高级定时任务管理
相关代码:[services/enhanced_scheduler](mdc:services/enhanced_scheduler)
### 业务逻辑服务
业务逻辑服务层包含多个关键服务:
- **TaskService**[services/task_service.py](mdc:services/task_service.py) - 任务管理服务
- **TaskEditService**[services/task_edit_service.py](mdc:services/task_edit_service.py) - 任务编辑服务
- **TemplateService**[services/template_service.py](mdc:services/template_service.py) - 模板管理服务
- **ScriptService**[services/script_service.py](mdc:services/script_service.py) - 脚本管理服务
### API接口层
API接口层通过FastAPI框架实现主要包括以下路由模块
- **任务API**[routes/task_api.py](mdc:routes/task_api.py) - 任务管理相关接口
- **任务编辑API**[routes/task_edit_api.py](mdc:routes/task_edit_api.py) - 任务编辑相关接口
- **模板API**[routes/template_api.py](mdc:routes/template_api.py) - 模板管理相关接口
- **脚本API**[routes/script_api.py](mdc:routes/script_api.py) - 脚本管理相关接口
- **数据库API**[routes/database.py](mdc:routes/database.py) - 数据库操作相关接口
### 数据模型层
数据模型层定义了系统中的各种数据实体:
- **TaskDef**[data/models/taskdef.py](mdc:data/models/taskdef.py) - 任务定义模型
- **TaskRecord**[data/models/taskrecord.py](mdc:data/models/taskrecord.py) - 任务记录模型
- **BlockRecord**[data/models/blockrecord.py](mdc:data/models/blockrecord.py) - 任务块记录模型
- **DataCache**[data/models/datacache.py](mdc:data/models/datacache.py) - 数据缓存模型
- **TaskTemplate**[data/models/tasktemplate.py](mdc:data/models/tasktemplate.py) - 任务模板模型
## 系统流程
1. 用户通过客户端界面创建或编辑任务
2. API接口层接收请求并转发给相应的业务逻辑服务
3. 业务逻辑服务处理请求,操作数据模型,并提交任务至调度系统
4. 调度系统根据任务优先级和资源情况安排任务执行
5. 执行结果通过状态管理机制反馈给用户

View File

@ -0,0 +1,246 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - 任务执行机制
## 任务执行概述
VWED任务模块系统的任务执行机制负责解析任务定义并按照指定的流程执行任务。任务执行是一个复杂的过程涉及多个组件的协同工作。
## 核心组件
### 任务执行器 (TaskExecutor)
任务执行器是负责执行整个任务的核心组件,管理任务的生命周期和状态。
**相关文件**: [services/execution/task_executor.py](mdc:services/execution/task_executor.py)
**主要功能**:
- 任务初始化和准备
- 任务流程解析
- 执行状态管理
- 异常处理和恢复
- 结果收集和处理
### 任务块执行器 (BlockExecutor)
任务块执行器负责执行任务中的单个块,是任务执行的基本单元。
**相关文件**: [services/execution/block_executor.py](mdc:services/execution/block_executor.py)
**主要功能**:
- 块参数解析和验证
- 块逻辑执行
- 块状态管理
- 块间数据传递
- 执行结果处理
### 任务上下文 (TaskContext)
任务上下文维护任务执行过程中的所有数据和状态,提供数据共享和传递机制。
**相关文件**: [services/execution/task_context.py](mdc:services/execution/task_context.py)
**主要功能**:
- 变量存储和访问
- 状态追踪
- 上下文隔离
- 数据持久化
- 上下文恢复
### 块处理器 (BlockHandlers)
块处理器实现了各种类型任务块的具体执行逻辑,包括条件判断、循环、数据处理等。
**相关文件**: [services/execution/block_handlers.py](mdc:services/execution/block_handlers.py)
**主要功能**:
- 实现各类块的执行逻辑
- 参数处理和验证
- 块间流程控制
- 特定功能实现
## 执行流程
### 1. 任务提交
任务执行从任务提交开始用户通过API接口或系统内部逻辑提交任务至调度系统。
```python
# 通过API提交任务
@router.post("/{task_id}/execute", response_model=ResponseModel)
async def execute_task(
task_id: int,
execution_params: Optional[TaskExecutionParams] = Body(None),
background_tasks: BackgroundTasks = BackgroundTasks(),
):
# 提交任务到调度系统
result = await task_service.execute_task(task_id, execution_params, background_tasks)
return format_response(message="任务提交成功", data=result)
```
### 2. 任务调度
调度系统接收任务请求,根据优先级和资源情况,将任务分配给工作线程。
```python
# 任务调度
async def schedule_task(self, task_func, priority=0, *args, **kwargs):
# 创建任务
task = Task(task_func, args, kwargs, priority)
# 加入优先级队列
await self.queue_manager.put_task(task)
# 返回任务ID
return task.id
```
### 3. 任务初始化
任务执行器接收到任务后,进行初始化操作,包括加载任务定义、创建执行上下文等。
```python
# 任务初始化
async def initialize(self):
# 加载任务定义
self.task_def = await self.load_task_definition()
# 创建任务记录
self.task_record = await self.create_task_record()
# 初始化执行上下文
self.context = TaskContext(self.task_record.id, self.execution_params)
# 加载初始数据
await self.load_initial_data()
```
### 4. 任务执行
任务执行器按照任务定义的流程,依次执行各个任务块。
```python
# 任务执行
async def execute(self):
try:
# 更新任务状态为执行中
await self.update_task_status(TaskStatus.RUNNING)
# 获取起始块
current_block = self.get_start_block()
# 循环执行任务块,直到结束或出错
while current_block and not self.should_stop:
# 执行当前块
block_result = await self.execute_block(current_block)
# 记录块执行结果
await self.record_block_result(current_block, block_result)
# 获取下一个要执行的块
current_block = self.get_next_block(current_block, block_result)
# 更新任务状态为完成
await self.update_task_status(TaskStatus.COMPLETED)
except Exception as e:
# 异常处理
await self.handle_exception(e)
```
### 5. 块执行
块执行器负责执行单个任务块,根据块类型调用相应的处理逻辑。
```python
# 块执行
async def execute_block(self, block_definition):
# 创建块执行记录
block_record = await self.create_block_record(block_definition)
try:
# 获取块类型
block_type = block_definition.get("type")
# 获取对应的块处理器
handler = self.get_block_handler(block_type)
# 前置处理
await self.pre_execute_block(block_definition, block_record)
# 执行块逻辑
result = await handler.execute(block_definition, self.context)
# 后置处理
await self.post_execute_block(block_definition, block_record, result)
return result
except Exception as e:
# 处理块执行异常
await self.handle_block_exception(block_definition, block_record, e)
raise
```
### 6. 结果处理
任务执行完成后,执行器会收集执行结果,更新任务状态,并进行必要的清理工作。
```python
# 结果处理
async def process_result(self):
# 收集执行结果
result = self.collect_execution_result()
# 更新任务记录
await self.update_task_record(result)
# 触发后续动作
await self.trigger_actions(result)
# 资源清理
await self.cleanup()
return result
```
## 执行特性
### 上下文管理
系统使用TaskContext管理任务执行过程中的数据和状态提供了变量存储、检索和作用域管理功能。
```python
# 上下文示例
context = TaskContext(task_record_id)
# 设置变量
await context.set_variable("customer_name", "张三")
# 获取变量
customer_name = await context.get_variable("customer_name")
# 检查变量是否存在
if await context.has_variable("order_id"):
# 处理逻辑
pass
```
### 错误处理
系统实现了多层次的错误处理机制,确保任务执行的稳定性和可靠性。
1. **块级错误处理**:每个块可以定义自己的错误处理策略
2. **任务级错误处理**:任务可以定义全局错误处理策略
3. **系统级错误处理**:系统提供默认的错误处理机制
### 状态追踪
系统对任务执行过程中的状态进行全面追踪,包括任务状态、块状态和变量状态。
### 超时管理
系统支持任务和块级别的超时设置,防止任务长时间未完成占用系统资源。
### 事务支持
系统支持事务处理,可以在任务执行过程中进行数据库事务操作,确保数据一致性。

View File

@ -0,0 +1,110 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - 任务调度系统
## 增强版任务调度系统概述
增强版任务调度系统是VWED任务模块的核心组件提供高性能、可靠性和可扩展性的任务处理能力。系统采用模块化设计包含多个协同工作的组件。
## 核心组件
### EnhancedScheduler
主调度器,负责协调各个组件工作,是整个调度系统的核心。它管理任务的生命周期,从提交到完成的全过程。
### PriorityQueueManager
优先级队列管理器,实现多级优先级队列,通过动态阈值算法优化任务分布,确保高优先级任务优先处理,同时避免低优先级任务长时间饥饿。
### WorkerManager
工作线程管理器,负责创建和管理工作线程池,支持动态调整线程池大小,进行心跳监控,及时发现异常并进行恢复。
### PeriodicTaskManager
定时任务管理器支持Cron表达式提供高级定时任务管理功能适用于需要周期性执行的任务。
### TaskPersistenceManager
任务持久化管理器,负责将任务队列持久化到存储系统,提供故障恢复机制,确保系统重启后任务不丢失。
## 工作流程
1. 任务提交通过API接口或内部服务提交任务到调度系统
2. 任务接收EnhancedScheduler接收任务并交由PriorityQueueManager进行优先级排队
3. 任务调度WorkerManager根据系统负载情况从队列中取出任务分配给工作线程
4. 任务执行:工作线程执行任务,并将执行状态反馈给调度器
5. 状态管理:调度器更新任务状态,并在必要时触发相应的回调函数
6. 结果处理:任务执行完成后,处理执行结果,更新数据库状态
## 系统特性
### 动态工作线程池
系统可根据任务负载情况自动调整工作线程数量,在最小工作线程数和最大工作线程数之间动态调整,以优化资源利用率。
```python
# 动态调整工作线程数
async def adjust_worker_count(self, current_queue_size: int):
"""根据队列大小动态调整工作线程数量"""
if current_queue_size > self.high_watermark and self.worker_count < self.max_worker_count:
# 增加工作线程
new_workers = min(self.worker_count + 2, self.max_worker_count) - self.worker_count
if new_workers > 0:
await self.add_workers(new_workers)
elif current_queue_size < self.low_watermark and self.worker_count > self.min_worker_count:
# 减少工作线程(只减空闲的)
idle_workers = len([w for w in self.workers.values() if w.status == WorkerStatus.IDLE])
if idle_workers > 2: # 保留一些空闲工作线程以应对突发负载
to_remove = min(idle_workers - 2, self.worker_count - self.min_worker_count)
if to_remove > 0:
await self.remove_workers(to_remove)
```
### 任务优先级管理
系统支持任务优先级设置,优先级越高的任务越先被调度执行。系统还实现了平衡调度策略,避免低优先级任务长时间得不到执行。
### 健壮性保障
系统实现了全面的异常处理和故障恢复机制:
1. 工作线程异常自动恢复
2. 系统重启后任务队列恢复
3. 僵尸任务检测和清理
4. 超时任务处理
### 监控和统计
系统提供丰富的监控和统计信息,包括:
1. 任务执行统计(成功率、平均执行时间等)
2. 队列状态监控(各优先级队列长度、等待时间等)
3. 资源使用监控CPU、内存使用率等
4. 工作线程健康状态
## 调度系统初始化
系统在应用启动时初始化,在应用关闭时优雅停止:
```python
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动前的初始化操作
# 启动增强版任务调度器
from services.enhanced_scheduler import scheduler
await scheduler.start(worker_count=settings.TASK_SCHEDULER_MIN_WORKER_COUNT)
logger.info(f"增强版任务调度器已启动,最小工作线程数: {settings.TASK_SCHEDULER_MIN_WORKER_COUNT},最大工作线程数: {settings.TASK_SCHEDULER_MAX_WORKER_COUNT}")
yield
# 应用程序关闭前的清理操作
# 停止增强版任务调度器
from services.enhanced_scheduler import scheduler
await scheduler.stop()
logger.info("增强版任务调度器已停止")
```

View File

@ -0,0 +1,152 @@
---
description:
globs:
alwaysApply: false
---
# VWED任务模块 - 工具和组件
## 工具函数概述
VWED任务模块系统包含多种工具函数和辅助类用于支持系统的各项功能。这些工具函数被广泛应用于系统的各个模块中。
### 日志工具
系统使用自定义的日志工具,支持多级别日志记录和日志文件管理。
**相关文件**: [utils/logger.py](mdc:utils/logger.py)
**主要功能**:
- 多级别日志DEBUG, INFO, WARNING, ERROR, CRITICAL
- 日志文件轮转
- 格式化日志输出
- 控制台和文件双重输出
### 内置函数
系统提供了一系列内置函数,用于在任务执行过程中进行常见操作。
**相关文件**: [utils/built_in_functions.py](mdc:utils/built_in_functions.py)
**主要功能**:
- 字符串处理函数
- 日期时间处理函数
- 数学计算函数
- 数据转换函数
- 条件判断函数
### 加密工具
系统提供了加密和解密功能,用于敏感数据的保护。
**相关文件**: [utils/crypto_utils.py](mdc:utils/crypto_utils.py)
**主要功能**:
- AES加密/解密
- RSA加密/解密
- 哈希函数
- Base64编码/解码
- JWT令牌处理
### 组件管理器
组件管理器负责加载、注册和管理系统中的预设组件。
**相关文件**: [utils/component_manager.py](mdc:utils/component_manager.py)
**主要功能**:
- 组件注册与发现
- 组件参数验证
- 组件生命周期管理
- 组件依赖管理
### API响应工具
统一处理API响应格式的工具函数。
**相关文件**: [utils/api_response.py](mdc:utils/api_response.py)
**主要功能**:
- 标准响应格式化
- 错误响应处理
- 分页响应处理
### 数据验证工具
用于验证用户输入和数据完整性的工具。
**相关文件**: [utils/validator.py](mdc:utils/validator.py)
**主要功能**:
- 数据类型验证
- 格式验证
- 业务规则验证
- 跨字段验证
### 数据库迁移工具
用于管理数据库架构变更的工具。
**相关文件**: [utils/db_migration.py](mdc:utils/db_migration.py)
**主要功能**:
- 数据库架构迁移
- 版本控制
- 数据迁移
- 回滚功能
## 预设组件概述
预设组件是系统中预定义的功能模块,可以被用户在任务设计器中拖拽和配置,构建任务流程。
### 基础组件
系统提供了一系列基础组件,作为所有预设组件的基类。
**相关文件**: [components/base_components.py](mdc:components/base_components.py)
### 组件类型
系统中的预设组件主要分为以下几类:
1. **流程控制组件**
- 条件判断组件
- 循环组件
- 并行执行组件
- 延时组件
2. **数据处理组件**
- 数据转换组件
- 数据过滤组件
- 数据聚合组件
- 数据映射组件
3. **集成组件**
- AGV控制组件
- 站点管理组件
- 设备控制组件
- API调用组件
4. **业务组件**
- 库位操作组件
- 订单处理组件
- 库存管理组件
- 质检组件
### 组件配置
每个组件都有一系列可配置的参数,用户可以通过任务编辑界面进行配置。参数分为以下几类:
1. **基本参数**:组件的必要配置,如名称、描述等
2. **输入参数**:组件的输入数据配置
3. **输出参数**:组件处理后的输出数据配置
4. **高级参数**:特定组件的高级配置选项
### 组件执行机制
组件的执行由调度系统控制,具有以下特点:
1. **生命周期**:初始化 -> 参数验证 -> 执行 -> 清理
2. **异常处理**:每个组件都有自己的异常处理机制
3. **上下文传递**:组件之间通过上下文传递数据
4. **状态跟踪**:系统会记录每个组件的执行状态和结果

8
.idea/.gitignore generated vendored Normal file
View File

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

8
.idea/VWED_task.iml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="pytf" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
.idea/misc.xml generated Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="pyvllm12" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="pytf" project-jdk-type="Python SDK" />
</project>

8
.idea/modules.xml generated Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/VWED_task.iml" filepath="$PROJECT_DIR$/.idea/VWED_task.iml" />
</modules>
</component>
</project>

46
Dockerfile Normal file
View File

@ -0,0 +1,46 @@
FROM python:3.12-slim
# 设置工作目录
WORKDIR /app
# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
APP_ENV=production \
TZ=Asia/Shanghai \
PIP_NO_CACHE_DIR=1 \
PIP_DISABLE_PIP_VERSION_CHECK=1 \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8
# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
default-libmysqlclient-dev \
vim \
locales \
fonts-wqy-zenhei \
fonts-wqy-microhei \
tk-dev \
python3-tk \
&& rm -rf /var/lib/apt/lists/* \
&& localedef -i zh_CN -c -f UTF-8 -A /usr/share/locale/locale.alias zh_CN.UTF-8
# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 创建日志目录
RUN mkdir -p logs && chmod -R 755 logs
# 复制项目文件
COPY . .
# 暴露端口
EXPOSE 8000
# 启动命令
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]

696
README.md Normal file
View File

@ -0,0 +1,696 @@
# VWED任务模块
## 项目概述
VWED任务模块是AMR自主移动机器人调度系统的核心组件之一用于管理和监控机器人任务的全生命周期。该模块提供了低代码配置工具使用户能够通过可视化界面设计和配置复杂的机器人任务流程无需编写大量代码。系统支持任务版本控制、流程编辑、测试执行和源代码生成等功能大幅提高了机器人任务配置的效率和灵活性。
## 项目架构
VWED任务模块采用分层架构设计遵循关注点分离原则各层次职责明确便于维护和扩展
### 1. 架构层次
- **表现层API层**处理HTTP请求和响应提供RESTful API接口
- **业务逻辑层Service层**:实现核心业务逻辑,处理任务和工作流的创建、执行和管理
- **代理层Agents层**:提供智能代理服务,支持任务自动化和优化(已设计,尚未实现)
- **领域层Core层**:定义核心领域模型和业务规则,包含工作流引擎和组件系统
- **数据层Data层**:提供数据模型定义和数据访问功能,支持任务、流程、组件等数据的持久化
- **智能服务层**:提供向量化和向量存储服务,支持知识检索和智能决策(已设计,尚未实现)
- **基础设施层**:提供数据持久化、日志记录、配置管理等基础服务
### 2. 设计模式
- **工厂模式**:用于组件的创建和注册
- **策略模式**:用于实现不同类型组件的执行逻辑
- **观察者模式**:用于任务状态变更通知
- **命令模式**:用于任务执行和撤销操作
- **组合模式**:用于构建组件树和工作流结构
- **仓储模式**:用于数据访问和持久化
### 3. 系统架构图
```
+-------------------+
| 用户界面 |
+--------+----------+
|
v
+------------------+ +----------+---------+
| | | |
| 外部知识库 +------------->+ API层 |
| | | |
+------------------+ +----+------+--------+
| |
| |
+----------------------------+ |
| |
v v
+----------+---------+ +---------+----------+
| | | |
| Agent系统 |<------------>| 业务服务层 |
| (包含LLM功能) | | |
+----+---------------+ +--------+-----------+
| |
| |
| v
| +--------+-----------+
| | |
| | 工作流引擎 |
| | |
| +--------+-----------+
| |
| |
| v
| +--------+-----------+
| | |
+----------------------------->+ 组件系统 |
| | |
| +--------+-----------+
| |
v v
+----+---------------+ +--------+-----------+
| | | |
| 智能服务层 | | 外部系统/设备 |
| (向量化和向量存储) | | |
+----+---------------+ +--------------------+
|
|
v
+----+---+
| |
|向量数据库|
| |
+--------+
```
> **注意**架构图中的Agent系统、外部知识库、智能服务层和向量数据库部分已完成设计但尚未实现。这些组件将在后续版本中逐步开发和集成。
## 项目结构
```
VWED_task/
├── routes/ # API路由定义
│ ├── task_api.py # 任务相关API
│ ├── task_edit_api.py # 任务编辑API
│ ├── script_api.py # 脚本相关API
│ ├── template_api.py # 模板相关API
│ ├── common_api.py # 通用API
│ ├── database.py # 数据库API
│ └── model/ # API模型定义
├── services/ # 业务服务层
│ ├── task_service.py # 任务服务
├── agents/ # 智能代理层(已设计,尚未实现)
│ ├── base_agent.py # 代理基类
│ ├── llm/ # 大语言模型集成
│ ├── prompts/ # 提示词模板
│ ├── tools/ # 代理工具集
│ └── teams/ # 代理团队协作
├── components/ # 组件实现
│ ├── base_components.py # 基础组件
├── core/ # 核心功能模块
│ ├── component.py # 组件基类定义
│ ├── context.py # 执行上下文
│ ├── exceptions.py # 异常定义
│ └── workflow.py # 工作流引擎
├── data/ # 数据存储
│ ├── models/ # 数据模型定义
│ │ ├── base.py # 基础模型
│ ├── session.py # 数据库会话管理
│ └── repositories/ # 数据仓储实现
├── migrations/ # 数据库迁移
│ ├── versions/ # 迁移版本
│ ├── env.py # 迁移环境配置
│ ├── script.py.mako # 迁移脚本模板
│ └── alembic.ini # Alembic配置
├── scripts/ # 脚本工具
│ ├── generate_migration.py # 生成迁移脚本
│ └── run_migration.py # 执行迁移脚本
├── utils/ # 工具函数
│ ├── logger.py # 日志工具
│ ├── validators.py # 数据验证工具
│ └── helpers.py # 辅助函数
├── config/ # 配置文件
│ ├── database.py # 数据库配置
├── logs/ # 日志文件
├── docs/ # 文档
├── tests/ # 测试代码
│ ├── unit/ # 单元测试
│ ├── integration/ # 集成测试
│ └── fixtures/ # 测试数据
├── app.py # 应用入口
├── Dockerfile # Docker配置文件
├── docker-compose.yml # Docker Compose配置
└── requirements.txt # 依赖包列表
```
## 核心功能
### 1. 任务管理
- **任务创建**:支持创建普通任务和定时任务
- **任务监控**:实时监控任务执行状态和进度
- **任务操作**:支持启动、暂停、取消、重试等操作
- **任务历史**:记录任务执行历史和结果
- **版本控制**:支持任务版本管理,可以回滚到历史版本
- **任务测试**:支持在测试环境中执行任务,验证任务配置
### 2. 任务编辑器
VWED任务模块提供了强大的可视化编辑器支持以下功能
- **流程图设计**:通过拖拽方式设计任务流程图
- **属性配置**:配置组件和连接的属性
- **变量管理**:定义和管理任务执行过程中的变量
- **撤销/重做**:支持编辑操作的撤销和重做
- **源代码生成**:自动生成任务执行的源代码
- **版本备份**:支持任务配置的版本备份和恢复
### 3. 组件库
VWED任务模块提供了丰富的组件库用户可以通过拖拽组件和配置参数的方式设计复杂的任务流程
- **子任务组件**:支持任务的模块化和复用
- **脚本组件**支持编写自定义JavaScript脚本
- **HTTP请求组件**:支持与外部系统进行通信
- **任务组件**:提供任务数据管理和状态控制功能
- **流程组件**:提供条件判断、循环、并行执行等流程控制功能
- **基础组件**提供数据验证、ID生成、时间处理等基础功能
- **库位组件**:提供库位管理和操作功能
- **机器人调度组件**:提供机器人选择、控制和状态监控功能
- **设备组件**:提供与外部设备通信的功能
### 4. 智能代理系统(已设计,尚未实现)
- **任务代理**:自动分析和优化任务流程
- **LLM集成**:集成大语言模型,提供智能决策支持
- **代理工具**:提供丰富的工具集,支持代理执行各种操作
- **团队协作**:支持多代理协作完成复杂任务
- **知识检索**:从外部知识库中检索相关信息,辅助决策
### 5. 智能服务层(已设计,尚未实现)
- **向量化服务**:将文本、图像等数据转换为向量表示
- **知识检索**:基于语义相似度进行知识检索
- **嵌入模型**:提供多种嵌入模型,支持不同类型数据的向量化
- **向量存储**:高效存储和检索向量数据
### 6. 工作流引擎
- **流程执行**:解析和执行任务流程图
- **上下文管理**:管理任务执行过程中的变量和状态
- **错误处理**:提供异常捕获和处理机制
- **并行执行**:支持多分支并行执行
- **动态加载**:支持动态加载和执行组件
### 7. 数据模型
系统提供了完善的数据模型,支持任务管理的各个方面:
- **任务模型**:存储任务基本信息和配置
- **任务版本**:管理任务的不同版本
- **任务记录**:记录任务的执行情况
- **任务流程节点**:存储流程图中的节点信息
- **任务流程连接**:存储流程图中的连接信息
- **任务变量定义**:管理任务中使用的变量
- **任务编辑历史**:记录编辑操作,支持撤销/重做
- **任务备份**:存储任务的备份数据
## 执行业务流程
### 系统启动流程
1. 应用启动app.py
2. 加载配置信息config模块
3. 初始化日志系统utils.logger
4. 初始化数据库连接data.session
5. 注册所有组件config.component_registry
6. 注册API路由api模块
7. 启动HTTP服务uvicorn
### 任务创建流程
1. 用户在VWED任务主页面点击"定义新任务"按钮
2. 前端发送创建任务请求到API层/api/tasks
3. API层调用任务服务task_service.py创建任务记录
4. 系统创建任务并返回任务ID
5. 前端跳转到任务编辑页面
6. 用户通过拖拽组件设计任务流程
7. 前端发送保存流程请求到API层/api/workflows
8. API层调用工作流服务workflow_service.py保存流程配置
9. 系统将流程配置保存到数据库,创建新版本
### 任务编辑流程
1. 用户打开任务编辑页面
2. 系统加载任务的最新版本和流程图数据
3. 用户通过拖拽组件和连接设计流程图
4. 用户配置组件属性和变量
5. 系统记录每一步编辑操作,支持撤销/重做
6. 用户点击保存按钮,系统创建新版本
7. 用户可以点击测试按钮,在测试环境中执行任务
8. 用户可以点击生成源码按钮,系统生成任务执行代码
### 任务执行流程
1. 用户在任务列表中选择任务并点击"执行"按钮
2. 前端发送执行任务请求到API层/api/tasks/{id}/execute
3. API层调用任务服务task_service.py创建任务记录
4. 任务服务加载任务配置和工作流定义
5. 任务服务初始化执行上下文context.py
6. 任务服务调用工作流引擎workflow.py执行任务
7. 工作流引擎解析任务流程图并按顺序执行各组件
8. 组件执行结果存储在上下文中,供后续组件使用
9. 系统实时更新任务状态和进度
10. 任务执行完成后,系统记录执行结果和日志
### 智能任务执行流程(已设计,尚未实现)
1. 用户在任务列表中选择任务并点击"智能执行"按钮
2. 前端发送智能执行任务请求到API层
3. API层调用Agent系统进行任务分析和优化
4. Agent系统从外部知识库检索相关知识
5. Agent系统基于LLM和检索到的知识生成执行计划
6. Agent系统调用业务服务层执行优化后的任务
7. 业务服务层调用工作流引擎执行任务
8. 执行过程中Agent系统持续监控任务状态
9. 遇到异常情况时Agent系统自动调整执行策略
10. 任务执行完成后Agent系统生成执行报告和优化建议
## 交互方式
VWED任务模块提供多种交互方式满足不同场景的需求
### 1. 用户界面交互
- **任务列表界面**
- 展示所有任务及其状态
- 提供任务筛选、搜索和排序功能
- 支持任务的创建、编辑、删除、执行等操作
- 显示任务执行状态和进度
- **任务编辑界面**
- 提供可视化的流程设计工具
- 左侧组件面板:展示可用组件
- 中央流程图编辑区:通过拖拽设计任务流程
- 右侧属性面板:配置组件参数
- 顶部工具栏:保存、运行、测试、撤销、重做等操作
- **任务监控界面**
- 实时显示任务执行状态和进度
- 展示任务执行日志和变量值
- 提供任务暂停、取消、重试等操作
## 技术栈
- **后端**FastAPI (Python)
- **数据库**SQLAlchemy ORM支持MySQL、PostgreSQL等
- **前端**React + Ant Design低代码编辑器
- **API文档**Swagger UI自动生成
- **工作流引擎**自研基于DAG的工作流引擎
- **组件系统**:可扩展的组件注册和执行系统
- **数据迁移**Alembic
- **智能代理**:基于大语言模型的智能代理系统(已设计,尚未实现)
- **向量数据库**:支持高效的向量存储和检索(已设计,尚未实现)
- **嵌入模型**:支持文本、图像等数据的向量化(已设计,尚未实现)
## 部署说明
### 环境要求
- Python 3.11+
- 数据库MySQL/PostgreSQL
- Node.js 14+(前端开发)
### 详细运行方法
#### 方法一使用Docker运行推荐
Docker是最简单的部署方式可以避免环境配置问题。
##### 1. 构建并运行Docker镜像
```bash
# 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 构建Docker镜像
docker build -t vwed-task:latest .
# 运行Docker容器
docker run -d -p 8000:8000 --name vwed-task-container vwed-task:latest
```
##### 2. 使用Docker Compose运行包含数据库和缓存
```bash
# 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 使用Docker Compose构建并启动所有服务
docker-compose up -d
```
##### 3. 验证服务是否正常运行
```bash
# 查看容器状态
docker ps
# 或者使用Docker Compose查看
docker-compose ps
# 查看应用日志
docker logs vwed-task-container
# 或者
docker-compose logs app
```
##### 4. 停止和删除容器
```bash
# 停止容器
docker stop vwed-task-container
docker rm vwed-task-container
# 或者使用Docker Compose
docker-compose down
```
#### 方法二:本地运行(不同操作系统)
##### 前提条件
- 安装CondaMiniconda或Anaconda
- 安装Git
- 安装数据库MySQL或PostgreSQL
##### Windows系统
```bash
# 1. 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 2. 创建并激活Conda环境 推荐使用3.11
conda create -n pytf python=3.11
conda activate pytf
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置数据库连接
# 编辑 config/database.py 文件,设置正确的数据库连接信息
# 5. 启动应用
python app.py
```
### 数据库配置说明
在运行应用前,需要修改`config/database.py`文件中的数据库配置将默认的数据库连接信息替换为您自己的本地或云上的MySQL数据库
```python
# 数据库连接配置
DB_CONFIG = ConfigDict(
default=dict(
dialect='mysql',
driver='pymysql',
username='your_username', # 修改为您的数据库用户名
password='your_password', # 修改为您的数据库密码
host='your_host', # 修改为您的数据库主机地址本地通常为localhost或127.0.0.1,云数据库使用对应的连接地址
port=3306, # 修改为您的数据库端口默认MySQL为3306
database='vwed_task', # 数据库名称,可以保持不变或修改为您想使用的数据库名
charset='utf8mb4'
),
test=dict(
dialect='sqlite',
database=':memory:'
)
)
```
如果您使用的是云数据库如阿里云RDS、AWS RDS等请确保
1. 数据库已创建并可以访问
2. 数据库用户有足够的权限至少需要CREATE、ALTER、SELECT、INSERT、UPDATE、DELETE权限
3. 数据库服务器的防火墙允许从您的应用服务器访问
您也可以通过环境变量来设置数据库连接信息,这样就不需要修改源代码:
```bash
# Windows
set VWED_ENV=default
set DB_HOST=your_host
set DB_PORT=3306
set DB_USER=your_username
set DB_PASSWORD=your_password
set DB_NAME=vwed_task
# macOS/Linux
export VWED_ENV=default
export DB_HOST=your_host
export DB_PORT=3306
export DB_USER=your_username
export DB_PASSWORD=your_password
export DB_NAME=vwed_task
```
系统启动时会自动检查数据库是否存在,如果不存在会自动创建数据库和所需的表结构。
##### macOS系统
```bash
# 1. 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 2. 创建并激活Conda环境
conda create -n pytf python=3.11
conda activate pytf
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置数据库连接
# 编辑 config/database.py 文件,设置正确的数据库连接信息
# 5. 启动应用
python app.py
```
##### Linux系统
```bash
# 1. 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 2. 创建并激活Conda环境
conda create -n pytf python=3.11
conda activate pytf
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置数据库连接
# 编辑 config/database.py 文件,设置正确的数据库连接信息
# 5. 启动应用
python app.py
```
#### 方法三使用虚拟环境不使用Conda不推荐
**注意:此方法不推荐使用**因为项目依赖复杂使用Conda可以更好地管理依赖关系和解决潜在的兼容性问题。此外某些依赖可能需要特定的编译环境Conda能更好地处理这些情况。如果您仍然希望使用此方法请按照以下步骤操作
##### Windows系统
```bash
# 1. 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 2. 创建并激活虚拟环境
python -m venv venv
.\venv\Scripts\activate
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置数据库连接
# 编辑 config/database.py 文件
# 5. 启动应用
python app.py
```
##### macOS/Linux系统
```bash
# 1. 克隆代码仓库
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
# 2. 创建并激活虚拟环境
python -m venv venv
source venv/bin/activate
# 3. 安装依赖
pip install -r requirements.txt
# 4. 配置数据库连接
# 编辑 config/database.py 文件
# 5. 启动应用
python app.py
```
### 安装步骤
1. 克隆代码库
2. 安装依赖:`pip install -r requirements.txt`
3. 配置数据库连接:修改`config/database.py`
4. 启动应用:`python app.py`
## 使用示例
### 创建简单任务
1. 进入VWED任务主页面
2. 点击"定义新任务"按钮
3. 输入任务名称"测试任务",选择"普通任务"类型
4. 在编辑页面拖入"选择执行机器人"组件
5. 配置机器人选择参数
6. 拖入"机器人通用动作"组件,配置目标站点
7. 连接组件,形成执行流程
8. 保存任务并执行
### 使用版本控制
1. 打开现有任务的编辑页面
2. 修改任务流程或组件配置
3. 点击"保存"按钮,系统自动创建新版本
4. 在版本历史中可以查看所有历史版本
5. 可以选择任意历史版本进行查看或恢复
### 使用撤销/重做功能
1. 在编辑页面进行操作(如添加节点、移动节点等)
2. 如需撤销操作,点击工具栏中的"撤销"按钮
3. 如需重做已撤销的操作,点击"重做"按钮
4. 系统会记录编辑会话中的所有操作历史
## 常见问题
1. **任务执行失败怎么办?**
- 查看任务执行日志,定位失败原因
- 在测试环境中验证任务配置
- 修改任务配置,解决问题后重试
2. **如何调试复杂任务?**
- 使用测试功能验证任务配置
- 查看执行日志和变量值
- 使用条件断点和单步执行
3. **如何管理大量任务?**
- 使用任务模板功能创建可复用的任务模板
- 使用子任务功能将复杂任务拆分为多个子任务
- 使用标签和分类功能组织任务
## 联系方式
如有问题或建议,请联系系统管理员或开发团队。
# Docker部署说明
## 使用Docker部署VWED任务模块
本项目支持使用Docker进行部署以下是部署步骤
### 前提条件
- 安装Docker和Docker Compose
- 确保端口8000、3306和6379未被占用
### 部署步骤
1. 克隆代码仓库
```bash
git clone http://192.168.1.2:8418/jzw/vwed_task_modules.git
cd vwed_task
```
2. 使用Docker Compose构建并启动服务
```bash
docker-compose up -d
```
这将启动三个容器:
- vwed-task: 应用服务
- vwed-mysql: MySQL数据库
- vwed-redis: Redis缓存
3. 验证服务是否正常运行
```bash
docker-compose ps
```
4. 访问API文档
打开浏览器,访问 http://localhost:8000/docs 查看API文档。
### 环境变量配置
可以通过修改`docker-compose.yml`文件中的环境变量来配置应用:
```yaml
environment:
- VWED_ENV=default # 环境名称
- DEBUG=false # 是否开启调试模式
- DB_HOST=db # 数据库主机
- DB_PORT=3306 # 数据库端口
- DB_USER=root # 数据库用户名
- DB_PASSWORD=password # 数据库密码
- DB_NAME=vwed_task # 数据库名称
- REDIS_HOST=redis # Redis主机
- REDIS_PORT=6379 # Redis端口
- REDIS_DB=0 # Redis数据库索引
```
### 单独构建Docker镜像
如果需要单独构建Docker镜像可以使用以下命令
```bash
docker build -t vwed-task:latest .
```
### 停止服务
```bash
docker-compose down
```
如果需要同时删除数据卷(会删除所有数据):
```bash
docker-compose down -v
```
### 查看日志
```bash
# 查看所有服务的日志
docker-compose logs
# 查看特定服务的日志
docker-compose logs app
docker-compose logs db
docker-compose logs redis
# 实时查看日志
docker-compose logs -f app
```

View File

@ -0,0 +1,357 @@
### 1. 获取天风任务列表
#### 接口描述
获取系统中所有任务的列表信息,支持分页查询、条件筛选和排序。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-task/list`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| pageNum | Integer | 否 | 页码默认为1 |
| pageSize | Integer | 否 | 每页记录数默认为10 |
| keyword | String | 否 | 关键字搜索(任务名称) |
| status | Integer | 否 | 任务状态筛选 |
| sortField | String | 否 | 排序字段 |
| sortOrder | String | 否 | 排序方式asc升序、desc降序 |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"total": 3,
"list": [
{
"id": "193f8412-fa0d-4b6d-9648-70bceacd6629",
"label": "test1",
"version": 19,
"templateName": "userTemplate",
"periodicTask": false,
"ifEnable": 0,
"status": 0,
"createDate": "2023-05-10 14:30:22",
"remark": "备注信息"
},
{
"id": "734749d1-0fdf-4a06-9fb7-8f991953d5e5",
"label": "test",
"version": 3,
"templateName": "userTemplate",
"periodicTask": true,
"ifEnable": 1,
"status": 0,
"createDate": "2023-05-15 09:45:18",
"remark": "定时任务"
},
{
"id": "7c6aac36-652b-4314-9433-f5788e9e7adb",
"label": "test1-备份",
"version": 1,
"templateName": "userTemplate",
"periodicTask": false,
"ifEnable": 0,
"status": 0,
"createDate": "2023-05-16 11:22:36",
"remark": "备份1"
}
],
"pageNum": 1,
"pageSize": 10,
"totalPages": 1
}
}
```
### 2. 创建任务
#### 接口描述
创建一个新任务,设置任务的基本信息。创建任务时只需提供任务名称和任务类型两个必填项。系统会自动将新建任务与当前已激活的模板进行关联,系统中有且只有一个处于激活状态的模板。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-task/create`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| label | String | 是 | 任务名称 |
| taskType | Integer | 是 | 任务类型1-普通任务2-定时任务 |
| mapId | Integer | 是 | 相关地图ID|
| remark | String | 否 | 任务备注 |
| period | Integer | 否 | 周期时间(毫秒) |
| delay | Integer | 否 | 延迟时间毫秒默认3000 |
| releaseSites | Boolean | 否 | 是否释放站点默认true |
| token | String | 否 | 用户token值用于认证 |
| tenantId | String | 否 | 租户ID用于多租户隔离默认为"default" |
#### 请求示例
```json
{
"label": "新任务",
"taskType": 1,
"remark": "测试用任务",
"token": "user_authentication_token",
"tenantId": "tenant1"
}
```
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": "193f8412-fa0d-4b6d-9648-70bceacd6629",
"label": "新任务",
"version": 1,
"templateName": "userTemplate",
"periodicTask": false,
"status": 0,
"createDate": "2023-05-10 14:30:22"
}
}
### 3. 删除任务
#### 接口描述
删除指定的一个或多个任务。
#### 请求方式
- **HTTP方法**: DELETE
- **接口路径**: `/api/vwed-task/delete`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| ids | Array | 是 | 要删除的任务ID数组 |
#### 请求示例
```json
{
"ids": ["193f8412-fa0d-4b6d-9648-70bceacd6629", "734749d1-0fdf-4a06-9fb7-8f991953d5e5"]
}
```
#### 响应参数
```json
{
"code": 200,
"message": "删除成功",
"data": null
}
```
### 5. 批量导出任务
#### 接口描述
导出多个指定任务的配置,返回加密的专有格式文件(.vtex)。导出时会自动去除ID、创建时间、更新时间、版本和删除标记等系统相关字段仅保留任务的功能性配置数据。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-task/export-batch`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| ids | Array | 是 | 要导出的任务ID数组 |
#### 请求示例
```json
{
"ids": ["193f8412-fa0d-4b6d-9648-70bceacd6629", "734749d1-0fdf-4a06-9fb7-8f991953d5e5"]
}
```
#### 响应参数
文件下载响应Content-Type为application/octet-stream文件为加密的二进制格式(.vtex),包含以下自动去除系统相关字段的任务定义信息:
- 已移除id, created_at, updated_at, version, deleted 等系统字段
- 保留label(任务名称), detail(任务详情), period(周期时间), delay(延迟时间)等功能性字段
#### 响应头信息
```
Content-Disposition: attachment; filename=tasks_export_2.vtex
Content-Type: application/octet-stream
X-Content-Type-Options: nosniff
```
### 7. 导入任务
#### 接口描述
通过导入任务配置文件(.vtex)创建新任务。支持批量导入多个任务,系统会自动为每个任务生成唯一的名称以避免冲突。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-task/import`
- **Content-Type**: multipart/form-data
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| file | File | 是 | 任务配置文件,加密的专有格式(.vtex) |
| token | String | 否 | 用户token值用于认证 |
| tenantId | String | 否 | 租户ID用于多租户隔离默认为"default" |
#### 响应参数
```json
{
"code": 200,
"message": "成功导入 2 个任务",
"data": {
"success_count": 2,
"failed_count": 0,
"failed_tasks": [],
"imported_tasks": [
{
"id": "193f8412-fa0d-4b6d-9648-70bceacd6631",
"name": "任务1-备份-16487239871234",
"original_name": "任务1"
},
{
"id": "734749d1-0fdf-4a06-9fb7-8f991953d5e6",
"name": "任务2-备份-16487239875678",
"original_name": "任务2"
}
]
}
}
```
#### 部分导入成功响应示例
```json
{
"code": 200,
"message": "部分导入成功: 成功 1 个, 失败 1 个",
"data": {
"success_count": 1,
"failed_count": 1,
"failed_tasks": [
{
"index": 1,
"name": "任务2",
"reason": "任务数据不完整"
}
],
"imported_tasks": [
{
"id": "193f8412-fa0d-4b6d-9648-70bceacd6631",
"name": "任务1-备份-16487239871234",
"original_name": "任务1"
}
]
}
}
```
#### 导入失败响应示例
```json
{
"code": 400,
"message": "解析任务数据失败: 文件格式无效或已损坏",
"data": null
}
```
### 8. 获取单个任务详情
#### 接口描述
获取指定任务的详细信息,包括任务的基本信息、配置参数和详细定义。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-task/{task_id}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| task_id | String | 是 | 任务ID路径参数 |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": "193f8412-fa0d-4b6d-9648-70bceacd6629",
"label": "test1",
"version": 19,
"detail": {
"inputParams": [
{
"name": "from",
"type": "String",
"label": "起点",
"required": false,
"defaultValue": "",
"remark": "起始位置"
},
{
"name": "to",
"type": "String",
"label": "终点",
"required": true,
"defaultValue": "",
"remark": "目标位置"
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {}
}
},
"templateName": "userTemplate",
"period": 3000,
"periodicTask": false,
"status": 0,
"ifEnable": 0,
"delay": 3000,
"releaseSites": true,
"createDate": "2023-05-10 14:30:22",
"remark": "测试任务"
}
}
```
#### 错误响应
```json
{
"code": 404,
"message": "任务不存在",
"data": null
}
```
```json
{
"code": 500,
"message": "获取任务详情失败: 内部服务器错误",
"data": null
}
```

View File

@ -0,0 +1,86 @@
# 任务模板管理接口文档
## 一、任务模板管理接口
### 1. 获取任务模板列表
#### 接口描述
获取系统中所有可用的任务模板列表。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-task/template/list`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| page | Integer | 否 | 页码默认为1 |
| pageSize | Integer | 否 | 每页记录数默认为10 |
| templateName | String | 否 | 模板名称,用于筛选 |
| status | Integer | 否 | 状态0-未启用1-启用完成 |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"total": 4,
"list": [
{
"id": "template-001",
"templateName": "Pulsating production line",
"templateDescription": "脉动产线模板",
"status": 0
},
{
"id": "template-002",
"templateName": "Assemble order",
"templateDescription": "拼合单模板",
"status": 0
},
{
"id": "template-003",
"templateName": "Dense peak bit",
"templateDescription": "密集库位模板",
"status": 0
},
{
"id": "template-004",
"templateName": "userTemplate",
"templateDescription": "用户自有模板",
"status": 1
}
]
}
}
```
### 4. 启用任务模板
#### 接口描述
启用指定的任务模板。当一个模板被启用时,之前已启用的模板会自动被禁用,确保系统中始终只有一个处于激活状态的模板。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-task/template/enable/{id}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 模板ID路径参数 |
#### 响应参数
```json
{
"code": 200,
"message": "模板启用成功",
"data": null
}
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,396 @@
# 在线脚本管理接口文档
## 一、在线脚本模块概述
在线脚本模块是配合天风任务模块使用的核心功能允许用户创建、编辑、管理和执行Python脚本。该模块支持脚本版本控制运行脚本并查看执行日志等功能。
## 二、在线脚本模块接口
### 1. 获取脚本列表
#### 接口描述
获取系统中的脚本列表支持分页、排序和筛选。数据来源是vwed_script表。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-script/list`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| page | Integer | 否 | 页码默认为1 |
| pageSize | Integer | 否 | 每页记录数默认为20 |
| name | String | 否 | 脚本名称,支持模糊查询 |
| status | Integer | 否 | 脚本状态(1:启用, 0:禁用) |
| folderPath | String | 否 | 脚本所在目录路径 |
| tags | String | 否 | 标签,支持模糊查询 |
| isPublic | Integer | 否 | 是否公开(1:是, 0:否) |
| createdBy | String | 否 | 创建者 |
| startTime | String | 否 | 创建时间范围的开始时间格式yyyy-MM-dd HH:mm:ss |
| endTime | String | 否 | 创建时间范围的结束时间格式yyyy-MM-dd HH:mm:ss |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"total": 15,
"list": [
{
"id": "script-001",
"name": "数据处理脚本",
"folderPath": "/数据处理",
"fileName": "data_processor.py",
"description": "用于处理CSV数据的脚本",
"version": 3,
"status": 1,
"isPublic": 1,
"tags": "数据,CSV,处理",
"createdBy": "admin",
"createdOn": "2025-04-10 09:30:45",
"updatedBy": "admin",
"updatedOn": "2025-04-12 15:20:10"
},
{
"id": "script-002",
"name": "邮件发送脚本",
"folderPath": "/通知",
"fileName": "email_sender.py",
"description": "自动发送邮件通知的脚本",
"version": 1,
"status": 1,
"isPublic": 1,
"tags": "邮件,通知",
"createdBy": "user1",
"createdOn": "2025-04-11 10:15:22",
"updatedBy": "user1",
"updatedOn": "2025-04-11 10:15:22"
}
]
}
}
```
### 2. 获取脚本详情
#### 接口描述
获取指定脚本的详细信息,包括脚本代码内容。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-script/{id}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 脚本ID路径参数 |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": "script-001",
"name": "数据处理脚本",
"folderPath": "/数据处理",
"fileName": "data_processor.py",
"description": "用于处理CSV数据的脚本",
"code": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\ndef process_data(input_file, output_file):\n # 处理逻辑\n pass\n\nif __name__ == '__main__':\n process_data('input.csv', 'output.csv')",
"version": 3,
"status": 1,
"isPublic": 1,
"tags": "数据,CSV,处理",
"createdBy": "admin",
"createdOn": "2025-04-10 09:30:45",
"updatedBy": "admin",
"updatedOn": "2025-04-12 15:20:10",
"testParams": "{\"input_file\": \"test.csv\", \"output_file\": \"result.csv\"}"
}
}
```
### 3. 创建脚本
#### 接口描述
创建一个新的脚本。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-script`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| folderPath | String | 否 | 脚本所在目录路径 |
| fileName | String | 是 | 脚本文件名,必须以.py结尾 |
#### 请求示例
```json
{
"folderPath": "/数据处理",
"fileName": "data_processor.py",
}
```
#### 响应参数
```json
{
"code": 200,
"message": "创建成功",
"data": {
"id": "script-001"
}
}
```
### 4. 更新脚本
#### 接口描述
更新现有脚本的信息,包括代码内容。每次更新会自动生成新的版本记录。
#### 请求方式
- **HTTP方法**: PUT
- **接口路径**: `/api/vwed-script/{id}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 脚本ID路径参数 |
| folderPath | String | 是 | 脚本所在目录路径 |
| fileName | String | 是 | 脚本文件名,必须以.py结尾 |
| code | String | 是 | 脚本代码内容 |
#### 请求示例
```json
{
"code": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\ndef process_data(input_file, output_file):\n # 更新的处理逻辑\n with open(input_file, 'r') as f_in:\n data = f_in.read()\n \n # 处理数据\n processed_data = data.upper()\n \n with open(output_file, 'w') as f_out:\n f_out.write(processed_data)\n\nif __name__ == '__main__':\n process_data('input.csv', 'output.csv')",
"changeLog": "增加了文件读写功能"
}
```
#### 响应参数
```json
{
"code": 200,
"message": "更新成功",
"data": {
"version": 4
}
}
```
### 5. 删除脚本
#### 接口描述
删除指定的脚本,同时删除所有相关的版本记录。
#### 请求方式
- **HTTP方法**: DELETE
- **接口路径**: `/api/vwed-script/{id}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 脚本ID路径参数 |
#### 响应参数
```json
{
"code": 200,
"message": "删除成功",
"data": null
}
```
### 6. 运行脚本
#### 接口描述
执行指定的脚本,并返回执行结果。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-script/{id}/run`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 脚本ID路径参数 |
#### 请求示例
```json
{
"id": "task-001",
}
```
#### 响应参数
```json
{
"code": 200,
"message": "执行成功",
"data": {
"logId": "log-001",
"result": {
"status": "success",
"output": {
"processed_rows": 100,
"duration": 0.25
}
},
"executionTime": 250
}
}
```
### 7. 停止脚本执行
#### 接口描述
停止正在执行的脚本。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-script/stop`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| logId | String | 是 | 脚本执行日志ID |
#### 请求示例
```json
{
"logId": "log-001"
}
```
#### 响应参数
```json
{
"code": 200,
"message": "已停止执行",
"data": null
}
```
### 12. 获取脚本执行日志详情
#### 接口描述
获取特定脚本执行日志的详细信息。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-script/log/{logId}`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| logId | String | 是 | 脚本执行日志ID路径参数 |
#### 响应参数
```json
{
"code": 200,
"message": "操作成功",
"data": {
"id": "log-003",
"scriptId": "script-001",
"scriptName": "数据处理脚本",
"version": 3,
"taskRecordId": "task-001",
"blockRecordId": "block-001",
"inputParams": "{\"input_file\":\"data.csv\",\"output_file\":\"result.csv\"}",
"outputResult": "{\"status\":\"success\",\"processed_rows\":100,\"duration\":0.25}",
"status": 1,
"errorMessage": null,
"executionTime": 250,
"startedOn": "2025-04-12 16:10:45",
"endedOn": "2025-04-12 16:10:45",
"code": "#!/usr/bin/env python\n# -*- coding: utf-8 -*-\n\ndef process_data(input_file, output_file):\n # 版本3的处理逻辑\n pass\n\nif __name__ == '__main__':\n process_data('input.csv', 'output.csv')"
}
}
```
### 13. 导出脚本
#### 接口描述
导出指定脚本的代码文件。
#### 请求方式
- **HTTP方法**: GET
- **接口路径**: `/api/vwed-script/{id}/export`
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| id | String | 是 | 脚本ID路径参数 |
#### 响应参数
返回脚本文件的二进制内容Content-Type为application/octet-stream或text/plain。
### 14. 导入脚本
#### 接口描述
从Python文件导入脚本。
#### 请求方式
- **HTTP方法**: POST
- **接口路径**: `/api/vwed-script/import`
- **Content-Type**: multipart/form-data
#### 请求参数
| 参数名 | 类型 | 必填 | 描述 |
|-------|------|-----|------|
| file | File | 是 | 要导入的Python脚本文件 |
#### 响应参数
```json
{
"code": 200,
"message": "导入成功",
"data": {
"id": "script-010"
}
}
```
## 三、数据结构
### 1. 脚本状态
| 状态码 | 描述 |
|-------|------|
| 1 | 启用 |
| 0 | 禁用 |
### 2. 脚本执行状态
| 状态码 | 描述 |
|-------|------|
| 1 | 成功 |
| 0 | 失败 |

View File

@ -0,0 +1,698 @@
# 库位处理接口文档
## 批量设置库位 (BatchSettingSiteBp)
本接口用于批量设置库位的占用状态和内容。当库位 IDs 和库区集同时提供时,会对这些库位进行批量设置操作。
### 描述
本块在需要批量设置库位内容和占用状态时使用,可同时设置多个库位或多个库区的库位的占用状态。当库位 Ids 和库区集参数均填入时,则表示可同时对满足这两个参数的库位进行设置。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ---------- | -------- | -------- | ------------ | ------------------------ |
| siteIds | 库位IDs | 非必填 | String[] | 多个库位 id 的集合 |
| groupNames | 库区集 | 非必填 | String[] | 多个库区的集合 |
| filled | 占用 | 必填 | Boolean | 库位是否占用状态,选择 true 或 false |
| content | 货物 | 非必填 | String | 填写库位中具体的货物 |
| type | 是否物理库位 | 非必填 | Boolean | 勾选设置的库位是否是物理库位或是逻辑库位。物理库位指地图上实际存在的库位,逻辑库位指因业务逻辑创建的虚拟库位,不实际存在于地图中。 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteIds": ["site001", "site002", "site003"],
"groupNames": [],
"filled": true,
"content": "产品A",
"type": "physical"
}
// 成功响应示例
{
"success": true,
"message": "批量设置库位成功,共设置 3 个库位",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "批量设置库位失败: 库位ID不存在",
"code": 404
}
```
## 获取密集库位 (GetIdleCrowdedSiteBp)
本接口用于获取密集库位,支持根据库区、占用状态等条件查找适合的库位。
### 描述
本块用于在一组密集库位中获取符合条件的空闲库位,支持重试机制。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ---------- | -------- | -------- | ------------ | ------------------------ |
| groupName | 库区集 | 必填 | String[] | 库区数组 |
| filled | 取/放 | 必填 | Boolean | 选出库位用来取货还是放货 |
| content | 货物(取) | 非必填 | String | 取货库位的货物内容,在放货此字段忽略 |
| lock | 获取库位后是否锁定 | 非必填 | Boolean | 选出库位后是否立即锁定 |
| retry | 是否重试 | 必填 | Boolean | 是否启用重试 |
| retryPeriod | 重试时间间隔(ms) | 非必填 | Long | 重试周期(毫秒) |
| retryNum | 重试次数 | 非必填 | Long | 重试次数 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.siteId | 选出的库位 | String | 获取到的库位ID |
### 调用示例
```json
// 输入参数示例
{
"groupName": ["density_area_1", "density_area_2"],
"filled": false,
"content": "",
"lock": true,
"retry": true,
"retryPeriod": 1000,
"retryNum": 3
}
// 成功响应示例
{
"success": true,
"message": "获取密集库位成功库位ID: site001",
"code": 200,
"data": {
"siteId": "site001"
}
}
// 失败响应示例
{
"success": false,
"message": "获取密集库位失败: 未找到合适的库位",
"code": 404
}
```
## 获取库位 (GetIdleSiteBp)
本接口用于获取符合条件的库位,支持按多种条件过滤和查询。
### 描述
本块用于获取符合特定条件的库位,可以指定多种查询参数,并支持自动无限重试机制直到找到合适的库位。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ------------ | -------- | -------- | ------------- | ------------------------- |
| siteId | 库位ID | 非必填 | String | 库位ID |
| content | 货物 | 非必填 | String | 获取该货物名称的库位 |
| filled | 是否有货物 | 非必填 | Boolean | true: 获取有货物的库位; false: 获取无货物的库位 |
| locked | 是否已锁定 | 必填 | Boolean | true: 获取已锁定的库位; false: 获取未锁定的库位 |
| type | 是否物理库位 | 非必填 | Boolean | 是否是物理库位 |
| groupName | 库区名 | 非必填 | String | 库区名称 |
| lock | 获取库位后是否锁定 | 非必填 | Boolean | 选出库位后是否立即锁定 |
| retryPeriod | 重试时间间隔(ms) | 非必填 | Long | 重试间隔时间毫秒默认为1000毫秒。系统会不断重试直到获取到库位。 |
| ifFair | 是否为公平锁 | 非必填 | Boolean | 任务先尝试加锁库位,优先这个任务加锁此库位 |
| orderDesc | 是否为降序 | 非必填 | Boolean | true: 优先获取库位id大的; false: 优先获取库位id小的; 默认true |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息,包含重试次数信息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.siteId | 选出的库位 | String | 获取到的库位ID |
### 调用示例
```json
// 输入参数示例
{
"locked": false,
"filled": false,
"groupName": "storage_area_A",
"lock": true,
"retryPeriod": 2000,
"ifFair": true,
"orderDesc": true
}
// 成功响应示例
{
"success": true,
"message": "获取库位成功库位ID: site123",
"code": 200,
"data": {
"siteId": "site123"
}
}
// 重试成功响应示例
{
"success": true,
"message": "第3次重试获取库位成功库位ID: site123",
"code": 200,
"data": {
"siteId": "site123"
}
}
```
### 注意事项
1. 该接口实现了无限重试机制,会一直尝试获取库位直到成功
2. 每次重试之间会等待retryPeriod指定的时间毫秒
3. 如果长时间无法获取到库位,建议检查查询条件是否合理
## 根据任务实例ID获取所有枷锁库位 (GetLockedSitesByTaskRecordIdBp)
本接口用于获取某个任务实例已锁定的所有库位。
### 描述
本块用于查询指定任务实例ID锁定的所有库位方便后续对这些库位进行操作。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ------------- | ---------- | -------- | ------------- | -------------- |
| taskRecordId | 任务实例ID | 必填 | String | 任务实例ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| ---------------- | -------------- | --------- | ----------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| lockedSiteIdList | 已锁定库位列表 | String[] | 已锁定的库位ID列表 |
### 调用示例
```json
// 输入参数示例
{
"taskRecordId": "task123456"
}
// 成功响应示例
{
"success": true,
"message": "获取任务锁定库位成功,共 3 个库位",
"code": 200,
"data": {
"lockedSiteIdList": ["site001", "site002", "site003"]
}
}
// 失败响应示例
{
"success": false,
"message": "获取任务锁定库位失败: 任务实例不存在",
"code": 404
}
```
## 获取库位扩展属性 (GetSiteAttrBp)
本接口用于获取库位的扩展属性值。
### 描述
本块用于获取指定库位ID的特定扩展属性值支持获取自定义属性。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| --------- | -------- | -------- | ------------- | -------------- |
| siteId | 库位ID | 必填 | String | 指定的库位 Id |
| attrName | 属性名称 | 必填 | String | 指定的库位扩展属性名称|
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| ---------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| attrValue | 属性值 | Any | 属性值 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"attrName": "temperature"
}
// 成功响应示例
{
"success": true,
"message": "获取库位属性值成功temperature: 25",
"code": 200,
"data": {
"attrValue": "25"
}
}
// 失败响应示例
{
"success": false,
"message": "获取库位属性值失败: 属性不存在",
"code": 404
}
```
## 查询库位 (QueryIdleSiteBp)
本接口用于查询符合条件的库位详细信息。
### 描述
本块用于根据指定条件查询库位的详细信息,与获取库位接口不同,此接口会返回库位的完整信息,而不会锁定库位。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ------------ | -------- | -------- | ------------- | ------------------------- |
| siteId | 库位ID | 非必填 | String | 库位ID |
| content | 货物 | 非必填 | String | 获取该货物名称的库位 |
| filled | 是否有货物 | 非必填 | Boolean | true: 获取有货物的库位; false: 获取无货物的库位 |
| locked | 是否已锁定 | 非必填 | Boolean | true: 获取已锁定的库位; false: 获取未锁定的库位 |
| type | 是否物理库位 | 非必填 | Boolean | 勾选 True 或者 False |
| groupName | 库区名 | 非必填 | String | 填入库区名称 |
| orderDesc | 是否为降序 | 非必填 | Boolean | true: 优先获取库位id大的; false: 优先获取库位id小的; 默认为false |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| site | 库位信息 | Object | 库位详细信息对象 |
### 库位对象属性(不确定)
| 属性名 | 中文名称 | 类型 | 描述 |
| ----------- | -------- | --------- | ------------------- |
| id | 库位ID | String | 库位ID |
| groupName | 库区名称 | String | 库区名称 |
| type | 类型 | Number | 库位类型 |
| filled | 占用 | Boolean | 是否已占用 |
| locked | 锁定 | Boolean | 是否已锁定 |
| content | 货物内容 | String | 库位内容 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"filled": false,
"locked": false
}
// 成功响应示例
{
"success": true,
"message": "查询库位成功库位ID: site001",
"code": 200,
"data": {
"site": {
"id": "site001",
"groupName": "storage_area_A",
"type": 0,
"filled": false,
"locked": false,
"content": ""
}
}
}
// 失败响应示例
{
"success": false,
"message": "查询库位失败: 未找到符合条件的库位",
"code": 404
}
```
## 设置库位扩展属性 (SetSiteAttrBp)
本接口用于设置库位的扩展属性值。
### 描述
本块用于设置指定库位ID的特定扩展属性值支持设置自定义属性。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ---------- | -------- | -------- | ------------- | ------------- |
| siteId | 库位ID | 必填 | String | 库位ID |
| attrName | 属性名称 | 必填 | String | 指定的库位扩展属性名称|
| attrValue | 属性值 | 非必填 | Any | 属性值 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"attrName": "temperature",
"attrValue": 25
}
// 成功响应示例
{
"success": true,
"message": "设置库位属性值成功site001.temperature = 25",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "设置库位属性值失败: 库位不存在",
"code": 404
}
```
## 设置库位货物 (SetSiteContentBp)
本接口用于设置库位的货物内容。
### 描述
本块用于设置指定库位ID的货物内容通常用于标记库位中存放的具体物品。
### 输入参数
| 参数名 | 是否必填 | 类型 | 描述 |
| --------- | -------- | ------------- | ------------- |
| siteId | 必填 | String | 库位ID |
| content | 必填 | String | 货物内容 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"content": "产品A-批次123"
}
// 成功响应示例
{
"success": true,
"message": "设置库位货物成功site001 货物: 产品A-批次123",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "设置库位货物失败: 库位不存在",
"code": 404
}
```
## 设置库位为空 (SetSiteEmptyBp)
本接口用于将库位设置为空闲状态。
### 描述
该块可以将指定库位设置为未占用状态,同时清空货物字段。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| --------- | -------- | -------- | ------------- | ------------- |
| siteId | 库位ID | 必填 | String | 库位ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001"
}
// 成功响应示例
{
"success": true,
"message": "设置库位为空成功库位ID: site001",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "设置库位为空失败: 库位不存在",
"code": 404
}
```
## 设置库位为占用 (SetSiteFilledBp)
本接口用于将库位设置为占用状态。
### 描述
该块可以将指定库位设置为占用状态,但不操作货物字符串。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| --------- | -------- | -------- | ------------- | ------------- |
| siteId | 库位ID | 必填 | String | 库位ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001"
}
// 成功响应示例
{
"success": true,
"message": "设置库位为占用成功库位ID: site001",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "设置库位为占用失败: 库位不存在",
"code": 404
}
```
## 锁定库位 (SetSiteLockedBp)
本接口用于锁定库位,防止其他任务操作该库位。
### 描述
该块可以将指定定的库位锁定,前提是该库位位已经在库存中设置或者在当前节点任务实例中被当前节点加锁。如果不满足条件,这个块将阻塞,直到该库位可交为解锁状态,然后进行锁定。
### 输入参数
| 参数名 | 是否必填 | 类型 | 描述 |
| ---------- | -------- | ------------ | ------------------------ |
| 库位 Id | 必填 | String | 指定的库位 Id |
| 是否为公平锁 | 非必填 | boolean | 任务先发出加锁库位,优先这个任务加锁此库位 |
| 加锁者 | 非必填 | String | 指定加锁该库位的加锁者默认为当前任务实例id |
| 重试次数 | 非必填 | Integer | 重试次数 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"ifFair": true,
"locker": "task123456",
"retryNum": 3
}
// 成功响应示例
{
"success": true,
"message": "锁定库位成功库位ID: site001",
"code": 200,
"data": {
"success": true
}
}
// 失败响应示例
{
"success": false,
"message": "锁定库位失败库位ID: site001可能已被其他任务锁定",
"code": 409,
"data": {
"success": false
}
}
```
## 解锁库位 (SetSiteUnlockedBp)
本接口用于解锁库位,允许其他任务操作该库位。
### 描述
本块用于解锁特定的库位ID解除其与特定任务的关联允许其他任务操作该库位。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ---------- | -------- | -------- | ------------- | --------------------- |
| siteId | 库位ID | 必填 | String | 指定的库位ID |
| unLockedId | 解锁者 | 非必填 | String | 指定解锁该库位的解锁者默认为当前任务实例id |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | --------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"unLockedId": "task123456"
}
// 成功响应示例
{
"success": true,
"message": "解锁库位成功库位ID: site001",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "解锁库位失败: 库位不存在",
"code": 404
}
```
## 设置库位标签 (SetSiteTagsBp)
本接口用于设置库位的标签信息。
### 描述
本块用于为指定库位设置标签,可用于标记库位的特殊属性或分类,便于后续查询和管理。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| --------- | -------- | -------- | ------------- | ------------- |
| siteId | 库位ID | 必填 | String | 指定的库位ID |
| tags | 标签 | 非必填 | String | 库位标签,多个标签可用逗号分隔 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
### 调用示例
```json
// 输入参数示例
{
"siteId": "site001",
"tags": "临时存储,高优先级,易碎品"
}
// 成功响应示例
{
"success": true,
"message": "设置库位标签成功库位ID: site001标签: 临时存储,高优先级,易碎品",
"code": 200
}
// 失败响应示例
{
"success": false,
"message": "设置库位标签失败: 库位不存在",
"code": 404
}
```

View File

@ -0,0 +1,273 @@
# 机器人调度接口文档
## 机器人通用动作 (CAgvOperationBp)
本接口用于执行机器人的通用动作操作,包括移动、取放货等。
### 描述
本块用于执行机器人的通用动作,提供了丰富的参数来满足各种场景下的动作需求,如移动到特定位置、携带货物等。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| --------------- | ------------ | -------- | ------------ | ------------------------ |
| targetSiteLabel | 目标站点名 | 必填 | String | 目标站点的名称或标识 |
| spin | 允许随动 | 非必填 | Boolean | 是否允许机器人在移动中同时进行旋转 |
| adjustInfo | 调整 | 非必填 | JSONArray | 机器人精细调整的参数信息 |
|task |指令 |非必填 | JSONArray | 机器人执行的动作 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.taskId | 任务ID | String | 生成的任务ID |
### 调用示例
```json
// 输入参数示例
{
"targetSiteLabel": "storage_B",
"postAction": "load",
"goodsId": "box456",
"isEndAction": false,
"max_speed": 1.2,
"max_wspeed": 0.5,
"spin": true,
"adjustInfo": [
{"type": "position", "x": 0.05, "y": 0.02, "theta": 0.1}
]
}
// 成功响应示例
{
"success": true,
"message": "机器人移动成功,目标站点: storage_B, 货物ID: box456, 任务ID: TASK20230501002",
"code": 200,
"data": {
"taskId": "TASK20230501002"
}
}
// 失败响应示例
{
"success": false,
"message": "机器人通用动作失败: 机器人当前不可用",
"code": 503
}
```
## 选择执行机器人 (CSelectAgvBp)
本接口用于从可用机器人中选择一个适合执行任务的机器人。
### 描述
本块用于根据指定条件(优先级、标签、机器人组等)从可用机器人中选择一个最合适的执行任务。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| ------------- | ------------ | -------- | ------------ | ------------------------- |
| priority | 优先级 | 非必填 | Long | 任务优先级,数值越大优先级越高 |
| vehicle | 指定机器人 | 非必填 | String | 指定使用的机器人ID |
| group | 指定机器人组 | 非必填 | String | 指定从哪个机器人组中选择 |
| keyRoute | 关键路径 | 必填 | String | 机器人需要执行的关键路径 |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| -------------- | ------------ | -------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.agvId | 选出的机器人 | String | 选择的机器人ID |
### 调用示例
```json
// 输入参数示例
{
"priority": 10,
"tag": "heavy_load",
"group": "warehouse_robots",
"keyRoute": "warehouse_to_shipping",
"keyGoodsId": "pallet123",
"mapfPriority": 2
}
// 成功响应示例
{
"success": true,
"message": "从机器人组 warehouse_robots 选择机器人成功: AGV001",
"code": 200,
"data": {
"agvId": "AGV001"
}
}
// 失败响应示例
{
"success": false,
"message": "选择执行机器人失败: 没有符合条件的可用机器人",
"code": 404
}
```
## 获取机器人位置 (VehicleStationBp)
本接口用于获取指定机器人的当前位置和上一个位置信息。
### 描述
本块用于查询指定机器人ID的当前位置和上一个位置可用于监控机器人状态或位置变化。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| -------- | ---------- | -------- | ------------ | ---------------- |
| vehicle | 指定机器人 | 必填 | String | 要查询的机器人ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| -------------- | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.station | 当前位置 | String | 机器人当前所在位置 |
| data.lastStation | 上次位置 | String | 机器人上一个所在位置 |
### 调用示例
```json
// 输入参数示例
{
"vehicle": "AGV001"
}
// 成功响应示例
{
"success": true,
"message": "获取机器人 AGV001 位置成功,当前位置: station_C, 上次位置: station_A",
"code": 200,
"data": {
"station": "station_C",
"lastStation": "station_A"
}
}
// 失败响应示例
{
"success": false,
"message": "获取机器人位置失败: 机器人ID不存在",
"code": 404
}
```
## 获取机器人电量 (GetBatteryLevelBp)
本接口用于获取指定机器人的当前电量水平。
### 描述
本块用于查询指定机器人ID的当前电量水平可用于监控机器人的电量状态以便及时充电或调度管理。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| -------- | ---------- | -------- | ------------ | ---------------- |
| vehicle | 机器人ID | 必填 | String | 要查询的机器人ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| ------------------ | -------- | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.batteryLevel | 电量 | Double | 机器人当前电量水平范围0-1表示0-100% |
### 调用示例
```json
// 输入参数示例
{
"vehicle": "AGV002"
}
// 成功响应示例
{
"success": true,
"message": "获取机器人 AGV002 电量成功,当前电量: 85.5%",
"code": 200,
"data": {
"batteryLevel": 0.855
}
}
// 失败响应示例
{
"success": false,
"message": "获取机器人电量失败: 机器人ID不存在",
"code": 404
}
```
## 获取机器人PGV码 (GetPGVCodeBp)
本接口用于获取机器人的PGV码信息用于定位和导航。
### 描述
本块用于获取指定机器人ID的PGV码信息PGV码用于机器人的精确定位和导航通过查询可以确定机器人是否正确识别到二维码信息。
### 输入参数
| 参数名 | 中文名称 | 是否必填 | 类型 | 描述 |
| -------- | ---------- | -------- | ------------ | ---------------- |
| vehicle | 机器人ID | 必填 | String | 要查询的机器人ID |
### 输出参数
| 参数名 | 中文名称 | 类型 | 描述 |
| --------------- | ------------ | ------- | ------------------- |
| success | 成功标志 | Boolean | 操作是否成功 |
| message | 消息 | String | 操作结果消息 |
| code | 返回代码 | Number | 操作结果代码 |
| data | 数据 | Object | 返回数据对象 |
| data.codeInfo | 二维码信息 | Boolean | 机器人是否识别到有效的PGV码 |
### 调用示例
```json
// 输入参数示例
{
"vehicle": "AGV003"
}
// 成功响应示例
{
"success": true,
"message": "获取机器人 AGV003 PGV码成功二维码信息: 有效",
"code": 200,
"data": {
"codeInfo": true
}
}
// 失败响应示例
{
"success": false,
"message": "获取机器人PGV码失败: 无法连接到机器人",
"code": 503
}
```

View File

@ -0,0 +1,299 @@
# VWED任务系统 - 系统架构设计
## 1. 整体架构图
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 客户端层 │
├─────────────────┬─────────────────┬──────────────────┬───────────────────┬──────┘
│ 任务管理界面 │ 任务创建界面 │ 任务编辑界面 │ 任务监控与执行 │
│ - 任务列表 │ - 基本信息表单 │ - 低代码编辑器 │ - 执行状态监控 │
│ - 状态筛选 │ - 任务类型选择 │ - 预设组件库 │ - 执行记录查看 │
│ - 导入/导出 │ │ - 流程设计工具 │ │
└─────────┬───────┴─────────┬───────┴───────┬──────────┴────────┬──────────┘
│ │ │ │
┌─────────▼─────────────────▼───────────────▼────────────────────▼───────────────┐
│ 业务逻辑层 │
├────────────────┬────────────────┬────────────────┬────────────────┬─────────────┤
│ 任务定义模块 │ 任务执行模块 │ 组件管理模块 │ 参数配置模块 │ 模板配置 │
│ - 任务创建 │ - 任务调度 │ - 组件选择 │ - 参数设置 │ - 模板创建 │
│ - 任务配置 │ - 状态管理 │ - 组件逻辑 │ - 参数验证 │ - 模板管理 │
│ - 任务编辑 │ - 子任务控制 │ - 参数配置 │ - 预设表达式 │ - 版本控制 │
└────────┬───────┴────────┬───────┴────────┬───────┴────────┬───────┴──────┬──────┘
│ │ │ │ │
┌────────▼────────────────▼────────────────▼────────────────▼──────────────▼──────┐
│ 数据访问层 │
├────────────────┬────────────────┬────────────────┬────────────────┬─────────────┤
│ 任务定义DAO │ 任务记录DAO │ 任务块记录DAO │ 数据缓存DAO │ 模板DAO │
└────────┬───────┴────────┬───────┴────────┬───────┴────────┬───────┴──────┬──────┘
│ │ │ │ │
┌────────▼────────────────▼────────────────▼────────────────▼──────────────▼──────┐
│ 数据存储层 │
├────────────────┬────────────────┬────────────────┬────────────────┬─────────────┤
│ vwed_taskdef │ vwed_taskrecord│vwed_blockrecord│vwed_datacache│vwed_task │
│ (任务定义表) │ (任务记录表) │ (任务块记录表) │ (数据缓存表) │template表 │
└────────────────┴────────────────┴────────────────┴────────────────┴─────────────┘
│ │ │ │ │
┌────────▼────────────────▼────────────────▼────────────────▼──────────────▼──────┐
│ 集成服务层 │
├────────────────┬────────────────┬────────────────┬────────────────┬─────────────┤
│ AGV控制接口 │ 站点管理接口 │ 设备接口 │ 外部系统接口 │ 认证服务 │
└────────────────┴────────────────┴────────────────┴────────────────┴─────────────┘
## 2. 系统模块拆分
### 2.1 核心模块
| 模块名称 | 功能描述 | 优先级 | 依赖模块 |
|---------|---------|--------|---------|
| 任务管理模块 | 提供任务的CRUD操作包括任务列表、筛选、搜索、导入导出功能 | 高 | 数据访问层 |
| 任务创建模块 | 创建新任务,设置基本信息和任务类型 | 高 | 任务管理模块,模板配置模块 |
| 任务定义模块 | 定义任务结构、存储任务流程和逻辑 | 高 | 数据访问层 |
| 任务执行模块 | 处理任务的执行、调度和状态管理 | 高 | 任务定义模块AGV控制接口 |
| 低代码编辑器 | 可视化任务流程设计器,预设组件拖拽配置 | 高 | 组件管理模块 |
| 组件管理模块 | 管理预设组件集合,提供组件选择和参数配置 | 高 | 无 |
### 2.2 扩展模块
| 模块名称 | 功能描述 | 优先级 | 依赖模块 |
|---------|---------|--------|---------|
| 模板配置模块 | 创建和管理任务模板,维护模板版本 | 中 | 任务定义模块 |
| 参数配置模块 | 为预设组件提供参数配置界面,支持预设表达式 | 中 | 组件管理模块 |
| 库位组件模块 | 管理库位操作相关的预设组件集合 | 中 | 组件管理模块,站点管理接口 |
| 机器人调度模块 | 管理机器人调度相关的预设组件集合 | 中 | 组件管理模块AGV控制接口 |
| 业务管理模块 | 管理业务规则,提供业务配置界面 | 中 | 任务管理模块 |
### 2.3 基础设施模块
| 模块名称 | 功能描述 | 优先级 | 依赖模块 |
|---------|---------|--------|---------|
| 数据访问层 | 封装对数据库的访问,提供统一接口 | 高 | 无 |
| AGV控制接口 | 提供与AGV交互的接口 | 高 | 无 |
| 站点管理接口 | 提供库位/站点的管理接口 | 高 | 无 |
| 设备接口 | 提供与外部设备通信的接口 | 中 | 无 |
| 认证授权模块 | 用户认证与权限管理 | 中 | 无 |
## 3. 任务调度系统架构
### 3.1 调度器架构图
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 任务调度系统 │
├───────────────────┬─────────────────────┬──────────────────┬────────────────────┤
│ 调度器核心 │ 工作线程池 │ 任务队列 │ 状态管理 │
│ - 任务分配逻辑 │ - 并发任务处理 │ - 优先级队列 │ - 任务状态跟踪 │
│ - 生命周期管理 │ - 资源隔离 │ - 延迟任务处理 │ - 失败处理机制 │
│ - 负载均衡 │ - 线程数控制 │ - 队列监控 │ - 状态通知 │
└─────────┬─────────┴──────────┬──────────┴────────┬─────────┴─────────┬──────────┘
│ │ │ │
┌─────────▼────────────────────▼───────────────────▼────────────────────▼──────────┐
│ 执行引擎层 │
├───────────────────┬─────────────────────┬──────────────────┬────────────────────┤
│ 任务执行器 │ 组件执行器 │ 异步IO管理 │ 资源管理 │
│ - 任务解析 │ - 组件加载 │ - 非阻塞操作 │ - 内存限制 │
│ - 执行上下文 │ - 参数验证 │ - 超时控制 │ - CPU使用监控 │
│ - 错误处理 │ - 结果处理 │ - 事件循环 │ - 资源释放 │
└───────────────────┴─────────────────────┴──────────────────┴────────────────────┘
### 3.2 调度系统关键组件
| 组件名称 | 功能描述 | 技术实现 |
|---------|---------|---------|
| 任务调度器 | 核心调度组件,负责任务分派和执行控制 | asyncio + 自定义调度算法 |
| 工作线程池 | 管理固定数量的工作线程,处理并发任务 | ThreadPoolExecutor线程数: 5 |
| 任务队列 | 存储待执行任务,支持优先级和延迟执行 | asyncio.Queue + 优先级算法 |
| 状态追踪器 | 记录和更新任务状态,提供实时状态查询 | 内存缓存 + 数据库持久化 |
| 执行上下文 | 为任务提供执行环境和参数传递机制 | 上下文管理器模式 |
| 异常处理器 | 捕获和处理任务执行过程中的异常 | try-except + 重试机制 |
### 3.3 调度系统工作流程
1. **任务提交阶段**
API层 → TaskEditService/TaskService → 任务调度器(scheduler) → 任务队列
2. **任务调度阶段**
任务调度器 → 工作线程池分配 → 执行上下文创建 → 任务执行器
3. **任务执行阶段**
任务执行器 → 组件执行器 → 业务逻辑处理 → 状态更新
4. **任务完成阶段**
任务执行器 → 状态追踪器 → 数据库更新 → 任务调度器(下一任务)
### 3.4 并发控制与资源管理
- **线程池大小**: 系统配置工作线程数为5表示最多同时执行5个任务
- **任务排队机制**: 超过并发上限的任务进入队列等待,按优先级和提交顺序排序
- **资源隔离**: 每个工作线程独立执行任务,防止任务间相互干扰
- **负载均衡**: 调度器根据线程负载情况,合理分配任务以优化系统资源利用
### 3.5 调度系统优势
1. **高性能**: 利用异步编程和线程池实现高效任务处理
2. **可靠性**: 完善的错误处理和状态管理机制,防止任务丢失
3. **可扩展性**: 支持动态调整线程池大小,适应不同负载场景
4. **灵活性**: 支持任务优先级,可根据业务需求调整执行顺序
5. **可监控性**: 提供详细的任务执行状态和统计信息,便于系统监控和问题排查
### 3.6 调度系统与应用生命周期集成
```python
# 应用启动时初始化调度器
@app.on_event("startup")
async def startup():
# 初始化任务调度器
await scheduler.start(worker_count=5)
logger.info("任务调度器已启动,工作线程数: 5")
# 应用关闭时停止调度器
@app.on_event("shutdown")
async def shutdown():
# 停止任务调度器
await scheduler.stop()
logger.info("任务调度器已停止")
```
### 3.7 增强版任务调度系统
为满足系统不断增长的任务处理需求和更高的可靠性要求,我们设计并实现了增强版任务调度系统,采用模块化设计,大幅提升了系统的性能、可靠性和可扩展性。
#### 3.7.1 增强版调度系统架构图
┌─────────────────────────────────────────────────────────────────────────────────┐
│ 增强版任务调度系统 │
├───────────────────┬─────────────────────┬──────────────────┬────────────────────┤
│ EnhancedScheduler │ PriorityQueueManager│ WorkerManager │PeriodicTaskManager │
│ - 调度器核心 │ - 多级优先级队列 │ - 动态工作线程池 │ - 高级定时任务 │
│ - 组件协调 │ - 动态阈值调整 │ - 心跳监控 │ - Cron表达式支持 │
│ - 任务分发 │ - 平衡调度策略 │ - 自动扩缩容 │ - 周期任务管理 │
└─────────┬─────────┴──────────┬──────────┴────────┬─────────┴─────────┬──────────┘
│ │ │ │
┌─────────▼────────────────────▼───────────────────▼────────────────────▼──────────┐
│ 支撑服务层 │
├───────────────────┬─────────────────────┬──────────────────┬────────────────────┤
│TaskPersistenceManager│ 任务执行器 │ 健壮性服务 │ 监控系统 │
│ - 队列持久化 │ - 超时控制 │ - 异常恢复机制 │ - 实时状态监控 │
│ - 备份与恢复 │ - 重试机制 │ - 僵尸任务清理 │ - 资源使用跟踪 │
│ - 故障恢复 │ - 资源控制 │ - 心跳检测 │ - 性能指标统计 │
└───────────────────┴─────────────────────┴──────────────────┴────────────────────┘
#### 3.7.2 增强版调度系统核心组件
| 组件名称 | 功能描述 | 技术特点 |
|---------|---------|---------|
| EnhancedTaskScheduler | 主调度器,协调各组件工作 | 单例模式,异步协程,组件化设计 |
| PriorityQueueManager | 优先级队列管理,实现多级队列 | 动态阈值算法,自适应优先级分布 |
| WorkerManager | 工作线程管理和监控 | 自动扩缩容,心跳检测,资源感知 |
| TaskPersistenceManager | 任务队列持久化,故障恢复 | 定期备份,数据一致性保障 |
| PeriodicTaskManager | 高级定时任务管理 | Cron表达式支持精确调度控制 |
#### 3.7.3 增强版调度系统主要特性
##### 1. 优先级队列管理优化
- **动态阈值多级队列**:根据任务优先级分布自动调整队列阈值
- **平衡调度策略**:确保高优先级任务优先处理,同时避免低优先级任务长时间饥饿
- **资源分配**:针对不同优先级队列分配不同的工作线程配额
##### 2. 健壮性提升
- **全面的异常处理**:增强异常捕获和处理,防止工作线程崩溃
- **工作线程自动恢复**:检测到异常退出时自动重启工作线程
- **心跳检测**:周期性检查各组件状态,及时发现异常
- **状态一致性保障**:增强任务状态管理,避免"僵尸任务"和状态不一致
##### 3. 性能优化
- **动态工作线程池**:根据系统负载和队列长度自动调整工作线程数量
- **资源感知调度**根据CPU和内存使用情况动态调整执行策略
- **非阻塞IO**全面采用异步IO操作提高系统吞吐量
##### 4. 功能增强
- **任务超时控制**:可为每个任务设置执行超时时间,超时自动终止
- **任务重试机制**:支持配置失败任务的重试策略(次数、间隔、退避算法)
- **高级定时任务**支持标准Cron表达式实现更灵活的定时调度
- **状态通知机制**:提供实时的任务状态变更通知
##### 5. 数据安全与持久化
- **任务队列持久化**:定期备份任务队列,确保系统崩溃后能恢复任务
- **数据库事务优化**:加强事务处理,确保状态更新的原子性
- **预防内存泄漏**:监控内存使用,及时清理无效资源
#### 3.7.4 增强版调度系统配置选项
系统提供丰富的配置项,可通过`config/settings.py`进行调整:
```python
# 增强版任务调度器配置
TASK_SCHEDULER_MIN_WORKER_COUNT = 5 # 最小工作线程数
TASK_SCHEDULER_MAX_WORKER_COUNT = 20 # 最大工作线程数
TASK_SCHEDULER_QUEUE_COUNT = 3 # 队列数量
TASK_SCHEDULER_QUEUE_THRESHOLD_PERCENTILES = [0.1, 0.3, 1.0] # 队列阈值
TASK_SCHEDULER_WORKER_RATIOS = [0.6, 0.3, 0.1] # 工作线程分配比例
TASK_SCHEDULER_TASK_TIMEOUT = 3600 # 任务超时时间(秒)
TASK_SCHEDULER_MAX_RETRY_COUNT = 3 # 最大重试次数
TASK_SCHEDULER_RETRY_DELAY = 60 # 重试基础延迟(秒)
TASK_SCHEDULER_BACKUP_INTERVAL = 300 # 备份间隔(秒)
TASK_SCHEDULER_MAX_BACKUPS = 5 # 最大备份数
```
#### 3.7.5 增强版调度系统集成方案
增强版调度系统设计为完全兼容现有系统接口,可通过集成脚本快速替换原有调度器:
```python
# 集成增强版调度系统
from services.enhanced_scheduler.integration import integrate_enhanced_scheduler
# 在应用启动时集成
@app.on_event("startup")
async def startup():
integration_result = await integrate_enhanced_scheduler()
if integration_result["success"]:
logger.info("增强版任务调度系统集成成功")
else:
logger.error(f"集成失败: {integration_result['message']}")
```
#### 3.7.6 增强版调度系统对比分析
| 特性 | 原有调度系统 | 增强版调度系统 | 提升效果 |
|------|------------|--------------|---------|
| 任务优先级 | 单一队列优先级 | 多级动态阈值队列 | 更精准的任务优先级控制 |
| 工作线程 | 固定数量 | 动态自适应 | 更高效的资源利用率 |
| 任务重试 | 无内置重试 | 可配置重试策略 | 提高任务执行成功率 |
| 定时任务 | 简单周期 | Cron表达式支持 | 更灵活的定时策略 |
| 故障恢复 | 有限支持 | 完整持久化方案 | 显著提高系统可靠性 |
| 监控能力 | 基础状态 | 全面指标监控 | 便于问题排查和优化 |
| 资源控制 | 无资源限制 | CPU/内存监控与控制 | 防止单任务资源过度占用 |
通过增强版任务调度系统的部署系统的任务处理能力、可靠性和可维护性将获得显著提升为VWED任务系统提供更稳定和高效的核心调度服务。
## 4. 数据流图
### 4.1 任务创建与执行流程
1. **任务定义阶段**
用户 → 任务创建界面 → 任务定义模块 → 数据访问层 → vwed_taskdef
2. **任务实例化阶段**
用户 → 任务管理界面 → 任务执行模块 → 数据访问层 → vwed_taskrecord
3. **任务执行阶段**
任务执行模块 → 组件管理模块 → 任务块记录DAO → vwed_blockrecord
任务执行模块 → AGV控制接口 → 机器人执行
4. **任务监控阶段**
vwed_taskrecord → 任务记录DAO → 任务监控界面 → 用户
## 5. 系统交互图
### 5.1 低代码编辑器与组件交互
用户 ↔ 低代码编辑器 ↔ 组件管理模块 ↔ 预设组件库
组件参数配置
任务定义
### 5.2 任务执行与AGV交互
任务执行模块 ↔ AGV控制接口 ↔ 机器人
任务块记录DAO ↔ vwed_blockrecord

View File

@ -0,0 +1,494 @@
# 天风任务系统 (AMR Task System) 数据库完整分析
## 1. 系统概述
天风任务模块是一个管理和编排自动化移动机器人(AMR)任务的系统。该系统允许用户创建、调度和监控各种类型的机器人任务,包括物料运输、站点状态管理等。系统采用模块化设计,通过任务模板、任务定义、任务执行记录等组件实现灵活的任务管理。
## 2. 完整数据库表结构及功能分析
### 2.1 核心任务定义和执行相关表
#### t_windtaskdef任务定义表
- **功能**:定义任务模板,包含任务流程和逻辑
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 任务定义唯一标识
- `label`: VARCHAR(255) - 任务名称标签
- `created_by`: VARCHAR(255) - 创建用户ID
- `version`: INT - 任务版本号
- `detail`: LONGTEXT - 任务详细定义JSON格式包含输入参数、根块配置等
- `template_name`: VARCHAR(255) - 所使用的模板名称
- `period`: INT NOT NULL DEFAULT 1000 - 周期时间(毫秒)
- `periodic_task`: INT NOT NULL DEFAULT 0 - 是否为周期任务
- `status`: INT DEFAULT 0 - 任务状态
- `if_enable`: INT NOT NULL DEFAULT 0 - 是否启用
- `delay`: INT NOT NULL DEFAULT 3000 - 延迟时间(毫秒)
- `release_sites`: BIT(1) - 释放站点
- `create_date`: DATETIME - 创建日期
- `remark`: VARCHAR(255) - 备注
- `tenant_id`: VARCHAR(255) NOT NULL - 租户ID用于多租户隔离
- `user_token`: VARCHAR(500) - 用户token值每次请求需要用到的认证信息
#### t_windtaskrecord任务执行记录表
- **功能**:记录任务的执行情况和结果
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 记录ID
- `def_id`: VARCHAR(255) - 对应的任务定义ID
- `def_label`: VARCHAR(150) - 任务标签
- `def_version`: INT - 任务定义版本
- `created_on`: DATETIME - 创建时间
- `ended_on`: DATETIME - 结束时间
- `ended_reason`: LONGTEXT - 结束原因
- `status`: INT - 任务状态1001: 进行中, 1003: 已完成, 1006: 失败)
- `input_params`: LONGTEXT - 输入参数
- `path`: TEXT - 执行路径记录AGV移动路径
- `agv_id`: VARCHAR(150) - 执行任务的AGV设备ID
- `parent_task_record_id`: VARCHAR(255) - 父任务记录ID
- `root_task_record_id`: VARCHAR(255) - 根任务记录ID
- `state_description`: VARCHAR(255) - 状态描述
- `executor_time`: INT - 执行时间
- `first_executor_time`: DATETIME - 首次执行时间
- `if_have_child_task`: BIT(1) - 是否有子任务
- `periodic_task`: INT NOT NULL DEFAULT 0 - 是否为周期任务
- `priority`: INT NOT NULL DEFAULT 1 - 优先级
- `root_block_state_id`: VARCHAR(255) - 根块状态ID
- `work_stations`: VARCHAR(255) - 工作站
- `work_types`: VARCHAR(255) - 工作类型
- `task_def_detail`: LONGTEXT - 任务定义详情
- `variables`: LONGTEXT - 变量信息
- `call_work_station`: VARCHAR(255) - 调用工作站
- `call_work_type`: VARCHAR(255) - 调用工作类型
#### t_windtasklog任务日志表
- **功能**:记录任务执行过程中的详细日志信息,用于监控和调试
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 日志记录ID
- `create_time`: DATETIME - 日志创建时间
- `level`: INT - 日志级别1: 信息, 3: 错误等)
- `message`: LONGTEXT - 日志消息内容
- `task_block_id`: INT - 任务块ID
- `task_id`: VARCHAR(255) - 对应的任务定义ID
- `task_record_id`: VARCHAR(255) - 对应的任务执行记录ID
#### t_windblockrecord任务块执行记录表
- **功能**:记录任务块的执行情况,一个任务由多个任务块组成
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 记录ID
- `block_name`: VARCHAR(255) - 块名称
- `block_id`: VARCHAR(255) - 块ID
- `block_config_id`: VARCHAR(255) - 块配置ID
- `block_input_params`: LONGTEXT - 块输入参数
- `block_input_params_value`: LONGTEXT - 块输入参数值
- `block_out_params_value`: LONGTEXT - 块输出参数值
- `block_internal_variables`: LONGTEXT - 块内部变量
- `task_id`: VARCHAR(255) - 关联的任务定义ID
- `task_record_id`: VARCHAR(255) - 关联的任务记录ID
- `started_on`: DATETIME - 开始时间
- `ended_on`: DATETIME - 结束时间
- `ended_reason`: LONGTEXT - 结束原因
- `status`: INT - 块执行状态
- `ctrl_status`: INT - 控制状态
- `input_params`: LONGTEXT - 输入参数
- `internal_variables`: LONGTEXT - 内部变量
- `output_params`: LONGTEXT - 输出参数
- `version`: INT - 版本号
- `remark`: LONGTEXT - 备注
### 2.2 任务模板和配置相关表
#### t_windtasktemplate任务模板表
- **功能**:定义可用的任务模板类型
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 模板ID
- `template_name`: VARCHAR(255) NOT NULL - 模板名称
- `template_description`: VARCHAR(255) NOT NULL - 模板描述
- `template_if_enable`: INT NOT NULL DEFAULT 0 - 是否启用
- `template_dir`: VARCHAR(255) - 模板目录
### 2.3 数据缓存相关表
#### t_winddatacache数据缓存表
- **功能**:存储系统配置和临时数据
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 缓存ID
- `data`: LONGTEXT - 缓存数据JSON格式
#### t_winddatacachesplit用户数据缓存表
- **功能**:存储用户特定的缓存数据,支持更高效的数据索引和检索
- **主要字段**
- `id`: VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL PRIMARY KEY - 缓存记录ID
- `data_key`: LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL - 数据键名
- `data_value`: LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL - 数据值
- `updated_on`: DATETIME NULL - 更新时间
- INDEX `dataKeyIndex`(`data_key`(768) ASC) USING BTREE - 数据键名索引,提高查询效率
#### t_modbus_configModbus配置表
- **功能**存储Modbus通信配置参数用于PLC等设备的通信连接和数据交换
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 配置记录ID
- `name`: VARCHAR(255) NOT NULL - 配置名称(如"料道信号监控-PLC-1"
- `ip`: VARCHAR(50) NOT NULL - 设备IP地址
- `port`: INT NOT NULL - 通信端口号
- `slave_id`: INT NOT NULL - 从站ID
- `address_type`: VARCHAR(10) NOT NULL - 地址类型(如"3x"
- `address_number`: INT NOT NULL - 地址编号
- `task_id`: VARCHAR(255) - 天风任务id
- `target_value`: INT - 目标值
- `remark`: VARCHAR(255) - 备注(如"1为货物到位0为空"
- `create_date`: DATETIME - 创建时间
- `update_date`: DATETIME - 更新时间
- `status`: INT DEFAULT 0 - 状态1:启用, 0:禁用)
- `tenant_id`: VARCHAR(255) - 租户ID
### 2.4 在线脚本相关表
#### t_wind_script在线脚本表
- **功能**存储系统中的Python脚本
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 脚本唯一标识
- `name`: VARCHAR(255) NOT NULL - 脚本名称
- `folder_path`: VARCHAR(255) DEFAULT '/' - 脚本所在目录路径
- `file_name`: VARCHAR(255) NOT NULL - 脚本文件名
- `description`: VARCHAR(500) - 脚本功能描述
- `code`: LONGTEXT NOT NULL - 脚本代码内容
- `version`: INT NOT NULL DEFAULT 1 - 当前版本号
- `status`: INT NOT NULL DEFAULT 1 - 状态(1:启用, 0:禁用)
- `is_public`: BIT(1) NOT NULL DEFAULT 1 - 是否公开
- `tags`: VARCHAR(255) - 标签,用于分类查询
- `created_by`: VARCHAR(255) - 创建者
- `created_on`: DATETIME - 创建时间
- `updated_by`: VARCHAR(255) - 最后更新者
- `updated_on`: DATETIME - 最后更新时间
- `test_params`: LONGTEXT - 测试参数(JSON格式)
- UNIQUE KEY `uk_folder_filename` (`folder_path`, `file_name`) - 确保同目录下文件名唯一
#### t_wind_script_version脚本版本表
- **功能**:保存脚本历史版本
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 版本记录ID
- `script_id`: VARCHAR(255) NOT NULL - 关联的脚本ID
- `version`: INT NOT NULL - 版本号
- `code`: LONGTEXT NOT NULL - 该版本代码
- `change_log`: TEXT - 版本变更说明
- `created_by`: VARCHAR(255) - 创建者
- `created_on`: DATETIME - 创建时间
- UNIQUE KEY `uk_script_version` (`script_id`, `version`) - 确保脚本版本唯一
#### t_wind_script_log脚本执行日志表
- **功能**:记录脚本执行情况
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 日志ID
- `script_id`: VARCHAR(255) NOT NULL - 关联的脚本ID
- `version`: INT NOT NULL - 使用的脚本版本
- `task_record_id`: VARCHAR(255) - 关联的任务记录ID
- `block_record_id`: VARCHAR(255) - 关联的任务块记录ID
- `input_params`: LONGTEXT - 输入参数(JSON格式)
- `output_result`: LONGTEXT - 输出结果(JSON格式)
- `status`: INT - 执行状态(1:成功, 0:失败)
- `error_message`: TEXT - 错误信息
- `execution_time`: INT - 执行耗时(毫秒)
- `started_on`: DATETIME - 开始时间
- `ended_on`: DATETIME - 结束时间
### 2.5 接口定义相关表
#### t_interfacedefhistory接口定义历史表
- **功能**:存储系统接口的定义和版本历史
- **主要字段**
- `id`: VARCHAR(255) NOT NULL PRIMARY KEY - 接口定义历史记录ID
- `create_date`: DATETIME - 创建日期
- `detail`: LONGTEXT - 接口详细定义JSON格式
- `method`: VARCHAR(255) NOT NULL - 请求方法(GET, POST, PUT, DELETE等)
- `project_id`: VARCHAR(255) - 关联的项目ID
- `url`: VARCHAR(255) NOT NULL - 接口URL
- `version`: INT - 版本号
- UNIQUE INDEX `uniq`(`method`, `url`, `version`) - 确保接口定义唯一
## 3. 表关系图
```
┌─────────────────────────┐ ┌────────────────────────┐ ┌───────────────────────┐
│ t_windtasktemplate │───────▶│ t_windtaskdef │◀───────│ t_wind_script │
│ (任务模板表) │ │ (任务定义表) │ │ (在线脚本表) │
└─────────────────────────┘ └──────────┬─────────────┘ └───────────┬───────────┘
▲ │ │
│ │ │
┌───────────────────────┐│ │ │
│ t_interfacedefhistory|│ │ │
│ (接口定义历史表) │┘ │ │
└───────────────────────┘ │ │
│ │
│ 实例化 │ 版本管理
▼ ▼
┌────────────────────────┐ ┌───────────────────────┐
│ t_windtaskrecord │ │ t_wind_script_version│
│ (任务执行记录表) │ │ (脚本版本表) │
└──────────┬─────────────┘ └───────────────────────┘
├────────────────┐
│ │
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ t_windblockrecord │───▶│ t_windtasklog │
│ (任务块执行记录表) │ │ (任务日志表) │
└────┬───────────────────┘ └────────────────────────┘
┌────────────────────┐ ┌────────────────────┐
│ t_winddatacache │ │ t_modbus_config │
│ (数据缓存表) │ │ (Modbus配置表) │
└────────────────────┘ └────────────────────┘
┌────────────────────────┐ ┌────────────────────┐
│ t_wind_script_log │◀────│ t_wind_script │
│ (脚本执行日志表) │ │ (在线脚本表) │
└────────────────────────┘ └────────────────────┘
```
## 4. 简化数据流分析
### 4.1 任务创建与执行流程
1. **任务定义阶段**
- 在`t_windtaskdef`表中创建任务定义
- 任务定义关联到特定的任务模板(`t_windtasktemplate`
- 当任务包含ScriptBp组件时会在`detail`中引用`t_wind_script`表的脚本
- 当任务包含接口调用组件时,会在`detail`中引用`t_interfacedefhistory`表的接口
- 定义输入参数、根块配置等详细信息
2. **任务实例化阶段**
- 当任务被触发时,在`t_windtaskrecord`表中创建记录
- 系统根据任务定义的`input_params`传入参数
- 如果是子任务,会记录`parent_task_record_id`
3. **任务执行阶段**
- 系统解析任务定义中的`detail`字段,确定执行流程
- 任务执行过程中,为每个执行块在`t_windblockrecord`表中创建记录
- 当执行到ScriptBp块时系统会调用相应的Python脚本执行
- 当任务需要与PLC等设备通信时会查询`t_modbus_config`表获取通信配置
- 块执行记录包含输入参数、输出参数、状态等信息
- AGV执行路径被记录在任务记录的`path`字段中
- 执行过程中可能需要访问或更新`t_winddatacache`中的数据
4. **任务完成阶段**
- 任务执行完成后,更新`t_windtaskrecord`中的状态、结束时间、结束原因
- 同时更新所有相关块记录的状态
## 5. 任务类型分析
从任务模板表(`t_windtasktemplate`)和任务定义表(`t_windtaskdef`)中,可以看出系统支持以下几种任务类型:
1. **流水线生产任务** (Pulsating production line)
- 执行从一个位置到多个目标位置的物料运输
- 适用于生产线场景,需要在多个工位间循环运送物料
2. **组装订单任务** (Assemble order)
- 处理从起点到终点的物料运输
- 适用于物料从源头到目的地的直接运输
3. **高密度库位任务** (Dense peak bit)
- 用于高密度存储区域的物料移动
- 包括三种子类型:
- lineOne从密集区到单点
- lineTwo从单点到密集区
- updateSite更新站点状态
- 适用于仓库密集货架区域的物料存取
4. **用户自定义任务** (userTemplate)
- 允许用户自定义任务流程
- 大部分在系统中的任务使用这种模板
- 提供最大的灵活性,可以组合各种任务块
## 6. 任务块类型和逻辑分析
### 6.1 主要任务块类型
`t_windblockrecord``t_windtaskdef`的详细字段分析,系统使用以下主要任务块类型:
1. **RootBp**:任务根块,所有任务的入口点
2. **CurrentTimeStampBp**:获取当前时间戳
3. **QueryIdleSiteBp**:查询空闲站点
4. **GetIdleSiteBp**:获取空闲站点
5. **GetIdleCrowdedSiteBp**:获取密集区的空闲站点
6. **SetSiteEmptyBp**:设置站点为空
7. **SetSiteFilledBp**:设置站点为已填充
8. **SetSiteLockedBp**:锁定站点
9. **SetSiteUnlockedBp**:解锁站点
10. **CSelectAgvBp**选择AGV执行任务
11. **CAgvOperationBp**AGV操作移动、装卸等
12. **SubTaskBp**:子任务
13. **IfBp**:条件判断
14. **IfElseBp**:条件分支
15. **WhileBp**:循环
16. **BatchSettingSiteBp**:批量设置站点状态
17. **IterateListBp**:列表迭代
18. **CombinedOrderBp**:组合订单
19. **NoticeOperatorByUserBp**:通知操作员
20. **CacheDataBp**:缓存数据
21. **PrintBp**:打印信息
22. **SetTaskVariableBp**:设置任务变量
23. **ScriptVariablesBp**:脚本变量
24. **TaskStateBp**:任务状态
25. **SkipToComponent**:跳转到组件
26. **ScriptBp**Python脚本任务块调用在线脚本执行自定义逻辑
27. **ApiCallBp**接口调用任务块调用预定义的API接口
### 6.2 任务块组合逻辑
任务块之间可以通过以下方式组合:
1. **序列执行**:一个块执行完后,执行下一个块
2. **条件分支**:通过`IfBp``IfElseBp`实现条件判断和分支执行
3. **循环执行**:通过`WhileBp``IterateListBp`实现循环和迭代
4. **子任务嵌套**:通过`SubTaskBp`调用其他任务定义
5. **跳转执行**:通过`SkipToComponent`实现跳转到指定组件
6. **脚本执行**:通过`ScriptBp`调用自定义Python脚本执行复杂逻辑
7. **接口调用**:通过`ApiCallBp`调用预定义的接口,实现外部系统交互
### 6.3 典型任务执行流程示例
#### 示例1WH到PKG的运输任务
```
1. CurrentTimeStampBp获取时间戳用于任务ID
2. QueryIdleSiteBp查询起点WH区域的站点状态
3. QueryIdleSiteBp查询终点PKG区域的站点状态
4. IfElseBp检查站点状态是否满足要求
5. SetSiteEmptyBp将起点站点标记为空
6. SetSiteFilledBp将终点站点标记为已填充
7. TaskStateBp更新任务状态描述
8. CSelectAgvBp选择合适的AGV执行运输
9. 完成任务
```
#### 示例2高密度库区物料取出任务
```
1. GetIdleCrowdedSiteBp从密集区获取有物料的站点
2. SetSiteLockedBp锁定终点站点
3. CSelectAgvBp选择合适的AGV
a. CAgvOperationBpAGV前往前置点
b. GetIdleCrowdedSiteBp获取实际的起点站点
c. CAgvOperationBpAGV前往起点站点
d. SetSiteEmptyBp将起点站点标记为空
e. SetSiteUnlockedBp解锁起点站点
f. CAgvOperationBpAGV前往终点站点
g. SetSiteUnlockedBp解锁终点站点
```
#### 示例3使用自定义脚本的任务流程
```
1. ScriptBp调用自定义Python脚本执行数据分析或复杂业务逻辑
a. 输入参数:从任务输入或前序任务块获取
b. 脚本执行调用t_wind_script表中的Python脚本
c. 输出结果:返回处理结果给任务流程
2. IfElseBp根据脚本返回结果判断后续流程
3. 根据条件执行不同分支
```
#### 示例4使用接口调用的任务流程
```
1. ApiCallBp调用预定义的外部系统接口
a. 准备请求参数:从任务变量或前序任务块获取参数
b. 接口执行调用t_interfacedefhistory表中定义的接口
c. 响应处理:将接口返回的结果映射到任务变量
2. IfElseBp根据接口返回结果判断后续处理逻辑
3. SubTaskBp根据需要触发后续子任务
```
#### 示例5使用Modbus通信的任务流程
```
1. ModbusBp与PLC设备进行Modbus通信
a. 配置获取从t_modbus_config表获取通信参数(IP, 端口, 从站ID等)
b. 读取操作:读取指定地址类型和地址编号的数据
c. 数据处理:将读取到的数据与目标值比较
2. IfElseBp根据Modbus返回值判断后续处理逻辑
a. 如返回值=1料道有物料
i. CSelectAgvBp选择合适的AGV
ii. CAgvOperationBpAGV前往料道位置取料
iii. TaskStateBp更新任务状态为"取料完成"
b. 如返回值=0料道无物料
i. TaskStateBp更新任务状态为"等待物料"
ii. PrintBp记录日志"料道暂无物料"
3. ScriptBp调用Python脚本更新状态到其他系统
```
## 7. 系统特点与设计理念
1. **模块化设计**
- 任务被分解为多个可重用的任务块
- 通过组合不同的任务块可以定义复杂的任务流程
- 便于扩展和定制化
2. **灵活性**
- 支持多种任务模板适应不同场景
- 任务定义中的JSON配置允许高度定制化
- 用户可以自定义任务流程
- 通过在线Python脚本扩展系统功能
3. **层次结构**
- 支持任务嵌套(主任务和子任务)
- 任务块之间可以建立依赖关系
- 支持复杂的业务流程编排
4. **状态管理**
- 详细记录任务和任务块的执行状态
- 支持任务恢复和错误处理
- 提供完整的执行历史记录
5. **资源协调**
- 通过锁定/解锁站点来避免资源冲突
- AGV选择机制确保任务分配给合适的设备
- 支持多AGV协同工作
6. **可编程性**
- 通过在线Python脚本模块允许用户编写自定义业务逻辑
- 无需修改系统代码即可扩展系统功能
- 支持复杂业务场景的快速实现
7. **外部设备集成**
- 通过Modbus配置表支持与PLC等工业控制设备的通信
- 可监控生产线信号状态,触发相应任务
- 实现生产自动化与物流自动化的无缝衔接
## 8. 在线脚本和接口与任务系统的关系
### 8.1 集成机制
1. **脚本集成**
- 在任务定义中使用ScriptBp类型任务块
- 在`t_windtaskdef`表的`detail`字段配置脚本关联信息
- 脚本执行时会记录在`t_wind_script_log`表,记录与脚本关联但不与任务块执行记录直接关联
2. **接口集成**
- 在任务定义中使用ApiCallBp类型任务块
- 在`t_windtaskdef`表的`detail`字段引用`t_interfacedefhistory`中定义的接口
- 接口定义表仅与任务定义表关联,用于任务设计阶段
3. **Modbus集成**
- 在任务定义中使用ModbusBp类型任务块
- 任务块引用`t_modbus_config`表中的配置参数
- 支持PLC信号状态的读取和写入操作
- 可基于PLC信号状态触发任务或更新系统状态
### 8.2 应用场景
1. **脚本应用场景**
- 复杂业务逻辑处理
- 系统集成与数据交互
- 数据分析和报告生成
- 动态业务规则执行
2. **接口应用场景**
- 外部系统集成(ERP、WMS等)
- 数据交换和同步
- 远程控制与指令发送
- 消息通知和事件触发
3. **Modbus应用场景**
- 生产线料道信号监控
- PLC控制器数据交换
- 设备状态采集与监控
- 自动化生产线与AGV系统联动
- 区域热处理等工艺流程的自动控制
通过脚本、接口和Modbus模块天风任务系统获得了更高的灵活性和扩展性能够快速适应不同客户和场景的需求变化同时能够无缝集成到现有的企业IT生态系统和工业自动化系统中。

Binary file not shown.

0
agents/__init__.py Normal file
View File

0
agents/llm/__init__.py Normal file
View File

3
agents/llm/base_llm.py Normal file
View File

@ -0,0 +1,3 @@
"""
LLM基类
"""

View File

0
agents/teams/__init__.py Normal file
View File

0
agents/tools/__init__.py Normal file
View File

View File

@ -0,0 +1,3 @@
"""
智能体相关工具
"""

243
app.py Normal file
View File

@ -0,0 +1,243 @@
# app.py
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.exceptions import RequestValidationError
import logging
import time
import traceback
from utils.logger import get_logger
from contextlib import asynccontextmanager
import uvicorn
import os
# 导入配置
from config.settings import settings
from config.error_messages import VALIDATION_ERROR_MESSAGES, HTTP_ERROR_MESSAGES
# 导入数据库相关
from data.session import init_database, close_database_connections, close_async_database_connections
from data.cache import redis_client
# 引入路由
from routes.database import router as db_router
from routes.template_api import router as template_router
from routes.task_api import router as task_router
from routes.common_api import router as common_router, format_response
from routes.task_edit_api import router as task_edit_router
from routes.script_api import router as script_router
# 设置日志
logger = get_logger("app")
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
应用程序生命周期管理
启动时初始化数据库和任务调度器关闭时清理资源
"""
# 启动前的初始化操作
# 初始化数据库
init_database()
# 初始化Redis连接
if redis_client.get_client() is None:
logger.warning("Redis连接失败部分功能可能无法正常使用")
# 启动增强版任务调度器
from services.enhanced_scheduler import scheduler
await scheduler.start(worker_count=settings.TASK_SCHEDULER_MIN_WORKER_COUNT)
logger.info(f"增强版任务调度器已启动,最小工作线程数: {settings.TASK_SCHEDULER_MIN_WORKER_COUNT},最大工作线程数: {settings.TASK_SCHEDULER_MAX_WORKER_COUNT}")
yield
# 应用程序关闭前的清理操作
logger.info("应用程序关闭中...")
# 停止增强版任务调度器
from services.enhanced_scheduler import scheduler
await scheduler.stop()
logger.info("增强版任务调度器已停止")
await close_async_database_connections() # 关闭异步数据库连接
close_database_connections() # 关闭同步数据库连接
# 创建FastAPI应用
app = FastAPI(
title=settings.APP_NAME,
description=settings.APP_DESCRIPTION,
version=settings.APP_VERSION,
lifespan=lifespan,
debug=settings.DEBUG
)
# 添加CORS中间件
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
allow_methods=settings.CORS_ALLOW_METHODS,
allow_headers=settings.CORS_ALLOW_HEADERS,
)
# 请求日志中间件
@app.middleware("http")
async def log_requests(request: Request, call_next):
"""记录请求日志的中间件"""
start_time = time.time()
# 获取请求信息
method = request.method
url = request.url.path
client_host = request.client.host if request.client else "unknown"
# 记录请求
logger.info(f"请求开始: {method} {url} 来自 {client_host}")
try:
# 处理请求
response = await call_next(request)
# 计算处理时间
process_time = time.time() - start_time
logger.info(f"请求完成: {method} {url} 状态码: {response.status_code} 耗时: {process_time:.4f}")
return response
except Exception as e:
# 记录异常
process_time = time.time() - start_time
logger.error(f"请求异常: {method} {url} 耗时: {process_time:.4f}")
logger.error(f"异常详情: {str(e)}")
logger.error(traceback.format_exc())
# 返回通用错误响应
return JSONResponse(
status_code=500,
content=format_response(
code=500,
message="服务器内部错误,请联系管理员",
data=None
)
)
# 全局验证错误处理器
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
"""
处理验证错误将错误消息转换为中文并提供更友好的错误提示
包括显示具体缺失的字段名称
"""
errors = exc.errors()
error_details = []
missing_fields = []
for error in errors:
error_type = error.get("type", "")
loc = error.get("loc", [])
# 获取完整的字段路径排除body/query等
if len(loc) > 1 and loc[0] in ["body", "query", "path", "header"]:
field_path = ".".join(str(item) for item in loc[1:])
else:
field_path = ".".join(str(item) for item in loc)
# 获取中文错误消息
message = VALIDATION_ERROR_MESSAGES.get(error_type, error.get("msg", "验证错误"))
# 替换消息中的参数
context = error.get("ctx", {})
for key, value in context.items():
message = message.replace(f"{{{key}}}", str(value))
# 收集缺失字段
if error_type == "missing" or error_type == "value_error.missing":
missing_fields.append(field_path)
error_details.append({
"field": field_path,
"message": message,
"type": error_type
})
# 构建友好的错误响应
if missing_fields:
missing_fields_str = ", ".join(missing_fields)
error_message = f"缺少必填字段: {missing_fields_str}"
elif error_details:
# 提取第一个错误的字段和消息
first_error = error_details[0]
error_message = f"参数 '{first_error['field']}' 验证失败: {first_error['message']}"
else:
error_message = "参数验证失败"
return JSONResponse(
status_code=400,
content={
"code": 400,
"message": error_message,
"data": error_details if len(error_details) > 1 else None
}
)
# HTTP错误处理器
@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
"""处理HTTP异常转换为统一的响应格式"""
status_code = exc.status_code
# 获取错误消息,优先使用自定义消息,否则使用配置中的错误消息
message = exc.detail
if isinstance(message, str) and message == "Not Found":
message = HTTP_ERROR_MESSAGES.get(status_code, message)
return JSONResponse(
status_code=status_code,
content=format_response(
code=status_code,
message=message,
data=None
)
)
# 全局异常处理器
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
"""处理所有未捕获的异常"""
logger.error(f"未捕获异常: {str(exc)}")
logger.error(traceback.format_exc())
return JSONResponse(
status_code=500,
content=format_response(
code=500,
message="服务器内部错误,请联系管理员",
data=None if not settings.DEBUG else str(exc)
)
)
# 注册路由
app.include_router(common_router)
app.include_router(db_router)
app.include_router(template_router)
app.include_router(task_router)
app.include_router(task_edit_router)
app.include_router(script_router)
# 根路由
@app.get("/")
async def root():
"""API根路由显示系统基本信息"""
return {
"app_name": settings.APP_NAME,
"version": settings.APP_VERSION,
"description": settings.APP_DESCRIPTION,
"status": "running"
}
# 主函数
if __name__ == "__main__":
# 从环境变量中获取端口默认为8000
port = int(os.environ.get("PORT", settings.SERVER_PORT))
# 启动服务器
uvicorn.run(
"app:app",
host="0.0.0.0",
port=port,
reload=settings.DEBUG,
workers=settings.SERVER_WORKERS
)

0
components/__init__.py Normal file
View File

View File

@ -0,0 +1,3 @@
"""
基础组件
"""

0
config/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,182 @@
{
"label": "HTTP 请求",
"order": 1,
"blocks": [
{
"type": "All",
"name": "GetBp",
"label": "发送 GET 请求",
"description": "",
"inputParams": [
{
"name": "url",
"type": "String",
"label": "请求的 URL",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "header",
"type": "JsonPair",
"label": "Header",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retry",
"type": "Boolean",
"label": "是否重试",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryTimes",
"type": "Integer",
"label": "重试次数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryInterval",
"type": "Long",
"label": "重试时间间隔(ms)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"response": {
"type": "String",
"label": "请求返回的字符串",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 发送 GET 请求 (GetBp)\n\n### 描述\n本块用于发送 GET 请求。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| url | 必填 | String | 请求的 URL |\n| header | 非必填 | JsonPair | Header |\n| retry | 非必填 | Boolean | 是否重试 |\n| retryTimes | 非必填 | Integer | 重试次数 |\n| retryInterval | 非必填 | Long | 重试时间间隔(ms) |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| response | String | 请求返回的字符串 |\n"
},
{
"type": "All",
"name": "PostBp",
"label": "发送 POST 请求",
"description": "",
"inputParams": [
{
"name": "url",
"type": "String",
"label": "请求的 URL",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "param",
"type": "String",
"label": "请求的参数, JSON 类型",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "header",
"type": "JsonPair",
"label": "Header",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "mediaType",
"type": "String",
"label": "类型",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"label": "默认",
"value": "JSON"
},
{
"label": "application/json",
"value": "JSON"
},
{
"label": "text/html",
"value": "HTML"
},
{
"label": "application/xml",
"value": "XML"
},
{
"label": "application/x-www-form-urlencoded",
"value": "XWWWFORMURLENCODED"
},
{
"label": "application/javascript",
"value": "JAVASCRIPT"
}
]
},
{
"name": "retry",
"type": "Boolean",
"label": "是否重试",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryTimes",
"type": "Integer",
"label": "重试次数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryInterval",
"type": "Long",
"label": "重试时间间隔(ms)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"response": {
"type": "Object",
"label": "响应的 JSON",
"description": null,
"className": "com.seer.rds.vo.response.HttpResponse"
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 发送 POST 请求 (PostBp)\n\n### 描述\n本块用于发送 POST 请求。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| url | 必填 | String | 请求的 URL |\n| param | 必填 | String | 请求的参数, JSON 类型 |\n| header | 非必填 | JsonPair | Header |\n| mediaType | 非必填 | String | 类型 |\n| retry | 非必填 | Boolean | 是否重试 |\n| retryTimes | 非必填 | Integer | 重试次数 |\n| retryInterval | 非必填 | Long | 重试时间间隔(ms) |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| response | Object | 响应的 JSON |\n"
}
]
}

View File

@ -0,0 +1,156 @@
{
"label": "设备",
"order": 8,
"blocks": [
{
"type": "Normal",
"name": "ModbusCommonReadNameBp",
"label": "通用读取 Modbus 值(Name)",
"description": "",
"inputParams": [
{
"name": "instanceName",
"type": "String",
"label": "Name",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "address",
"type": "Integer",
"label": "地址编号",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "remark",
"type": "String",
"label": "地址说明",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "## 通用读取 Modbus 值(Name) (ModbusCommonReadNameBp)\n\n### 描述\n本块用于通过设备名称和地址读取Modbus设备的值。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------------|---------|----------|------------|\n| instanceName | 必填 | String | Name |\n| address | 选填 | Integer | 地址编号 |\n| remark | 选填 | String | 地址说明 |\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|-------------|----------|------------|\n| modbusValue | String | Modbus值 |\n\n### 输出参数\n无",
"outputParams": {},
"contextVariables": {
"modbusValue": {
"type": "String",
"label": "Modbus值",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": ""
},
{
"type": "Normal",
"name": "ModbusCommonWaitNameBp",
"label": "通用等待 Modbus 值(Name)",
"description": "",
"inputParams": [
{
"name": "targetValue",
"type": "Integer",
"label": "目标值",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "instanceName",
"type": "String",
"label": "Name",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "address",
"type": "Integer",
"label": "地址编号",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "remark",
"type": "String",
"label": "地址说明",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 通用等待 Modbus 值(Name) (ModbusCommonWaitNameBp)\n\n### 描述\n本块用于等待Modbus设备的值达到目标值。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------------|---------|----------|------------|\n| targetValue | 必填 | Integer | 目标值 |\n| instanceName | 必填 | String | Name |\n| address | 选填 | Integer | 地址编号 |\n| remark | 选填 | String | 地址说明 |\n\n### 上下文变量\n无\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "ModbusCommonWriteNameBp",
"label": "通用写入 Modbus 值(Name)",
"description": "",
"inputParams": [
{
"name": "newValue",
"type": "Integer",
"label": "写入值",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "instanceName",
"type": "String",
"label": "Name",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "address",
"type": "Integer",
"label": "地址编号",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "remark",
"type": "String",
"label": "地址说明",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 通用写入 Modbus 值(Name) (ModbusCommonWriteNameBp)\n\n### 描述\n本块用于向Modbus设备写入新值。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------------|---------|----------|------------|\n| newValue | 必填 | Integer | 写入值 |\n| instanceName | 必填 | String | Name |\n| address | 选填 | Integer | 地址编号 |\n| remark | 选填 | String | 地址说明 |\n\n### 上下文变量\n无\n\n### 输出参数\n无"
}
]
}

View File

@ -0,0 +1,246 @@
{
"label": "基础",
"order": 4,
"blocks": [
{
"type": "All",
"name": "CheckTaskRecordIdIsExistBp",
"label": "校验任务实例Id是否存在",
"description": "",
"inputParams": [
{
"name": "taskRecordId",
"type": "String",
"label": "任务实例Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"taskRecordIdIsExist": {
"type": "boolean",
"label": "Id是否存在",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null
},
{
"type": "All",
"name": "ReleaseResourceBp",
"label": "立即释放任务资源(相同设备下可以继续下达相同任务)",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null
},
{
"type": "All",
"name": "CreateUuidBp",
"label": "创建唯一id",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"createUuid": {
"type": "String",
"label": "创建唯一id",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 校验任务实例Id是否存在 (CheckTaskRecordIdIsExistBp)\n\n### 描述\n本块用于校验任务实例Id是否存在。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|--------------|---------|--------|------------|\n| taskRecordId | 必填 | String | 任务实例Id |\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|-----------------|----------|-----------|\n| taskRecordIdIsExist | boolean | Id是否存在 |\n"
},
{
"type": "All",
"name": "CurrentTimeStampBp",
"label": "当前时间戳",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"currentTimeStamp": {
"type": "Long",
"label": "当前时间戳",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 当前时间戳 (CurrentTimeStampBp)\n\n### 描述\n本块用于获取当前时间戳。\n\n### 输入参数\n无\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|-----------------|-------|------------|\n\n| currentTimeStamp | Long | 当前时间戳 |\n\n## 执行sql (JdbcExecuteBp)\n### 描述\n本块用于执行sql语句。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------|---------|--------|---------|\n| sql | 必填 | String | sql语句 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "JdbcExecuteBp",
"label": "执行sql",
"description": "",
"inputParams": [
{
"name": "sql",
"type": "String",
"label": "sql语句",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 查询sql (JdbcQueryBp)\n\n### 描述\n本块用于查询sql语句。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------|---------|--------|---------|\n| sql | 必填 | String | sql语句 |\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|-----------|--------|--------------|\n| resultSet | String | 查询sql返回值 |\n"
},
{
"type": "All",
"name": "JdbcQueryBp",
"label": "查询sql",
"description": "",
"inputParams": [
{
"name": "sql",
"type": "String",
"label": "sql语句",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"resultSet": {
"type": "String",
"label": "查询sql返回值",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 查询sql (JdbcQueryBp)\n\n### 描述\n本块用于查询sql语句。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|-------|---------|--------|---------|\n| sql | 必填 | String | sql语句 |\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|-----------|--------|--------------|\n| resultSet | String | 查询sql返回值 |\n"
},
{
"type": "All",
"name": "PrintBp",
"label": "打印",
"description": "",
"inputParams": [
{
"name": "message",
"type": "Any",
"label": "消息",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 打印 (PrintBp)\n\n### 描述\n本块用于打印信息。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| message | 非必填 | Any | 消息 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "StringToJsonArrayBp",
"label": "将字符串转换成JSON数组",
"description": "",
"inputParams": [
{
"name": "convertString",
"type": "String",
"label": "需要转换的字符串",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {
"convertArray": {
"type": "Object",
"label": "转换后的JSON数组",
"description": null
}
},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 将字符串转换成JSON数组 (StringToJsonArrayBp)\n\n### 描述\n本块用于将字符串转换成JSON数组。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|--------------|---------|--------|----------------|\n| convertString | 必填 | String | 需要转换的字符串 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n|--------------|--------|------------------|\n| convertArray | Object | 转换后的JSON数组 |\n"
},
{
"type": "All",
"name": "StringToJsonObjectBp",
"label": "将字符串转换成JSON对象",
"description": "",
"inputParams": [
{
"name": "convertString",
"type": "String",
"label": "需要转换的字符串",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {
"convertObject": {
"type": "Object",
"label": "转换后的JSON对象",
"description": null
}
},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 将字符串转换成JSON对象 (StringToJsonObjectBp)\n\n### 描述\n本块用于将字符串转换成JSON对象。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n|--------------|---------|--------|----------------|\n| convertString | 必填 | String | 需要转换的字符串 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n|--------------|--------|------------------|\n| convertObject | Object | 转换后的JSON对象 |\n"
},
{
"type": "All",
"name": "TimestampBp",
"label": "当前时间",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"timestamp": {
"type": "String",
"label": "时间",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 当前时间 (TimestampBp)\n\n### 描述\n本块用于获取当前时间。\n\n### 输入参数\n无\n\n### 上下文变量\n\n| 变量名 | 类型 | 描述 |\n|----------|--------|--------|\n| timestamp | String | 当前时间 |\n"
}
]
}

View File

@ -0,0 +1,319 @@
{
"label": "流程",
"order": 3,
"blocks": [
{
"type": "All",
"name": "BreakBp",
"label": "break",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null
},
{
"type": "All",
"name": "DelayBp",
"label": "延迟",
"description": "",
"inputParams": [
{
"name": "timeMillis",
"type": "Long",
"label": "毫秒",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 延迟 (DelayBp)\n\n### 描述\n本块用于延迟执行。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| timeMillis | 必填 | Long | 延迟时间(毫秒) |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "IfBp",
"label": "If",
"description": "",
"inputParams": [
{
"name": "condition",
"type": "Boolean",
"label": "条件",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## If (IfBp)\n\n### 描述\n本块用于条件判断。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| condition | 必填 | Boolean | 条件 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "IfElseBp",
"label": "If-Else",
"description": "",
"inputParams": [
{
"name": "conditionIf",
"type": "Boolean",
"label": "if条件",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {
"if": {
"label": "if为真",
"childrenMinNum": 1,
"childrenMaxNum": -1
},
"else": {
"label": "else",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## If-Else (IfElseBp)\n\n### 描述\n本块用于条件判断。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| conditionIf | 必填 | Boolean | 条件 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "IterateListBp",
"label": "遍历数组",
"description": "",
"inputParams": [
{
"name": "list",
"type": "JSONArray",
"label": "数组",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"index": {
"type": "Long",
"label": "循环索引",
"description": null
},
"item": {
"type": "Any",
"label": "当前项",
"description": null
}
},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 遍历数组 (IterateListBp)\n\n### 描述\n本块用于遍历数组。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| list | 必填 | JSONArray | 数组 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "ParallelFlowBp",
"label": "并行执行",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null
},
{
"type": "Normal",
"name": "RepeatNumBp",
"label": "重复执行N次",
"description": "",
"inputParams": [
{
"name": "num",
"type": "Long",
"label": "次数N<1000",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"index": {
"type": "Long",
"label": "循环索引",
"description": null
}
},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 重复执行N次 (RepeatNumBp)\n\n### 描述\n本块用于重复执行N次。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| num | 必填 | Long | 次数N<1000 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "ReturnBp",
"label": "return",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## return (ReturnBp)\n\n### 描述\n本块用于返回值。\n\n### 输入参数\n无\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SerialFlowBp",
"label": "串行执行",
"description": "",
"inputParams": [],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 串行执行 (SerialFlowBp)\n\n### 描述\n本块用于串行执行。\n\n### 输入参数\n无\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "ThrowExceptionBp",
"label": "抛出异常",
"description": "",
"inputParams": [
{
"name": "message",
"type": "String",
"label": "异常提示文本",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 抛出异常 (ThrowExceptionBp)\n\n### 描述\n本块用于抛出异常。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| message | 必填 | String | 异常提示文本 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "WhileBp",
"label": "while",
"description": "",
"inputParams": [
{
"name": "loopCondition",
"type": "Boolean",
"label": "循环条件",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "runOnce",
"type": "Boolean",
"label": "至少执行一次子块",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryPeriod",
"type": "Long",
"label": "循环时间间隔(ms)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "printContinuously",
"type": "Boolean",
"label": "是否持续打印日志(默认为false)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## while (WhileBp)\n\n### 描述\n本块用于循环执行。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| loopCondition | 必填 | Boolean | 循环条件 |\n\n### 输出参数\n无\n"
}
]
}

View File

@ -0,0 +1,567 @@
{
"label": "机器人调度",
"order": 7,
"blocks": [
{
"type": "Normal",
"name": "CAgvOperationBp",
"label": "机器人通用动作",
"description": "",
"inputParams": [
{
"name": "targetSiteLabel",
"type": "String",
"label": "目标站点名",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "spin",
"type": "Boolean",
"label": "允许随动",
"description": "",
"required": false,
"defaultValue": false,
"options": []
},
{
"name": "task",
"type": "JSONArray",
"label": "指令",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "binTask",
"type": "String",
"label": "binTask",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "param",
"type": "String",
"label": "参数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "preBinTask",
"type": "String",
"label": "预置binTask",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "param",
"type": "String",
"label": "参数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "JackLoad",
"type": "String",
"label": "顶升 JackLoad",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "inspired_unique",
"type": "Boolean",
"label": "启用识别",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "unique_file",
"type": "String",
"label": "识别文件",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "JackHeight",
"type": "String",
"label": "设置顶升高度 JackHeight",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "targetHeight",
"type": "Double",
"label": "目标高度",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
]
},
{
"name": "JackUnload",
"type": "String",
"label": "顶降 JackUnload",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "inspired_unique",
"type": "Boolean",
"label": "启用识别",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "Wait",
"type": "String",
"label": "等待 Wait",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "wait_time",
"type": "Integer",
"label": "等待时间(ms)",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
]
},
{
"name": "ForkLoad",
"type": "String",
"label": "叉车取货 ForkLoad",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "start_height",
"type": "Double",
"label": "起始高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "end_height",
"type": "Double",
"label": "结束高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "inspired_unique",
"type": "Boolean",
"label": "启用识别",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "unique_file",
"type": "String",
"label": "识别文件",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "special_height",
"type": "Double",
"label": "识别后高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "ForkUnload",
"type": "String",
"label": "降低叉齿 ForkUnload",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "start_height",
"type": "Double",
"label": "起始高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "end_height",
"type": "Double",
"label": "结束高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "inspired_unique",
"type": "Boolean",
"label": "启用识别",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "unique_file",
"type": "String",
"label": "识别文件",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "special_height",
"type": "Double",
"label": "识别后高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "ForkHeight",
"type": "String",
"label": "边走边升降叉齿 ForkHeight",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "start_height",
"type": "Double",
"label": "起始高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "fork_height",
"type": "Double",
"label": "货叉行走过程中举升高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "end_height",
"type": "Double",
"label": "结束高度",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
},
{
"name": "CustomCommand",
"type": "String",
"label": "自定义指令",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "command",
"type": "String",
"label": "指令方式",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "operation_name",
"type": "String",
"label": "操作名",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "param",
"type": "JSONArray",
"label": "属性",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
}
]
},
{
"name": "syspy/setDO.py",
"type": "String",
"label": "syspy/setDO.py",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "DO",
"type": "JSONArray",
"label": "设置DO",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
]
},
{
"name": "syspy/waitDO.py",
"type": "String",
"label": "syspy/waitDO.py",
"description": "",
"required": false,
"defaultValue": null,
"options": [
{
"name": "DO",
"type": "JSONArray",
"label": "设置DO",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "timeout",
"type": "Integer",
"label": "超时时间(秒)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
]
}
]
}
],
"extraInputParamsFunc": "agvOperationBpExtraInputParams",
"outputParams": {},
"contextVariables": {
"containerName": {
"type": "String",
"label": "料箱名",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 机器人通用动作 (CAgvOperationBp)\n\n### 描述\n本块用于执行机器人通用动作。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| targetSiteLabel | 必填 | String | 目标站点名 |\n| spin | 非必填 | Boolean | 允许随动 |\n| task | 非必填 | JSONArray | 指令 |\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "CSelectAgvBp",
"label": "选择执行机器人",
"description": "",
"inputParams": [
{
"name": "priority",
"type": "Long",
"label": "优先级",
"description": "越大优先级越高",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "vehicle",
"type": "String",
"label": "指定机器人",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "group",
"type": "String",
"label": "指定机器人组",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "keyRoute",
"type": "String",
"label": "关键路径",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"selectedAgvId": {
"type": "String",
"label": "选出的机器人",
"description": null
}
},
"children": {
"default": {
"label": "默认",
"childrenMinNum": 1,
"childrenMaxNum": -1
}
},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 选择执行机器人 (CSelectAgvBp)\n\n### 描述\n本块用于选择执行机器人。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| priority | 非必填 | Long | 优先级 |\n| vehicle | 非必填 | String | 指定机器人 |\n| group | 非必填 | String | 指定机器人组 |\n| keyRoute | 必填 | String | 关键路径 |\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "VehicleStationBp",
"label": "获取机器人位置",
"description": "",
"inputParams": [
{
"name": "vehicle",
"type": "String",
"label": "指定机器人",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"station": {
"type": "String",
"label": "当前位置",
"description": null
},
"lastStation": {
"type": "String",
"label": "上次位置",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取机器人位置 (VehicleStationBp)\n\n### 描述\n本块用于获取机器人位置。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| vehicle | 必填 | String | 指定机器人 |\n\n### 输出参数\n无\n"
},{
"type": "All",
"name": "GetBatteryLevelBp",
"label": "获取机器人电量",
"description": "",
"inputParams": [
{
"name": "vehicle",
"type": "String",
"label": "机器人ID",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"batteryLevel": {
"type": "Double",
"label": "电量",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取机器人电量 (GetBatteryLevelBp)\n\n### 描述\n本块用于获取机器人电量。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| vehicle | 必填 | String | 机器人ID |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "GetPGVCodeBp",
"label": "获取机器人 PGV 码",
"description": "",
"inputParams": [
{
"name": "vehicle",
"type": "String",
"label": "机器人ID",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"codeInfo": {
"type": "Boolean",
"label": "二维码信息",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取机器人 PGV 码 (GetPGVCodeBp)\n\n### 描述\n本块用于获取机器人 PGV 码。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| vehicle | 必填 | String | 机器人ID |\n\n### 输出参数\n无\n"
}
]
}

View File

@ -0,0 +1,70 @@
{
"label": "脚本",
"order": 0,
"blocks": [
{
"type": "All",
"name": "ScriptBp",
"label": "运行脚本",
"description": "",
"inputParams": [
{
"name": "functionName",
"type": "String",
"label": "函数名",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "functionArgs",
"type": "Any",
"label": "函数参数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null
},
{
"type": "All",
"name": "ScriptVariablesBp",
"label": "脚本设置task.variables",
"description": "",
"inputParams": [
{
"name": "functionName",
"type": "String",
"label": "函数名",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "functionArgs",
"type": "Any",
"label": "函数参数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null
}
]
}

View File

@ -0,0 +1,660 @@
{
"label": "库位",
"order": 5,
"blocks": [
{
"type": "All",
"name": "BatchSettingSiteBp",
"label": "批量设置库位",
"description": "",
"inputParams": [
{
"name": "siteIds",
"type": "JSONArray",
"label": "库位Ids",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "groupNames",
"type": "JSONArray",
"label": "库区集",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "filled",
"type": "Boolean",
"label": "占用",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "content",
"type": "String",
"label": "货物",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "type",
"type": "Boolean",
"label": "是否物理库位",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 批量设置库位 (BatchSettingSiteBp)\n\n### 描述\n本块用于批量设置库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteIds | 非必填 | JSONArray | 库位Ids |\n| groupNames | 非必填 | JSONArray | 库区集 |\n| filled | 必填 | Boolean | 占用 |\n| content | 非必填 | String | 货物 |\n| type | 非必填 | Boolean | 是否物理库位 |\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "GetIdleCrowdedSiteBp",
"label": "获取密集库位",
"description": "",
"inputParams": [
{
"name": "groupName",
"type": "JSONArray",
"label": "库区集",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "filled",
"type": "Boolean",
"label": "取/放",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "content",
"type": "String",
"label": "货物(取)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "lock",
"type": "Boolean",
"label": "获取库位后是否锁定",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retry",
"type": "Boolean",
"label": "是否重试",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "retryPeriod",
"type": "Long",
"label": "重试时间间隔(ms)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryNum",
"type": "Long",
"label": "重试次数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"siteId": {
"type": "String",
"label": "选出的库位",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取密集库位 (GetIdleCrowdedSiteBp)\n\n### 描述\n本块用于获取密集库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| groupName | 必填 | JSONArray | 库区集 |\n| filled | 必填 | Boolean | 取/放 |\n| content | 非必填 | String | 货物(取) |\n| lock | 非必填 | Boolean | 获取库位后是否锁定 |\n| retry | 必填 | Boolean | 是否重试 |\n| retryPeriod | 非必填 | Long | 重试时间间隔(ms) |\n| retryNum | 非必填 | Long | 重试次数 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| siteId | String | 选出的库位 |\n"
},
{
"type": "Normal",
"name": "GetIdleSiteBp",
"label": "获取库位",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位ID",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "content",
"type": "String",
"label": "货物",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "filled",
"type": "Boolean",
"label": "是否有货物",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "locked",
"type": "Boolean",
"label": "是否已锁定",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "type",
"type": "Boolean",
"label": "是否物理库位",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "groupName",
"type": "String",
"label": "库区名",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "lock",
"type": "Boolean",
"label": "获取库位后是否锁定",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "retryPeriod",
"type": "Long",
"label": "重试时间间隔(ms)",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "ifFair",
"type": "Boolean",
"label": "是否为公平锁",
"description": "",
"required": false,
"defaultValue": true,
"options": []
},
{
"name": "orderDesc",
"type": "Boolean",
"label": "是否为降序",
"description": "",
"required": false,
"defaultValue": true,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"siteId": {
"type": "String",
"label": "选出的库位",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取库位 (GetIdleSiteBp)\n\n### 描述\n本块用于获取库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 非必填 | String | 库位ID |\n| content | 非必填 | String | 货物 |\n| filled | 非必填 | Boolean | 是否有货物 |\n| locked | 必填 | Boolean | 是否已锁定 |\n| type | 非必填 | Boolean | 是否物理库位 |\n| groupName | 非必填 | String | 库区名 |\n| lock | 非必填 | Boolean | 获取库位后是否锁定 |\n| retryPeriod | 非必填 | Long | 重试时间间隔(ms) |\n| ifFair | 非必填 | Boolean | 是否为公平锁 |\n| orderDesc | 非必填 | Boolean | 是否为降序 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| siteId | String | 选出的库位 |\n"
},
{
"type": "All",
"name": "GetLockedSitesByTaskRecordIdBp",
"label": "根据任务实例ID获取所有加锁库位",
"description": "",
"inputParams": [
{
"name": "taskRecordId",
"type": "String",
"label": "任务实例Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"lockedSiteIdList": {
"type": "String",
"label": "该任务实例的所有加锁库位列表",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 根据任务实例ID获取所有加锁库位 (GetLockedSitesByTaskRecordIdBp)\n\n### 描述\n本块用于根据任务实例ID获取所有加锁库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| taskRecordId | 必填 | String | 任务实例Id |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| lockedSiteIdList | String | 该任务实例的所有加锁库位列表 |\n"
},
{
"type": "All",
"name": "GetSiteAttrBp",
"label": "获取库位扩展属性值",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "attrName",
"type": "String",
"label": "属性名称",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"attrValue": {
"type": "String",
"label": "属性值",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取库位扩展属性值 (GetSiteAttrBp)\n\n### 描述\n本块用于获取库位扩展属性值。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| attrName | 必填 | String | 属性名称 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| attrValue | String | 属性值 |\n"
},
{
"type": "All",
"name": "QueryIdleSiteBp",
"label": "查询库位",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位ID",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "content",
"type": "String",
"label": "货物",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "filled",
"type": "Boolean",
"label": "是否有货物",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "locked",
"type": "Boolean",
"label": "是否已锁定",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "type",
"type": "Boolean",
"label": "是否物理库位",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "groupName",
"type": "String",
"label": "库区名",
"description": "",
"required": false,
"defaultValue": null,
"options": []
},
{
"name": "orderDesc",
"type": "Boolean",
"label": "是否为降序",
"description": "",
"required": false,
"defaultValue": true,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"site": {
"type": "Object",
"label": "选出的库位",
"description": null,
"className": "com.seer.rds.model.worksite.WorkSite"
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 查询库位 (QueryIdleSiteBp)\n\n### 描述\n本块用于查询库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 非必填 | String | 库位ID |\n| content | 非必填 | String | 货物 |\n| filled | 非必填 | Boolean | 是否有货物 |\n| locked | 必填 | Boolean | 是否已锁定 |\n| type | 非必填 | Boolean | 是否物理库位 |\n| groupName | 非必填 | String | 库区名 |\n| orderDesc | 非必填 | Boolean | 是否为降序 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| site | Object | 选出的库位 |\n"
},
{
"type": "All",
"name": "SetSiteAttrBp",
"label": "设置库位扩展属性",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "attrName",
"type": "String",
"label": "属性名称",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "attrValue",
"type": "String",
"label": "属性值",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置库位扩展属性 (SetSiteAttrBp)\n\n### 描述\n本块用于设置库位扩展属性。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| attrName | 必填 | String | 属性名称 |\n| attrValue | 非必填 | String | 属性值 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SetSiteContentBp",
"label": "设置库位货物",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "content",
"type": "String",
"label": "货物",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置库位货物 (SetSiteContentBp)\n\n### 描述\n本块用于设置库位货物。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| content | 必填 | String | 货物 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SetSiteEmptyBp",
"label": "设置库位为空",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null
},
{
"type": "All",
"name": "SetSiteFilledBp",
"label": "设置库位为占用",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置库位为占用 (SetSiteFilledBp)\n\n### 描述\n本块用于设置库位为占用。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SetSiteLockedBp",
"label": "锁定库位",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "ifFair",
"type": "Boolean",
"label": "是否为公平锁",
"description": "",
"required": false,
"defaultValue": true,
"options": []
},
{
"name": "lockedId",
"type": "String",
"label": "加锁者",
"description": "",
"required": false,
"defaultValue": true,
"options": []
},
{
"name": "retryTimes",
"type": "Integer",
"label": "重试次数",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"success": {
"type": "Boolean",
"label": "锁定成功",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 锁定库位 (SetSiteLockedBp)\n\n### 描述\n本块用于锁定库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| ifFair | 非必填 | Boolean | 是否为公平锁 |\n| lockedId | 非必填 | String | 加锁者 |\n| retryTimes | 非必填 | Integer | 重试次数 |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| success | Boolean | 锁定成功 |\n"
},
{
"type": "All",
"name": "SetSiteTagsBp",
"label": "设置库位标签",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "tags",
"type": "String",
"label": "标签",
"description": "",
"required": false,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置库位标签 (SetSiteTagsBp)\n\n### 描述\n本块用于设置库位标签。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| tags | 非必填 | String | 标签 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SetSiteUnlockedBp",
"label": "解锁库位",
"description": "",
"inputParams": [
{
"name": "siteId",
"type": "String",
"label": "库位Id",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "unLockedId",
"type": "String",
"label": "解锁者",
"description": "",
"required": false,
"defaultValue": true,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 解锁库位 (SetSiteUnlockedBp)\n\n### 描述\n本块用于解锁库位。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| siteId | 必填 | String | 库位Id |\n| unLockedId | 非必填 | String | 解锁者 |\n\n### 输出参数\n无\n"
}
]
}

174
config/components/task.json Normal file
View File

@ -0,0 +1,174 @@
{
"label": "任务",
"order": 2,
"blocks": [
{
"type": "All",
"name": "CacheDataBp",
"label": "缓存数据",
"description": "",
"inputParams": [
{
"name": "key",
"type": "String",
"label": "缓存key",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "value",
"type": "String",
"label": "缓存value",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 缓存数据 (CacheDataBp)\n\n### 描述\n本块用于缓存数据。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| key | 必填 | String | 缓存key |\n| value | 必填 | String | 缓存value |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "ClearCacheDataBp",
"label": "清除缓存数据",
"description": "",
"inputParams": [
{
"name": "key",
"type": "String",
"label": "key",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 清除缓存数据 (ClearCacheDataBp)\n\n### 描述\n本块用于清除缓存数据。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| key | 必填 | String | 缓存key |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "GetCacheDataBp",
"label": "获取缓存数据",
"description": "",
"inputParams": [
{
"name": "key",
"type": "String",
"label": "缓存key",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {
"value": {
"type": "String",
"label": "缓存的数据",
"description": null
}
},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 获取缓存数据 (GetCacheDataBp)\n\n### 描述\n本块用于获取缓存数据。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| key | 必填 | String | 缓存key |\n\n### 输出参数\n\n| 参数名 | 类型 | 描述 |\n\n|---------|------|------|\n| value | String | 缓存的数据 |\n"
},
{
"type": "All",
"name": "SetTaskVariableBp",
"label": "设置任务变量",
"description": "",
"inputParams": [
{
"name": "varName",
"type": "String",
"label": "变量名",
"description": "",
"required": true,
"defaultValue": null,
"options": []
},
{
"name": "varValue",
"type": "Any",
"label": "变量值",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置任务变量 (SetTaskVariableBp)\n\n### 描述\n本块用于设置任务变量。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| varName | 必填 | String | 变量名 |\n| varValue | 必填 | Any | 变量值 |\n\n### 输出参数\n无\n"
},
{
"type": "All",
"name": "SkipToComponent",
"label": "跳到某个块",
"description": "",
"inputParams": [
{
"name": "skipComponentId",
"type": "String",
"label": "跳到块的标识",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 跳到某个块 (SkipToComponent)\n\n### 描述\n本块用于跳到某个块。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| skipComponentId | 必填 | String | 跳到块的标识 |\n\n### 输出参数\n无\n"
},
{
"type": "Normal",
"name": "TaskStateBp",
"label": "设置任务状态",
"description": "",
"inputParams": [
{
"name": "stateMsg",
"type": "String",
"label": "状态描述",
"description": "",
"required": true,
"defaultValue": null,
"options": []
}
],
"extraInputParamsFunc": "",
"outputParams": {},
"contextVariables": {},
"children": {},
"hidden": false,
"scriptFunction": null,
"operatingInstructions": "## 设置任务状态 (TaskStateBp)\n\n### 描述\n本块用于设置任务状态。\n\n### 输入参数\n\n| 参数名 | 是否必填 | 类型 | 描述 |\n\n|---------|---------|------|------|\n| stateMsg | 必填 | String | 状态描述 |\n\n### 输出参数\n无\n"
}
]
}

482
config/components/test.json Normal file
View File

@ -0,0 +1,482 @@
{
"inputParams": [
{
"name": "input",
"type": "String",
"label": "input",
"remark": "",
"defaultValue": "",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "CSelectAgvBp",
"children": {
"default": [
{
"id": 2,
"name": "b2",
"blockType": "CAgvOperationBp",
"children": {},
"inputParams": {
"targetSiteLabel": {
"type": "Simple",
"value": "ko1",
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"inputParams": {
"keyRoute": {
"type": "Simple",
"value": "apt",
"required": true
},
"group": {
"type": "Simple",
"value": "bbo"
},
"vehicle": {
"type": "Simple",
"value": "boot1"
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": true,
"refTaskDefId": "",
"expanded": true
}
}
===============================
{
"inputParams": [],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 0,
"name": "bb7",
"blockType": "PrintBp",
"inputParams": {
"message": {
"type": "Simple",
"value": "123",
"required": false
}
},
"children": {},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
}
================================
{
"taskId": "ac1b5b23-f628-45a4-8053-847405406db1",
"source_type": 1,
"source_system": "SYSTEM",
"source_device": "AB2223Ndsa1",
"params": [
{
"name": "a",
"type": "整数",
"label": "a",
"defaultValue": "1"
},
{
"name": "b",
"type": "整数",
"label": "b",
"defaultValue": "1"
}
]
}
===================================
{
"inputParams": [
{
"name": "1222",
"type": "String",
"label": "231",
"remark": "12",
"defaultValue": "333",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "WhileBp",
"children": {},
"inputParams": {
"loopCondition": {
"type": "Simple",
"value": true,
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}
=====================
{
"inputParams": [
{
"name": "1222",
"type": "String",
"label": "231",
"remark": "12",
"defaultValue": "333",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "CSelectAgvBp",
"children": {},
"inputParams": {
"priority": {
"type": "Simple",
"value": "10"
},
"vehicle": {
"type": "Simple",
"value": "amr1"
},
"group": {
"type": "Simple",
"value": "group_amr"
},
"keyRoute": {
"type": "Simple",
"value": "apt1",
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}
=========================
{
"inputParams": [
{
"name": "1222",
"type": "String",
"label": "231",
"remark": "12",
"defaultValue": "333",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "CSelectAgvBp",
"children": {},
"inputParams": {
"priority": {
"type": "Simple",
"value": "10"
},
"vehicle": {
"type": "Simple",
"value": "amr1"
},
"group": {
"type": "Simple",
"value": "group_amr"
},
"keyRoute": {
"type": "Simple",
"value": "apt1",
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}
=================================
{
"inputParams": [
{
"name": "测试",
"type": "Boolean",
"label": "132",
"remark": "",
"defaultValue": "213",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 2,
"name": "b2",
"blockType": "CSelectAgvBp",
"children": {
"default": [
{
"id": 3,
"name": "b3",
"blockType": "CAgvOperationBp",
"children": {},
"inputParams": {
"targetSiteLabel": {
"type": "Simple",
"value": "wqlo",
"required": true
},
"scriptName": {
"type": "Simple",
"value": "JackUnload"
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"inputParams": {
"keyRoute": {
"type": "Simple",
"value": "TK01",
"required": true
},
"vehicle": {
"type": "Simple",
"value": ""
},
"priority": {
"type": "Simple",
"value": "1"
},
"tag": {
"type": "Simple",
"value": ""
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}
================================
{
"inputParams": [
{
"name": "测试",
"type": "Boolean",
"label": "132",
"remark": "",
"defaultValue": "213",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "CSelectAgvBp",
"children": {
"default": [
{
"id": 2,
"name": "b2",
"blockType": "CAgvOperationBp",
"children": {},
"inputParams": {
"targetSiteLabel": {
"type": "Simple",
"value": "PT02",
"required": true
},
"scriptName": {
"type": "Simple",
"value": "JackUnload"
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"inputParams": {
"keyRoute": {
"type": "Simple",
"value": "TK01",
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}
=====================
{
"inputParams": [
{
"name": "测试",
"type": "Boolean",
"label": "132",
"remark": "",
"defaultValue": "213",
"required": false
}
],
"outputParams": [],
"rootBlock": {
"id": -1,
"name": "-1",
"blockType": "RootBp",
"inputParams": {},
"children": {
"default": [
{
"id": 1,
"name": "b1",
"blockType": "IterateListBp",
"children": {
"default": [
{
"id": 2,
"name": "b2",
"blockType": "PrintBp",
"children": {},
"inputParams": {
"message": {
"type": "Expression",
"value": "blocks.b1.item"
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"inputParams": {
"list": {
"type": "Simple",
"value": "[1,2,3,4,5]",
"required": true
}
},
"refTaskDefId": "",
"selected": false,
"expanded": true
}
]
},
"selected": false,
"refTaskDefId": "",
"expanded": true
}
}

83
config/database_config.py Normal file
View File

@ -0,0 +1,83 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据库配置模块
仅包含数据库连接的配置信息
"""
from sqlalchemy.ext.declarative import declarative_base
from config.settings import settings
# 创建Model基类
Base = declarative_base()
# 数据库连接配置
class DBConfig:
"""数据库配置类"""
# 数据库连接URL
DATABASE_URL = settings.DATABASE_URL
# 数据库连接参数
DATABASE_ARGS = settings.DATABASE_ARGS
# 异步数据库连接参数
ASYNC_DATABASE_ARGS = {
"pool_size": settings.DB_POOL_SIZE,
"max_overflow": settings.DB_MAX_OVERFLOW,
"pool_recycle": settings.DB_POOL_RECYCLE,
"echo": settings.DB_ECHO,
"pool_pre_ping": True
}
@classmethod
def create_db_url(cls, include_db_name=True):
"""
创建数据库连接URL
Args:
include_db_name: 是否包含数据库名称
Returns:
str: 数据库连接URL
"""
if include_db_name:
return settings.DATABASE_URL
else:
# 根据数据库类型创建不同的连接URL
if settings.DB_DIALECT == 'sqlite':
return "sqlite:///:memory:"
return f"{settings.DB_DIALECT}+{settings.DB_DRIVER}://{settings.DB_USER}:{settings.DB_PASSWORD}@{settings.DB_HOST}:{settings.DB_PORT}/mysql"
# 缓存配置
class CacheConfig:
"""缓存配置类定义Redis缓存配置"""
# Redis连接配置
REDIS_URL = settings.REDIS_URL
REDIS_HOST = settings.REDIS_HOST
REDIS_PORT = settings.REDIS_PORT
REDIS_DB = settings.REDIS_DB
REDIS_PASSWORD = settings.REDIS_PASSWORD
REDIS_PREFIX = settings.REDIS_PREFIX
REDIS_SOCKET_TIMEOUT = settings.REDIS_SOCKET_TIMEOUT
REDIS_SOCKET_CONNECT_TIMEOUT = settings.REDIS_SOCKET_CONNECT_TIMEOUT
REDIS_DECODE_RESPONSES = settings.REDIS_DECODE_RESPONSES
@classmethod
def get_redis_connection_args(cls):
"""
获取Redis连接参数
Returns:
dict: Redis连接参数字典
"""
return {
"host": cls.REDIS_HOST,
"port": cls.REDIS_PORT,
"db": cls.REDIS_DB,
"password": cls.REDIS_PASSWORD,
"socket_timeout": cls.REDIS_SOCKET_TIMEOUT,
"socket_connect_timeout": cls.REDIS_SOCKET_CONNECT_TIMEOUT,
"decode_responses": cls.REDIS_DECODE_RESPONSES
}

97
config/error_messages.py Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
错误消息配置模块
包含各种错误消息的中文映射表
"""
from typing import Dict, Any
# 验证错误消息中文映射表
VALIDATION_ERROR_MESSAGES: Dict[str, str] = {
# 字符串类型错误
"string_too_short": "字符串长度不足,至少需要{min_length}个字符",
"string_too_long": "字符串长度超出限制,最多允许{max_length}个字符",
"string_pattern_mismatch": "字符串格式不符合要求",
# 数值类型错误
"value_error.number.not_ge": "数值必须大于或等于{ge}",
"value_error.number.not_le": "数值必须小于或等于{le}",
"value_error.number.not_gt": "数值必须大于{gt}",
"value_error.number.not_lt": "数值必须小于{lt}",
# 缺失与空值错误
"missing": "缺少必填字段",
"null": "不能为空值",
"value_error.missing": "缺少必填字段",
# 类型错误
"type_error": "类型错误,期望{expected_type}",
"type_error.integer": "必须是整数类型",
"type_error.float": "必须是浮点数类型",
"type_error.string": "必须是字符串类型",
"type_error.bool": "必须是布尔类型",
"type_error.list": "必须是列表类型",
"type_error.dict": "必须是字典类型",
"type_error.date": "必须是日期类型",
"type_error.datetime": "必须是日期时间类型",
"type_error.time": "必须是时间类型",
# 值错误
"value_error": "值错误",
"value_error.any_str.max_length": "字符串长度不能超过{limit_value}",
"value_error.decimal.max_digits": "数字总位数不能超过{max_digits}",
"value_error.decimal.max_places": "小数位数不能超过{decimal_places}",
"value_error.decimal.not_finite": "数值必须是有限的",
"value_error.email": "邮箱格式不正确",
"value_error.url": "URL格式不正确",
"value_error.uuid": "UUID格式不正确",
"value_error.json": "JSON格式不正确",
# 列表相关错误
"list_type": "必须是列表类型",
"list_min_items": "列表至少需要{min_items}个元素",
"list_max_items": "列表最多允许{max_items}个元素",
"list_unique_items": "列表元素必须唯一",
# 日期时间相关错误
"date_from_datetime_inexact": "日期转换不准确",
"date_from_datetime_not_allowed": "不允许从日期时间转换为日期",
"time_delta_in_wrong_format": "时间增量格式错误",
# 枚举相关错误
"enum": "值必须是预设的枚举值之一",
# 布尔相关错误
"boolean_not_none": "布尔值不能为空",
# 对象相关错误
"object_extra": "不允许额外字段",
"object_invalid": "对象无效"
}
# 其他业务错误消息,可根据需要扩展
BUSINESS_ERROR_MESSAGES: Dict[str, str] = {
"record_not_found": "记录不存在",
"permission_denied": "权限不足",
"already_exists": "记录已存在",
"operation_failed": "操作失败"
}
# HTTP错误状态码对应的消息
HTTP_ERROR_MESSAGES: Dict[int, str] = {
400: "请求参数有误",
401: "未授权访问",
403: "禁止访问",
404: "资源不存在",
405: "请求方法不允许",
408: "请求超时",
409: "资源冲突",
422: "请求参数验证失败",
429: "请求过于频繁",
500: "服务器内部错误",
502: "网关错误",
503: "服务暂时不可用",
504: "网关超时"
}

342
config/settings.py Normal file
View File

@ -0,0 +1,342 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
系统配置模块
提供集中的配置管理支持开发环境测试环境和生产环境
"""
import os
from typing import Dict, Any, Optional, List
from pydantic import Field
from pydantic_settings import BaseSettings
# 定义数据目录路径
DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "data")
# 确保数据目录存在
os.makedirs(DATA_DIR, exist_ok=True)
# 服务器配置
default_server_config = {
'host': '0.0.0.0',
'port': 8000,
'workers': 1,
'reload': True,
'log_level': 'info'
}
production_server_config = {
'host': '0.0.0.0',
'port': 8000,
'workers': 4,
'reload': False,
'log_level': 'warning'
}
test_server_config = {
'host': '127.0.0.1',
'port': 8001,
'workers': 1,
'reload': False,
'log_level': 'debug'
}
# 数据库配置
default_db_config = {
'dialect': 'mysql',
'driver': 'pymysql',
'username': 'root',
'password': 'root',
'host': 'localhost',
'port': 3306,
'database': 'vwed_task',
'charset': 'utf8mb4'
}
# Redis配置
default_redis_config = {
'host': 'localhost',
'port': 6379,
'db': 0,
'password': None,
'prefix': 'vwed:',
'socket_timeout': 5,
'socket_connect_timeout': 5,
'decode_responses': True
}
test_redis_config = {
'host': 'localhost',
'port': 6379,
'db': 1,
'password': None,
'prefix': 'vwed_test:',
'decode_responses': True
}
# 库位服务API端点映射
storage_api_endpoints = {
"batch_setting_site": "/site/batch-setting",
"get_idle_crowded_site": "/site/idle-crowded",
"get_idle_site": "/site/idle",
"get_locked_sites_by_task_record_id": "/site/locked-by-task",
"get_site_attr": "/site/attr",
"query_idle_site": "/site/query",
"set_site_attr": "/site/attr",
"set_site_content": "/site/content",
"set_site_empty": "/site/empty",
"set_site_filled": "/site/filled",
"set_site_locked": "/site/lock",
"set_site_tags": "/site/tags",
"set_site_unlocked": "/site/unlock"
}
# 库位服务API HTTP方法映射
storage_api_methods = {
"batch_setting_site": "POST",
"get_idle_crowded_site": "GET",
"get_idle_site": "GET",
"get_locked_sites_by_task_record_id": "GET",
"get_site_attr": "GET",
"query_idle_site": "GET",
"set_site_attr": "PUT",
"set_site_content": "PUT",
"set_site_empty": "PUT",
"set_site_filled": "PUT",
"set_site_locked": "PUT",
"set_site_tags": "PUT",
"set_site_unlocked": "PUT"
}
# 机器人调度服务API端点映射
robot_api_endpoints = {
"vehicle_station": "/robot/station",
"get_battery_level": "/robot/battery",
"get_pgv_code": "/robot/pgv-code"
}
# 机器人调度服务API HTTP方法映射
robot_api_methods = {
"vehicle_station": "GET",
"get_battery_level": "GET",
"get_pgv_code": "GET"
}
# 外部服务API配置
external_api_config = {
"storage": {
"base_url": "http://localhost:8080/api/storage",
"endpoints": storage_api_endpoints,
"methods": storage_api_methods
},
"robot": {
"base_url": "http://localhost:8080/api/robot",
"endpoints": robot_api_endpoints,
"methods": robot_api_methods
}
}
def get_config_for_env(env: str, config_type: str) -> Dict[str, Any]:
"""根据环境获取配置"""
if config_type == 'server':
if env == 'production':
return production_server_config
elif env == 'test':
return test_server_config
return default_server_config
elif config_type == 'db':
# 目前只有默认数据库配置
return default_db_config
elif config_type == 'redis':
if env == 'test':
return test_redis_config
return default_redis_config
return {}
class BaseConfig(BaseSettings):
"""基础配置类"""
# 应用信息
APP_NAME: str = "VWED任务系统"
APP_VERSION: str = "1.0.0"
APP_DESCRIPTION: str = "自动化移动机器人(AMR)任务管理系统"
# 系统设置
DEBUG: bool = False
API_PREFIX: str = "/api"
# 获取当前环境
_env: str = os.getenv("APP_ENV", "development").lower()
# 服务配置
_server_config = get_config_for_env(_env, 'server')
SERVER_HOST: str = Field(default=_server_config['host'], env="HOST")
SERVER_PORT: int = Field(default=_server_config['port'], env="PORT")
SERVER_WORKERS: int = Field(default=_server_config['workers'], env="WORKERS")
SERVER_RELOAD: bool = Field(default=_server_config['reload'], env="RELOAD")
SERVER_LOG_LEVEL: str = Field(default=_server_config['log_level'], env="LOG_LEVEL")
# Modbus设备配置
MODBUS_MOCK_MODE: bool = Field(default=True, env="MODBUS_MOCK_MODE") # 测试模式True表示启用模拟数据
MODBUS_TIMEOUT: float = Field(default=2.0, env="MODBUS_TIMEOUT") # Modbus通信超时时间
MODBUS_RETRY_INTERVAL: float = Field(default=1.0, env="MODBUS_RETRY_INTERVAL") # 重试间隔时间(秒)
MODBUS_POLL_INTERVAL: float = Field(default=0.5, env="MODBUS_POLL_INTERVAL") # 轮询间隔时间(秒)
# 数据库连接配置
_db_config = get_config_for_env(_env, 'db')
DB_DIALECT: str = Field(default=_db_config['dialect'], env="DB_DIALECT")
DB_DRIVER: str = Field(default=_db_config['driver'], env="DB_DRIVER")
DB_USER: str = Field(default=_db_config['username'], env="DB_USER")
DB_PASSWORD: str = Field(default=_db_config['password'], env="DB_PASSWORD")
DB_HOST: str = Field(default=_db_config['host'], env="DB_HOST")
DB_PORT: str = Field(default=str(_db_config['port']), env="DB_PORT")
DB_NAME: str = Field(default=_db_config['database'], env="DB_NAME")
DB_CHARSET: str = Field(default=_db_config['charset'], env="DB_CHARSET")
DB_ECHO: bool = False # 是否输出SQL语句
DB_POOL_SIZE: int = 10
DB_MAX_OVERFLOW: int = 20
DB_POOL_RECYCLE: int = 3600 # 连接池回收时间,防止连接过期
# Redis配置
_redis_config = get_config_for_env(_env, 'redis')
REDIS_HOST: str = Field(default=_redis_config['host'], env="REDIS_HOST")
REDIS_PORT: int = Field(default=_redis_config['port'], env="REDIS_PORT")
REDIS_DB: int = Field(default=_redis_config['db'], env="REDIS_DB")
REDIS_PASSWORD: Optional[str] = Field(default=_redis_config['password'], env="REDIS_PASSWORD")
REDIS_PREFIX: str = Field(default=_redis_config['prefix'], env="REDIS_PREFIX")
REDIS_SOCKET_TIMEOUT: int = Field(default=_redis_config['socket_timeout'], env="REDIS_SOCKET_TIMEOUT")
REDIS_SOCKET_CONNECT_TIMEOUT: int = Field(default=_redis_config['socket_connect_timeout'], env="REDIS_SOCKET_CONNECT_TIMEOUT")
REDIS_DECODE_RESPONSES: bool = Field(default=_redis_config['decode_responses'], env="REDIS_DECODE_RESPONSES")
# 安全设置
SECRET_KEY: str = Field(default="YOUR_SECRET_KEY_HERE", env="SECRET_KEY")
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 # 1天
# 外部服务API通用配置
API_TIMEOUT: int = Field(default=30, env="API_TIMEOUT") # 请求超时时间(秒)
API_TOKEN: Optional[str] = Field(default=None, env="API_TOKEN") # API通用认证令牌
API_MOCK_MODE: bool = Field(default=False, env="API_MOCK_MODE") # 是否启用API模拟模式
# 库位服务API配置
STORAGE_API_BASE_URL: str = Field(default=external_api_config["storage"]["base_url"], env="STORAGE_API_BASE_URL")
STORAGE_API_ENDPOINTS: Dict[str, str] = external_api_config["storage"]["endpoints"]
STORAGE_API_METHODS: Dict[str, str] = external_api_config["storage"]["methods"]
STORAGE_API_TIMEOUT: int = Field(default=30, env="STORAGE_API_TIMEOUT")
STORAGE_API_TOKEN: Optional[str] = Field(default=None, env="STORAGE_API_TOKEN")
STORAGE_API_MOCK_MODE: bool = Field(default=False, env="STORAGE_API_MOCK_MODE")
# 机器人调度服务API配置
ROBOT_API_BASE_URL: str = Field(default=external_api_config["robot"]["base_url"], env="ROBOT_API_BASE_URL")
ROBOT_API_ENDPOINTS: Dict[str, str] = external_api_config["robot"]["endpoints"]
ROBOT_API_METHODS: Dict[str, str] = external_api_config["robot"]["methods"]
ROBOT_API_TIMEOUT: int = Field(default=30, env="ROBOT_API_TIMEOUT")
ROBOT_API_TOKEN: Optional[str] = Field(default=None, env="ROBOT_API_TOKEN")
ROBOT_API_MOCK_MODE: bool = Field(default=False, env="ROBOT_API_MOCK_MODE")
# CORS设置
CORS_ORIGINS: List[str] = ["*"]
CORS_ALLOW_CREDENTIALS: bool = True
CORS_ALLOW_METHODS: List[str] = ["*"]
CORS_ALLOW_HEADERS: List[str] = ["*"]
# 日志设置
LOG_LEVEL: str = "INFO"
LOG_FILE: str = "logs/app.log"
LOG_FORMAT: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# 任务调度设置
TASK_SCHEDULER_WORKER_COUNT: int = 5 # 任务调度器工作线程数量
# 脚本执行配置
SCRIPT_TIMEOUT: int = os.getenv("SCRIPT_TIMEOUT", 60) # 脚本执行超时时间(秒)
SCRIPT_MAX_WORKERS: int = os.getenv("SCRIPT_MAX_WORKERS", 5) # 脚本执行最大线程数
# 任务导出加密配置
TASK_EXPORT_ENCRYPTION_KEY: str = Field(default="vwed_task_export_secret_key", env="TASK_EXPORT_ENCRYPTION_KEY") # 导出加密密钥
TASK_EXPORT_ENCRYPTION_ALGORITHM: str = Field(default="AES", env="TASK_EXPORT_ENCRYPTION_ALGORITHM") # 加密算法
TASK_EXPORT_IV: str = Field(default="vwed1234task5678", env="TASK_EXPORT_IV") # 初始化向量
# 增强版任务调度器配置
TASK_SCHEDULER_MIN_WORKER_COUNT: int = 5 # 最小工作线程数
TASK_SCHEDULER_MAX_WORKER_COUNT: int = 20 # 最大工作线程数
TASK_SCHEDULER_QUEUE_COUNT: int = 3 # 队列数量
TASK_SCHEDULER_QUEUE_THRESHOLD_PERCENTILES: List[float] = [0.1, 0.3, 1.0] # 队列阈值百分比配置
TASK_SCHEDULER_WORKER_RATIOS: List[float] = [0.6, 0.3, 0.1] # 工作线程分配比例
TASK_SCHEDULER_TASK_TIMEOUT: int = 3600 # 任务超时时间(秒)
TASK_SCHEDULER_MAX_RETRY_COUNT: int = 3 # 最大重试次数
TASK_SCHEDULER_RETRY_DELAY: int = 60 # 重试基础延迟(秒)
TASK_SCHEDULER_BACKUP_INTERVAL: int = 300 # 备份间隔(秒)
TASK_SCHEDULER_BACKUP_DIR: str = os.path.join(DATA_DIR, "task_backups") # 备份目录
TASK_SCHEDULER_MAX_BACKUPS: int = 5 # 最大备份数
TASK_SCHEDULER_ZOMBIE_TASK_CHECK_INTERVAL: int = 60 # 僵尸任务检查间隔(秒)
TASK_SCHEDULER_CPU_THRESHOLD: float = 80.0 # CPU使用率阈值百分比
TASK_SCHEDULER_MEMORY_THRESHOLD: float = 80.0 # 内存使用率阈值(百分比)
TASK_SCHEDULER_AUTO_SCALE_INTERVAL: int = 60 # 自动扩缩容间隔(秒)
TASK_SCHEDULER_WORKER_HEARTBEAT_INTERVAL: int = 30 # 心跳间隔(秒)
@property
def DATABASE_URL(self) -> str:
"""构建数据库连接URL"""
if self.DB_DIALECT == 'sqlite':
return f"sqlite:///{self.DB_NAME}"
return f"{self.DB_DIALECT}+{self.DB_DRIVER}://{self.DB_USER}:{self.DB_PASSWORD}@{self.DB_HOST}:{self.DB_PORT}/{self.DB_NAME}?charset={self.DB_CHARSET}"
@property
def DATABASE_ARGS(self) -> Dict[str, Any]:
"""构建数据库连接参数"""
args = {
"pool_size": self.DB_POOL_SIZE,
"max_overflow": self.DB_MAX_OVERFLOW,
"pool_recycle": self.DB_POOL_RECYCLE,
"echo": self.DB_ECHO
}
return args
@property
def REDIS_URL(self) -> str:
"""构建Redis连接URL"""
if self.REDIS_PASSWORD:
return f"redis://:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
return f"redis://{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
# 更新为Pydantic v2的配置方式
model_config = {
"env_file": ".env",
"env_file_encoding": "utf-8",
"case_sensitive": True
}
class DevelopmentConfig(BaseConfig):
"""开发环境配置"""
DEBUG: bool = True
DB_ECHO: bool = True # 开发环境输出SQL语句
LOG_LEVEL: str = "DEBUG"
SERVER_RELOAD: bool = True # 开发环境启用热重载
STORAGE_API_MOCK_MODE: bool = True # 开发环境默认使用API模拟模式
ROBOT_API_MOCK_MODE: bool = True # 开发环境默认使用机器人API模拟模式
# 根据环境变量选择配置
def get_config():
"""根据环境变量获取配置"""
return DevelopmentConfig()
# 导出配置
settings = get_config()
# 添加LogConfig类以供logger.py使用
class LogConfig:
"""日志配置类"""
@staticmethod
def as_dict():
"""返回日志配置字典"""
return {
"level": settings.LOG_LEVEL,
"file": settings.LOG_FILE,
"format": settings.LOG_FORMAT
}

57
config/tf_api_config.py Normal file
View File

@ -0,0 +1,57 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
系统内部服务API配置
用于配置与系统内部服务通信的相关参数
"""
import os
from typing import Dict, Any, Optional, List
# 天系统内部服务API端点配置
tf_api_endpoints = {
"create_task": "/task",
"choose_amr": "/taskBlock",
"add_action": "/taskBlockAction",
"closure_task": "/taskBlock/{}/closure",
"get_task_block": "/taskBlock/{id}",
"get_task_block_action": "/taskBlockAction/{id}",
"set_task_in_progress": "/task/vwedtask/{id}/inprogress",
"set_task_completed": "/task/vwedtask/{id}/completed",
"set_task_terminated": "/task/vwedtask/{id}/terminated",
"set_task_failed": "/task/vwedtask/{id}/failed"
}
# 系统内部服务API HTTP方法配置
tf_api_methods = {
"create_task": "POST",
"choose_amr": "POST",
"add_action": "POST",
"closure_task": "PUT",
"get_task_block": "GET",
"get_task_block_action": "GET",
"set_task_in_progress": "PUT",
"set_task_completed": "PUT",
"set_task_terminated": "PUT",
"set_task_failed": "PUT"
}
# 从环境变量读取配置,或使用默认值
TF_API_BASE_URL = os.getenv("TF_API_BASE_URL", "http://192.168.189.101:8080/jeecg-boot")
TF_API_TIMEOUT = int(os.getenv("TF_API_TIMEOUT", "60"))
TF_API_RETRY_TIMES = int(os.getenv("TF_API_RETRY_TIMES", "3"))
TF_API_MOCK_MODE = False
TF_API_TOKEN_HEADER = os.getenv("TF_API_TOKEN_HEADER", "X-Access-Token") # token请求头名称
def get_tf_api_config() -> Dict[str, Any]:
"""获取天风系统API配置"""
return {
"base_url": TF_API_BASE_URL,
"timeout": TF_API_TIMEOUT,
"retry_times": TF_API_RETRY_TIMES,
"mock_mode": TF_API_MOCK_MODE,
"endpoints": tf_api_endpoints,
"methods": tf_api_methods,
"token_header": TF_API_TOKEN_HEADER
}

0
core/__init__.py Normal file
View File

View File

View File

@ -0,0 +1,3 @@
"""
向量化核心功能
"""

View File

@ -0,0 +1,3 @@
"""
向量存储核心功能
"""

10
data/__init__.py Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
VWED任务系统数据模块
"""
# 确保子模块正确加载
import data.models

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

285
data/cache.py Normal file
View File

@ -0,0 +1,285 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
缓存管理模块
提供Redis缓存连接和操作功能
"""
import logging
import json
from typing import Any, Optional, Union, Dict, List
import redis
from config.database_config import CacheConfig
from utils.logger import get_logger
# 获取日志记录器
logger = get_logger("data.cache")
class RedisClient:
"""Redis客户端封装常用的Redis操作"""
_instance = None
_redis_client = None
def __new__(cls, *args, **kwargs):
"""单例模式确保只有一个Redis连接"""
if cls._instance is None:
cls._instance = super(RedisClient, cls).__new__(cls)
return cls._instance
def __init__(self):
"""初始化Redis连接"""
if self._redis_client is None:
try:
self._redis_client = redis.Redis(
**CacheConfig.get_redis_connection_args()
)
logger.info(f"Redis连接已建立{CacheConfig.REDIS_HOST}:{CacheConfig.REDIS_PORT}/{CacheConfig.REDIS_DB}")
except Exception as e:
logger.error(f"Redis连接失败{str(e)}")
self._redis_client = None
def get_client(self) -> redis.Redis:
"""获取Redis客户端"""
return self._redis_client
def add_prefix(self, key: str) -> str:
"""添加键前缀"""
return f"{CacheConfig.REDIS_PREFIX}{key}"
def set(self, key: str, value: Any, expire: Optional[int] = None) -> bool:
"""
设置缓存
Args:
key: 缓存键
value: 缓存值如果不是字符串会尝试JSON序列化
expire: 过期时间()
Returns:
bool: 操作是否成功
"""
try:
if self._redis_client is None:
return False
# 添加前缀
prefixed_key = self.add_prefix(key)
# 处理非字符串值
if not isinstance(value, (str, bytes, int, float)):
value = json.dumps(value, ensure_ascii=False)
# 设置缓存
self._redis_client.set(prefixed_key, value)
# 设置过期时间
if expire is not None:
self._redis_client.expire(prefixed_key, expire)
return True
except Exception as e:
logger.error(f"设置缓存失败:{str(e)}")
return False
def get(self, key: str, default: Any = None) -> Any:
"""
获取缓存
Args:
key: 缓存键
default: 默认值缓存不存在时返回
Returns:
Any: 缓存值或默认值
"""
try:
if self._redis_client is None:
return default
# 添加前缀
prefixed_key = self.add_prefix(key)
# 获取缓存
value = self._redis_client.get(prefixed_key)
if value is None:
return default
# 尝试JSON反序列化
try:
return json.loads(value)
except (TypeError, json.JSONDecodeError):
return value
except Exception as e:
logger.error(f"获取缓存失败:{str(e)}")
return default
def delete(self, key: str) -> bool:
"""
删除缓存
Args:
key: 缓存键
Returns:
bool: 操作是否成功
"""
try:
if self._redis_client is None:
return False
# 添加前缀
prefixed_key = self.add_prefix(key)
# 删除缓存
return bool(self._redis_client.delete(prefixed_key))
except Exception as e:
logger.error(f"删除缓存失败:{str(e)}")
return False
def exists(self, key: str) -> bool:
"""
检查缓存是否存在
Args:
key: 缓存键
Returns:
bool: 缓存是否存在
"""
try:
if self._redis_client is None:
return False
# 添加前缀
prefixed_key = self.add_prefix(key)
# 检查缓存
return bool(self._redis_client.exists(prefixed_key))
except Exception as e:
logger.error(f"检查缓存失败:{str(e)}")
return False
def expire(self, key: str, seconds: int) -> bool:
"""
设置缓存过期时间
Args:
key: 缓存键
seconds: 过期时间()
Returns:
bool: 操作是否成功
"""
try:
if self._redis_client is None:
return False
# 添加前缀
prefixed_key = self.add_prefix(key)
# 设置过期时间
return bool(self._redis_client.expire(prefixed_key, seconds))
except Exception as e:
logger.error(f"设置缓存过期时间失败:{str(e)}")
return False
def ttl(self, key: str) -> int:
"""
获取缓存剩余过期时间
Args:
key: 缓存键
Returns:
int: 剩余过期时间()-1表示永不过期-2表示键不存在
"""
try:
if self._redis_client is None:
return -2
# 添加前缀
prefixed_key = self.add_prefix(key)
# 获取过期时间
return self._redis_client.ttl(prefixed_key)
except Exception as e:
logger.error(f"获取缓存过期时间失败:{str(e)}")
return -2
def hset(self, key: str, field: str, value: Any) -> bool:
"""
设置哈希表字段
Args:
key: 缓存键
field: 字段名
value: 字段值
Returns:
bool: 操作是否成功
"""
try:
if self._redis_client is None:
return False
# 添加前缀
prefixed_key = self.add_prefix(key)
# 处理非字符串值
if not isinstance(value, (str, bytes, int, float)):
value = json.dumps(value, ensure_ascii=False)
# 设置哈希表字段
self._redis_client.hset(prefixed_key, field, value)
return True
except Exception as e:
logger.error(f"设置哈希表字段失败:{str(e)}")
return False
def hget(self, key: str, field: str, default: Any = None) -> Any:
"""
获取哈希表字段
Args:
key: 缓存键
field: 字段名
default: 默认值字段不存在时返回
Returns:
Any: 字段值或默认值
"""
try:
if self._redis_client is None:
return default
# 添加前缀
prefixed_key = self.add_prefix(key)
# 获取哈希表字段
value = self._redis_client.hget(prefixed_key, field)
if value is None:
return default
# 尝试JSON反序列化
try:
return json.loads(value)
except (TypeError, json.JSONDecodeError):
return value
except Exception as e:
logger.error(f"获取哈希表字段失败:{str(e)}")
return default
# 导出Redis客户端单例
redis_client = RedisClient()
def get_cache():
"""获取Redis客户端"""
return redis_client

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,10 @@
from enum import IntEnum
class TaskBlockRecordStatus(IntEnum):
"""任务块执行记录状态枚举"""
SUCCESS = 1000 # 执行成功
RUNNING = 1001 # 执行中
NOT_EXECUTED = 1006 # 未执行
FAILED = 2000 # 执行失败
CANCELED = 2002 # 取消

View File

@ -0,0 +1,25 @@
from enum import IntEnum
class EnableStatus(IntEnum):
"""任务启用状态枚举"""
DISABLED = 0 # 未启用
ENABLED = 1 # 已启用
class PeriodicTaskStatus(IntEnum):
"""周期任务状态枚举"""
NON_PERIODIC = 0 # 非周期任务
PERIODIC = 1 # 周期任务
class TaskStatusEnum(IntEnum):
"""任务状态枚举"""
PENDING = 0 # 待执行
RUNNING = 1 # 运行中
class TaskTypeEnum(IntEnum):
"""任务类型枚举"""
NORMAL = 1 # 普通任务
PERIODIC = 2 # 周期任务

View File

@ -0,0 +1,16 @@
from enum import StrEnum
class TaskInputParamType(StrEnum):
"""任务输入参数类型枚举"""
SIMPLE = "Simple" # 简单值
EXPRESSION = "Expression" # 表达式
JSON = "JSON" # JSON
class TaskInputParamVariables(StrEnum):
"""任务输入参数变量枚举"""
VWED_ = "vwed_" #
BLOCKS = "blocks" # 块
TASK_INPUTS = "taskInputs" # 任务输入
STRING_UTILS = "StringUtils" # 字符串工具类

View File

@ -0,0 +1,17 @@
from enum import IntEnum
class TaskStatus(IntEnum):
"""任务状态枚举"""
COMPLETED = 1000 # 完成
RUNNING = 1001 # 运行中
QUEUED = 1002 # 队列中
FAILED = 2000 # 失败
CANCELED = 2001 # 取消
PAUSED = 2002 # 暂停
class SourceType(IntEnum):
"""来源类型枚举"""
SYSTEM_SCHEDULING = 1 # 系统调度
CALL_MACHINE = 2 # 呼叫机
THIRD_SYSTEM = 3 # 第三方系统
HAND_DEVICE = 4 # 手持设备

25
data/models/__init__.py Normal file
View File

@ -0,0 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
数据模型包
导入所有模型以便应用程序使用
"""
from data.models.base import BaseModel
from data.models.taskdef import VWEDTaskDef
from data.models.taskrecord import VWEDTaskRecord
from data.models.tasklog import VWEDTaskLog
from data.models.blockrecord import VWEDBlockRecord
from data.models.tasktemplate import VWEDTaskTemplate
from data.models.datacache import VWEDDataCache
from data.models.datacachesplit import VWEDDataCacheSplit
from data.models.script import VWEDScript, VWEDScriptVersion, VWEDScriptLog
from data.models.modbusconfig import VWEDModbusConfig
# 导出所有模型供应用程序使用
__all__ = [
'BaseModel', 'VWEDTaskDef', 'VWEDTaskRecord', 'VWEDTaskLog',
'VWEDBlockRecord', 'VWEDTaskTemplate', 'VWEDDataCache', 'VWEDDataCacheSplit',
'VWEDScript', 'VWEDScriptVersion', 'VWEDScriptLog', 'VWEDModbusConfig'
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More