#!/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: 外部任务创建请求,包含ReqCode、SourceID、TargetID、TaskType Returns: ExternalTaskResponse: 包含code、reqCode、message、rowCount的响应 """ 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调度任务请求,包含ReqCode、TaskTyp、SecurityKey等参数 Returns: ExternalTaskResponse: 包含code、reqCode、message、rowCount的响应 """ 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 )