VWED_server/routes/external_task_api.py

383 lines
14 KiB
Python
Raw Normal View History

2025-07-30 15:11:59 +08:00
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
外部任务接口API模块
提供外部系统调用的任务创建接口
"""
import json
from typing import Dict, Any
from fastapi import APIRouter, Body, Request
from routes.model.external_task_model import ExternalTaskRequest, ExternalTaskResponse, TaskTypeEnum, GenAgvSchedulingTaskRequest
from routes.model.task_edit_model import TaskEditRunRequest, TaskInputParamNew, InputParamType
from services.task_edit_service import TaskEditService
from routes.common_api import format_response, error_response
from utils.logger import get_logger
from data.enum.task_record_enum import SourceType
from config.tf_api_config import TF_API_TOKEN
# tf_api_config = get_tf_api_config()
# 创建路由
router = APIRouter(
prefix="",
tags=["外部任务接口"]
)
# 设置日志
logger = get_logger("app.external_task_api")
# 任务类型到模板ID的映射
TASK_TYPE_TEMPLATE_MAPPING = {
TaskTypeEnum.GG2MP: "template_gg2mp_id", # 高柜到MP模板ID
TaskTypeEnum.GGFK2MP: "template_ggfk2mp_id", # 高柜发库到MP模板ID
TaskTypeEnum.GT2MP: "571985c1-cfa5-4186-8acd-6e3868a5e08c", # 高台到MP模板ID
TaskTypeEnum.GTFK2MP: "template_gtfk2mp_id", # 高台发库到MP模板ID
TaskTypeEnum.ZG2MP: "template_zg2mp_id", # 中柜到MP模板ID
TaskTypeEnum.QZ2MP: "template_qz2mp_id", # 清洗到MP模板ID
TaskTypeEnum.LG2MP: "template_lg2mp_id", # 料柜到MP模板ID
TaskTypeEnum.PHZ2MP: "template_phz2mp_id", # 配货站到MP模板ID
TaskTypeEnum.MP2GG: "template_mp2gg_id", # MP到高柜模板ID
TaskTypeEnum.MP2GGFK: "571985c1-cfa5-4186-8acd-6e3868a5e08c", # MP到高柜发库模板ID
TaskTypeEnum.MP2GT: "template_mp2gt_id", # MP到高台模板ID
TaskTypeEnum.MP2GTFK: "template_mp2gtfk_id", # MP到高台发库模板ID
TaskTypeEnum.MP2ZG: "template_mp2zg_id", # MP到中柜模板ID
TaskTypeEnum.MP2QZ: "template_mp2qz_id", # MP到清洗模板ID
TaskTypeEnum.MP2LG: "template_mp2lg_id", # MP到料柜模板ID
TaskTypeEnum.MP2PHZ: "template_mp2phz_id", # MP到配货站模板ID
}
@router.post("/newTask")
async def create_new_task(request: Request, task_request: ExternalTaskRequest = Body(...)):
"""
创建新任务接口
根据任务类型自动选择对应的任务模板并执行任务
Args:
task_request: 外部任务创建请求包含ReqCodeSourceIDTargetIDTaskType
Returns:
ExternalTaskResponse: 包含codereqCodemessagerowCount的响应
"""
try:
logger.info(f"收到外部任务创建请求: ReqCode={task_request.ReqCode}, TaskType={task_request.TaskType}")
# 根据任务类型获取对应的模板ID
template_id = TASK_TYPE_TEMPLATE_MAPPING.get(task_request.TaskType)
# print("template_id::::", template_id, "==========")
if not template_id:
logger.error(f"不支持的任务类型: {task_request.TaskType}")
return ExternalTaskResponse(
code=400,
reqCode=task_request.ReqCode,
message=f"不支持的任务类型: {task_request.TaskType}",
rowCount=0
)
# 构造任务运行参数
task_params = []
# 添加SourceID参数如果提供
if task_request.SourceID:
task_params.append(TaskInputParamNew(
name="sourceId",
type=InputParamType.STRING,
label="来源ID",
required=False,
defaultValue=task_request.SourceID,
remark="外部接口传入的来源ID"
))
# 添加TargetID参数
task_params.append(TaskInputParamNew(
name="targetId",
type=InputParamType.STRING,
label="目标ID",
required=True,
defaultValue=task_request.TargetID,
remark="外部接口传入的目标ID"
))
# 添加ReqCode参数
task_params.append(TaskInputParamNew(
name="reqCode",
type=InputParamType.STRING,
label="请求标识码",
required=True,
defaultValue=task_request.ReqCode,
remark="外部接口传入的请求唯一标识码"
))
# 构造任务执行请求
run_request = TaskEditRunRequest(
taskId=template_id,
params=task_params,
source_type=SourceType.SYSTEM_SCHEDULING, # 第三方系统
source_system="EXTERNAL_API", # 外部接口系统标识
source_device=request.client.host if request.client else "unknown", # 使用客户端IP作为设备标识
use_modbus=False,
modbus_timeout=5000
)
# 获取客户端信息
client_ip = request.client.host if request.client else None
user_agent = request.headers.get("user-agent", "")
tf_api_token = TF_API_TOKEN
client_info = {
"user_agent": user_agent,
"headers": dict(request.headers),
"method": request.method,
"url": str(request.url)
}
client_info_str = json.dumps(client_info, ensure_ascii=False)
# print("tf_api_config::::::::::::", tf_api_token)
# print("run_request:::::::::", run_request)
# print("client_ip:::::::::", client_ip)
# print("client_info:::::::::", client_info)
# print("client_info_str:::::::::", client_info_str)
# print("tf_api_token:::::::::", tf_api_token)
# 调用任务执行服务
result = await TaskEditService.run_task(
run_request,
client_ip=client_ip,
client_info=client_info_str,
tf_api_token=tf_api_token
)
if result is None:
logger.error(f"任务启动失败: ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message="任务启动失败",
rowCount=0
)
if not result.get("success", False):
logger.error(f"任务启动失败: {result.get('message')}, ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message=result.get("message", "任务启动失败"),
rowCount=0
)
logger.info(f"任务启动成功: ReqCode={task_request.ReqCode}, TaskRecordId={result.get('taskRecordId')}")
return ExternalTaskResponse(
code=0,
reqCode=task_request.ReqCode,
message="成功",
rowCount=1
)
except Exception as e:
logger.error(f"创建外部任务异常: {str(e)}, ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message=f"创建任务失败: {str(e)}",
rowCount=0
)
@router.post("/GenAgvSchedulingTask")
async def gen_agv_scheduling_task(request: Request, task_request: GenAgvSchedulingTaskRequest = Body(...)):
"""
AGV调度任务接口
用于生成AGV调度任务
Args:
task_request: AGV调度任务请求包含ReqCodeTaskTypSecurityKey等参数
Returns:
ExternalTaskResponse: 包含codereqCodemessagerowCount的响应
"""
try:
logger.info(f"收到AGV调度任务请求: ReqCode={task_request.ReqCode}, TaskTyp={task_request.TaskTyp}")
# # 验证安全密钥(可根据实际需求实现验证逻辑)
# if not task_request.SecurityKey:
# logger.error(f"安全密钥不能为空: ReqCode={task_request.ReqCode}")
# return ExternalTaskResponse(
# code=400,
# reqCode=task_request.ReqCode,
# message="安全密钥不能为空",
# rowCount=0GenAgvSchedulingTaskRequest
# )
# 根据任务类型获取对应的模板ID
template_id = TASK_TYPE_TEMPLATE_MAPPING.get(task_request.TaskTyp)
# if not template_id:
# logger.error(f"不支持的任务类型: {task_request.TaskTyp}, ReqCode={task_request.ReqCode}")
# return ExternalTaskResponse(
# code=400,
# reqCode=task_request.ReqCode,
# message=f"不支持的任务类型: {task_request.TaskTyp}",
# rowCount=0
# )
# 构造任务运行参数
task_params = []
# 添加任务代码参数
task_params.append(TaskInputParamNew(
name="taskCode",
type=InputParamType.STRING,
label="任务代码",
required=True,
defaultValue=task_request.TaskCode,
remark="AGV调度任务代码"
))
# 添加类型参数
task_params.append(TaskInputParamNew(
name="type",
type=InputParamType.STRING,
label="类型",
required=True,
defaultValue=task_request.Type,
remark="任务类型标识"
))
# 添加子类型参数
task_params.append(TaskInputParamNew(
name="subType",
type=InputParamType.STRING,
label="子类型",
required=True,
defaultValue=task_request.SubType,
remark="任务子类型标识"
))
# 添加区域位置代码参数
task_params.append(TaskInputParamNew(
name="areaPositonCode",
type=InputParamType.STRING,
label="区域位置代码",
required=True,
defaultValue=task_request.AreaPositonCode,
remark="区域位置代码"
))
# 添加区域位置名称参数
task_params.append(TaskInputParamNew(
name="areaPositonName",
type=InputParamType.STRING,
label="区域位置名称",
required=True,
defaultValue=task_request.AreaPositonName,
remark="区域位置名称"
))
# 添加位置代码路径参数转为JSON字符串
position_path_json = json.dumps([path.dict() for path in task_request.PositionCodePath], ensure_ascii=False)
task_params.append(TaskInputParamNew(
name="positionCodePath",
type=InputParamType.STRING,
label="位置代码路径",
required=True,
defaultValue=position_path_json,
remark="位置代码路径JSON数组"
))
# 添加客户端代码参数(如果提供)
if task_request.ClientCode:
task_params.append(TaskInputParamNew(
name="clientCode",
type=InputParamType.STRING,
label="客户端代码",
required=False,
defaultValue=task_request.ClientCode,
remark="客户端代码"
))
# 添加令牌代码参数(如果提供)
if task_request.TokenCode:
task_params.append(TaskInputParamNew(
name="tokenCode",
type=InputParamType.STRING,
label="令牌代码",
required=False,
defaultValue=task_request.TokenCode,
remark="令牌代码"
))
# 添加ReqCode参数
task_params.append(TaskInputParamNew(
name="reqCode",
type=InputParamType.STRING,
label="请求标识码",
required=True,
defaultValue=task_request.ReqCode,
remark="请求唯一标识码"
))
# 构造任务执行请求
run_request = TaskEditRunRequest(
taskId=template_id,
params=task_params,
source_type=SourceType.SYSTEM_SCHEDULING, # 第三方系统
source_system="AGV_SCHEDULING", # AGV调度系统标识
source_device=request.client.host if request.client else "unknown", # 使用客户端IP作为设备标识
use_modbus=False,
modbus_timeout=5000
)
# 获取客户端信息
client_ip = request.client.host if request.client else None
user_agent = request.headers.get("user-agent", "")
tf_api_token = TF_API_TOKEN
client_info = {
"user_agent": user_agent,
"headers": dict(request.headers),
"method": request.method,
"url": str(request.url)
}
client_info_str = json.dumps(client_info, ensure_ascii=False)
# 调用任务执行服务
result = await TaskEditService.run_task(
run_request,
client_ip=client_ip,
client_info=client_info_str,
tf_api_token=tf_api_token
)
if result is None:
logger.error(f"AGV调度任务启动失败: ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message="任务启动失败",
rowCount=0
)
if not result.get("success", False):
logger.error(f"AGV调度任务启动失败: {result.get('message')}, ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message=result.get("message", "任务启动失败"),
rowCount=0
)
logger.info(f"AGV调度任务启动成功: ReqCode={task_request.ReqCode}, TaskRecordId={result.get('taskRecordId')}")
return ExternalTaskResponse(
code=0,
reqCode=task_request.ReqCode,
message="成功",
rowCount=0
)
except Exception as e:
logger.error(f"创建AGV调度任务异常: {str(e)}, ReqCode={task_request.ReqCode}")
return ExternalTaskResponse(
code=500,
reqCode=task_request.ReqCode,
message=f"创建任务失败: {str(e)}",
rowCount=0
)