using Quartz;
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_ITaskInfoRepository;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.StackerCrane;
using WIDESEAWCS_Tasks.StackerCraneJob;
using WIDESEA_Core;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_Tasks
{
///
/// 堆垛机任务作业(Quartz Job)- 核心调度逻辑
///
///
/// Quartz 定时任务,负责堆垛机的任务调度。
/// 使用 [DisallowConcurrentExecution] 禁止并发执行,确保同一堆垛机的任务串行处理。
///
/// 核心职责:
/// 1. 从配置文件加载命令类型映射
/// 2. 检查堆垛机任务完成状态
/// 3. 选择合适的任务(委托给 StackerCraneTaskSelector)
/// 4. 构建命令对象(委托给 StackerCraneCommandBuilder)
/// 5. 发送命令到堆垛机
/// 6. 处理任务完成事件
///
/// 架构设计:
/// - StackerCraneTaskSelector:负责选择合适的任务
/// - StackerCraneCommandBuilder:负责将任务转换为命令对象
/// - CommonStackerCraneJob:负责调度流程控制
///
[DisallowConcurrentExecution]
public class CommonStackerCraneJob : IJob
{
///
/// 任务服务
///
private readonly ITaskService _taskService;
///
/// 任务执行明细服务
///
private readonly ITaskExecuteDetailService _taskExecuteDetailService;
///
/// 任务仓储
///
private readonly ITaskRepository _taskRepository;
///
/// 堆垛机命令配置
///
///
/// 包含巷道与命令类型的映射关系。
/// 从 JSON 文件加载。
///
private readonly StackerCraneCommandConfig _config;
///
/// 堆垛机任务选择器
///
///
/// 负责选择合适的任务进行执行。
///
private readonly StackerCraneTaskSelector _taskSelector;
///
/// 堆垛机命令构建器
///
///
/// 负责将任务转换为堆垛机可执行的命令对象。
///
private readonly StackerCraneCommandBuilder _commandBuilder;
///
/// 构造函数
///
/// 任务服务
/// 任务执行明细服务
/// 任务仓储
/// 路由服务
/// HTTP 客户端帮助类
public CommonStackerCraneJob(
ITaskService taskService,
ITaskExecuteDetailService taskExecuteDetailService,
ITaskRepository taskRepository,
IRouterService routerService,
HttpClientHelper httpClientHelper)
{
_taskService = taskService;
_taskExecuteDetailService = taskExecuteDetailService;
_taskRepository = taskRepository;
// 加载配置文件
_config = LoadConfig();
// 初始化任务选择器
_taskSelector = new StackerCraneTaskSelector(taskService, routerService, httpClientHelper);
// 初始化命令构建器
_commandBuilder = new StackerCraneCommandBuilder(taskService, routerService, _config);
}
///
/// 加载配置文件(优先级:配置文件 > 默认配置)
///
///
/// 从应用程序目录下的 StackerCraneJob/stackercrane-command-config.json 读取配置。
/// 如果文件不存在或解析失败,使用默认配置。
///
/// 堆垛机命令配置
private static StackerCraneCommandConfig LoadConfig()
{
try
{
// 构造配置文件路径
string configPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "StackerCraneJob", "stackercrane-command-config.json");
if (File.Exists(configPath))
{
// 读取并解析 JSON 配置
string json = File.ReadAllText(configPath);
return System.Text.Json.JsonSerializer.Deserialize(json) ?? new StackerCraneCommandConfig();
}
}
catch (Exception ex)
{
// 配置加载失败,使用默认配置
Console.WriteLine($"配置加载失败: {ex.Message},使用默认配置");
}
return new StackerCraneCommandConfig();
}
///
/// Quartz Job 的执行入口
///
///
/// 执行流程:
/// 1. 从 JobDataMap 获取堆垛机设备信息
/// 2. 订阅任务完成事件(仅第一次执行时)
/// 3. 检查堆垛机任务完成状态
/// 4. 检查是否可以发送任务
/// 5. 选择任务
/// 6. 构建命令
/// 7. 发送命令
/// 8. 更新任务状态和堆垛机状态
///
/// Quartz 作业执行上下文
public Task Execute(IJobExecutionContext context)
{
try
{
// 从 JobDataMap 获取堆垛机设备参数
bool flag = context.JobDetail.JobDataMap.TryGetValue("JobParams", out object? value);
if (!flag || value is not IStackerCrane commonStackerCrane)
{
// 参数无效,直接返回
return Task.CompletedTask;
}
// ========== 订阅任务完成事件(全局只订阅一次) ==========
if (!commonStackerCrane.IsEventSubscribed)
{
// 绑定任务完成事件处理方法
commonStackerCrane.StackerCraneTaskCompletedEventHandler += CommonStackerCrane_StackerCraneTaskCompletedEventHandler;
}
// ========== 检查堆垛机任务完成状态 ==========
commonStackerCrane.CheckStackerCraneTaskCompleted();
// ========== 检查是否可以发送新任务 ==========
if (!commonStackerCrane.IsCanSendTask(commonStackerCrane.Communicator, commonStackerCrane.DeviceProDTOs, commonStackerCrane.DeviceProtocolDetailDTOs))
{
// 堆垛机不可用(如正在执行上一任务),直接返回
return Task.CompletedTask;
}
// ========== 选择任务 ==========
// 任务选择下沉到专用选择器
Dt_Task? task = _taskSelector.SelectTask(commonStackerCrane);
if (task == null)
{
// 没有可用任务
return Task.CompletedTask;
}
// ========== 构建命令 ==========
// 命令构建下沉到专用构建器
object? stackerCraneTaskCommand = _commandBuilder.ConvertToStackerCraneTaskCommand(task);
if (stackerCraneTaskCommand == null)
{
// 命令构建失败
return Task.CompletedTask;
}
// ========== 发送命令 ==========
bool sendFlag = SendStackerCraneCommand(commonStackerCrane, stackerCraneTaskCommand);
if (sendFlag)
{
// 发送成功,更新状态
commonStackerCrane.LastTaskType = task.TaskType;
_taskService.UpdateTaskStatusToNext(task.TaskNum);
}
}
catch (Exception ex)
{
// 记录异常
Console.WriteLine($"CommonStackerCraneJob Error: {ex.Message}");
}
return Task.CompletedTask;
}
///
/// 堆垛机任务完成事件处理
///
///
/// 当堆垛机报告任务完成时调用此方法。
/// 处理:
/// 1. 记录日志
/// 2. 更新任务状态为完成
/// 3. 清除堆垛机的作业指令
///
/// 事件发送者(堆垛机设备)
/// 事件参数,包含完成的任务号
private void CommonStackerCrane_StackerCraneTaskCompletedEventHandler(object? sender, StackerCraneTaskCompletedEventArgs e)
{
IStackerCrane? stackerCrane = sender as IStackerCrane;
if (stackerCrane != null)
{
// 记录日志
Console.Out.WriteLine("TaskCompleted" + e.TaskNum);
// 更新任务状态为完成
_taskService.StackCraneTaskCompleted(e.TaskNum);
// 清除堆垛机的作业指令(设置为 2,表示空闲)
stackerCrane.SetValue(StackerCraneDBName.WorkAction, 2);
}
}
///
/// 发送堆垛机命令
///
///
/// 根据命令类型调用相应的发送方法。
/// 支持标准命令和成型命令两种格式。
///
/// 堆垛机设备对象
/// 命令对象
/// 发送是否成功
private static bool SendStackerCraneCommand(IStackerCrane commonStackerCrane, object command)
{
return command switch
{
// 成型命令(如 HC 巷道)
FormationStackerCraneTaskCommand formationCommand => commonStackerCrane.SendCommand(formationCommand),
// 标准命令(如 GW、CW 巷道)
StackerCraneTaskCommand standardCommand => commonStackerCrane.SendCommand(standardCommand),
// 未知命令类型
_ => false
};
}
}
}