package com.mes.task.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.mes.device.entity.DeviceConfig;
|
import com.mes.device.entity.DeviceGroupConfig;
|
import com.mes.device.mapper.DeviceGroupRelationMapper;
|
import com.mes.device.service.DeviceGroupConfigService;
|
import com.mes.task.dto.MultiDeviceTaskQuery;
|
import com.mes.task.dto.MultiDeviceTaskRequest;
|
import com.mes.task.dto.TaskParameters;
|
import com.mes.task.entity.MultiDeviceTask;
|
import com.mes.task.entity.TaskStepDetail;
|
import com.mes.task.mapper.MultiDeviceTaskMapper;
|
import com.mes.task.mapper.TaskStepDetailMapper;
|
import com.mes.task.model.TaskExecutionResult;
|
import com.mes.task.service.MultiDeviceTaskService;
|
import com.mes.task.service.TaskExecutionEngine;
|
import com.mes.task.service.TaskStatusNotificationService;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.StringUtils;
|
|
import java.text.SimpleDateFormat;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Locale;
|
|
/**
|
* 多设备任务服务实现
|
*/
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class MultiDeviceTaskServiceImpl extends ServiceImpl<MultiDeviceTaskMapper, MultiDeviceTask>
|
implements MultiDeviceTaskService {
|
|
private final DeviceGroupConfigService deviceGroupConfigService;
|
private final DeviceGroupRelationMapper deviceGroupRelationMapper;
|
private final TaskStepDetailMapper taskStepDetailMapper;
|
private final TaskExecutionEngine taskExecutionEngine;
|
private final TaskStatusNotificationService notificationService;
|
private final ObjectMapper objectMapper;
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public MultiDeviceTask startTask(MultiDeviceTaskRequest request) {
|
DeviceGroupConfig groupConfig = deviceGroupConfigService.getDeviceGroupById(request.getGroupId());
|
if (groupConfig == null) {
|
throw new IllegalArgumentException("设备组不存在: " + request.getGroupId());
|
}
|
if (groupConfig.getStatus() != DeviceGroupConfig.Status.ENABLED) {
|
throw new IllegalStateException("设备组未启用,无法执行任务");
|
}
|
|
List<DeviceConfig> devices = deviceGroupRelationMapper.getOrderedDeviceConfigs(groupConfig.getId());
|
if (CollectionUtils.isEmpty(devices)) {
|
throw new IllegalStateException("设备组未配置任何设备,无法执行任务");
|
}
|
|
TaskParameters parameters = request.getParameters();
|
if (parameters == null || CollectionUtils.isEmpty(parameters.getGlassIds())) {
|
throw new IllegalArgumentException("至少需要配置一条玻璃ID");
|
}
|
|
MultiDeviceTask task = new MultiDeviceTask();
|
task.setTaskId(generateTaskId(groupConfig));
|
task.setGroupId(String.valueOf(groupConfig.getId()));
|
task.setProjectId(String.valueOf(groupConfig.getProjectId()));
|
task.setStatus(MultiDeviceTask.Status.PENDING.name());
|
task.setCurrentStep(0);
|
task.setTotalSteps(devices.size());
|
task.setStartTime(new Date());
|
save(task);
|
|
try {
|
// 通知任务开始
|
notificationService.notifyTaskStatus(task);
|
|
TaskExecutionResult result = taskExecutionEngine.execute(task, groupConfig, devices, parameters);
|
task.setStatus(result.isSuccess() ? MultiDeviceTask.Status.COMPLETED.name() : MultiDeviceTask.Status.FAILED.name());
|
task.setErrorMessage(result.isSuccess() ? null : result.getMessage());
|
task.setEndTime(new Date());
|
task.setResultData(writeJson(result.getData()));
|
updateById(task);
|
|
// 通知任务完成
|
notificationService.notifyTaskStatus(task);
|
|
return task;
|
} catch (Exception ex) {
|
log.error("多设备任务执行异常, taskId={}", task.getTaskId(), ex);
|
task.setStatus(MultiDeviceTask.Status.FAILED.name());
|
task.setErrorMessage(ex.getMessage());
|
task.setEndTime(new Date());
|
updateById(task);
|
throw new RuntimeException("多设备任务执行失败: " + ex.getMessage(), ex);
|
}
|
}
|
|
@Override
|
public MultiDeviceTask getTaskByTaskId(String taskId) {
|
LambdaQueryWrapper<MultiDeviceTask> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(MultiDeviceTask::getTaskId, taskId);
|
return getOne(wrapper);
|
}
|
|
@Override
|
public List<TaskStepDetail> getTaskSteps(String taskId) {
|
LambdaQueryWrapper<TaskStepDetail> wrapper = new LambdaQueryWrapper<>();
|
wrapper.eq(TaskStepDetail::getTaskId, taskId);
|
wrapper.orderByAsc(TaskStepDetail::getStepOrder);
|
return taskStepDetailMapper.selectList(wrapper);
|
}
|
|
@Override
|
public boolean cancelTask(String taskId) {
|
MultiDeviceTask task = getTaskByTaskId(taskId);
|
if (task == null) {
|
return false;
|
}
|
if (!MultiDeviceTask.Status.RUNNING.name().equals(task.getStatus())) {
|
return false;
|
}
|
task.setStatus(MultiDeviceTask.Status.CANCELLED.name());
|
task.setEndTime(new Date());
|
return updateById(task);
|
}
|
|
@Override
|
public Page<MultiDeviceTask> queryTasks(MultiDeviceTaskQuery query) {
|
int page = query.getPage() != null && query.getPage() > 0 ? query.getPage() : 1;
|
int size = query.getSize() != null && query.getSize() > 0 ? query.getSize() : 10;
|
Page<MultiDeviceTask> pageParam = new Page<>(page, size);
|
|
LambdaQueryWrapper<MultiDeviceTask> wrapper = new LambdaQueryWrapper<>();
|
if (query.getGroupId() != null) {
|
wrapper.eq(MultiDeviceTask::getGroupId, String.valueOf(query.getGroupId()));
|
}
|
if (StringUtils.hasText(query.getStatus())) {
|
wrapper.eq(MultiDeviceTask::getStatus, query.getStatus().toUpperCase(Locale.ROOT));
|
}
|
wrapper.orderByDesc(MultiDeviceTask::getCreatedTime);
|
return page(pageParam, wrapper);
|
}
|
|
private String generateTaskId(DeviceGroupConfig groupConfig) {
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA);
|
return "TASK_" + groupConfig.getId() + "_" + sdf.format(new Date());
|
}
|
|
private String writeJson(Object data) {
|
if (data == null) {
|
return "{}";
|
}
|
try {
|
return objectMapper.writeValueAsString(data);
|
} catch (JsonProcessingException e) {
|
return "{}";
|
}
|
}
|
}
|