package com.mes.device.service.impl;
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.mes.device.entity.DeviceConfig;
|
import com.mes.device.entity.DeviceGroupConfig;
|
import com.mes.device.service.DeviceCoordinationService;
|
import com.mes.task.model.TaskExecutionContext;
|
import lombok.RequiredArgsConstructor;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.StringUtils;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
/**
|
* 设备协调服务实现
|
*
|
* @author mes
|
* @since 2025-01-XX
|
*/
|
@Slf4j
|
@Service
|
@RequiredArgsConstructor
|
public class DeviceCoordinationServiceImpl implements DeviceCoordinationService {
|
|
private static final TypeReference<Map<String, Object>> MAP_TYPE = new TypeReference<Map<String, Object>>() {};
|
|
private final ObjectMapper objectMapper;
|
|
@Override
|
public CoordinationResult coordinateExecution(DeviceGroupConfig groupConfig,
|
List<DeviceConfig> devices,
|
TaskExecutionContext context) {
|
if (CollectionUtils.isEmpty(devices)) {
|
return CoordinationResult.failure("设备列表为空");
|
}
|
|
// 检查所有设备的依赖关系
|
List<String> unsatisfiedDevices = new ArrayList<>();
|
for (DeviceConfig device : devices) {
|
DependencyCheckResult checkResult = checkDependencies(device, context);
|
if (!checkResult.isSatisfied()) {
|
unsatisfiedDevices.add(device.getDeviceName() + "(" + device.getDeviceCode() + ")");
|
log.warn("设备依赖检查失败: deviceId={}, message={}", device.getId(), checkResult.getMessage());
|
}
|
}
|
|
if (!unsatisfiedDevices.isEmpty()) {
|
String message = "以下设备的依赖条件不满足: " + String.join(", ", unsatisfiedDevices);
|
return CoordinationResult.failure(message);
|
}
|
|
// 构建协调元数据
|
Map<String, Object> metadata = new HashMap<>();
|
metadata.put("deviceCount", devices.size());
|
metadata.put("executionOrder", devices.stream()
|
.map(d -> d.getDeviceName() + "(" + d.getDeviceCode() + ")")
|
.collect(Collectors.toList()));
|
|
return CoordinationResult.success("设备协调成功,可以开始执行", metadata);
|
}
|
|
@Override
|
public boolean transferData(DeviceConfig fromDevice,
|
DeviceConfig toDevice,
|
Map<String, Object> data,
|
TaskExecutionContext context) {
|
if (fromDevice == null || toDevice == null || data == null || context == null) {
|
log.warn("数据传递参数不完整");
|
return false;
|
}
|
|
try {
|
// 将数据存储到共享上下文中
|
String dataKey = String.format("device_%s_to_%s", fromDevice.getId(), toDevice.getId());
|
context.getSharedData().put(dataKey, data);
|
|
// 根据设备类型,提取关键数据并更新上下文
|
if (DeviceConfig.DeviceType.LOAD_VEHICLE.equals(fromDevice.getDeviceType())) {
|
// 大车设备完成,传递玻璃ID列表
|
Object glassIds = data.get("glassIds");
|
if (glassIds instanceof List) {
|
@SuppressWarnings("unchecked")
|
List<String> ids = (List<String>) glassIds;
|
context.setLoadedGlassIds(new ArrayList<>(ids));
|
log.info("大车设备数据传递: fromDevice={}, toDevice={}, glassIds={}",
|
fromDevice.getDeviceCode(), toDevice.getDeviceCode(), ids);
|
}
|
} else if (DeviceConfig.DeviceType.LARGE_GLASS.equals(fromDevice.getDeviceType())) {
|
// 大理片设备完成,传递处理后的玻璃ID列表
|
Object glassIds = data.get("glassIds");
|
if (glassIds instanceof List) {
|
@SuppressWarnings("unchecked")
|
List<String> ids = (List<String>) glassIds;
|
context.setProcessedGlassIds(new ArrayList<>(ids));
|
log.info("大理片设备数据传递: fromDevice={}, toDevice={}, glassIds={}",
|
fromDevice.getDeviceCode(), toDevice.getDeviceCode(), ids);
|
}
|
}
|
|
// 存储通用数据
|
context.getSharedData().put("lastTransferFrom", fromDevice.getId());
|
context.getSharedData().put("lastTransferTo", toDevice.getId());
|
context.getSharedData().put("lastTransferTime", System.currentTimeMillis());
|
|
return true;
|
} catch (Exception e) {
|
log.error("数据传递失败: fromDevice={}, toDevice={}",
|
fromDevice.getDeviceCode(), toDevice.getDeviceCode(), e);
|
return false;
|
}
|
}
|
|
@Override
|
public void syncDeviceStatus(DeviceConfig device,
|
DeviceStatus status,
|
TaskExecutionContext context) {
|
if (device == null || context == null) {
|
return;
|
}
|
|
String statusKey = String.format("device_%s_status", device.getId());
|
context.getSharedData().put(statusKey, status.name());
|
context.getSharedData().put(statusKey + "_time", System.currentTimeMillis());
|
|
// 更新设备状态映射
|
@SuppressWarnings("unchecked")
|
Map<Long, String> deviceStatusMap = (Map<Long, String>) context.getSharedData()
|
.computeIfAbsent("deviceStatusMap", k -> new HashMap<Long, String>());
|
deviceStatusMap.put(device.getId(), status.name());
|
|
log.debug("设备状态同步: deviceId={}, status={}", device.getId(), status);
|
}
|
|
@Override
|
public DependencyCheckResult checkDependencies(DeviceConfig device,
|
TaskExecutionContext context) {
|
if (device == null || context == null) {
|
return DependencyCheckResult.unsatisfied("设备或上下文为空", Collections.emptyList());
|
}
|
|
List<String> missingDependencies = new ArrayList<>();
|
|
// 检查设备类型特定的依赖
|
String deviceType = device.getDeviceType();
|
if (DeviceConfig.DeviceType.LARGE_GLASS.equals(deviceType)) {
|
// 大理片设备需要大车设备先完成
|
List<String> loadedGlassIds = context.getSafeLoadedGlassIds();
|
if (CollectionUtils.isEmpty(loadedGlassIds)) {
|
missingDependencies.add("大车设备未完成,缺少玻璃ID列表");
|
}
|
} else if (DeviceConfig.DeviceType.GLASS_STORAGE.equals(deviceType)) {
|
// 玻璃存储设备需要大理片设备先完成(优先),或大车设备完成
|
List<String> processedGlassIds = context.getSafeProcessedGlassIds();
|
List<String> loadedGlassIds = context.getSafeLoadedGlassIds();
|
if (CollectionUtils.isEmpty(processedGlassIds) && CollectionUtils.isEmpty(loadedGlassIds)) {
|
missingDependencies.add("前置设备未完成,缺少玻璃ID列表");
|
}
|
}
|
|
// 检查设备配置中的依赖关系(从extraParams中读取)
|
Map<String, Object> deviceDependencies = getDeviceDependencies(device);
|
if (!CollectionUtils.isEmpty(deviceDependencies)) {
|
for (Map.Entry<String, Object> entry : deviceDependencies.entrySet()) {
|
String depDeviceCode = entry.getKey();
|
Object depStatus = entry.getValue();
|
|
// 检查依赖设备的状态
|
@SuppressWarnings("unchecked")
|
Map<Long, String> deviceStatusMap = (Map<Long, String>) context.getSharedData()
|
.get("deviceStatusMap");
|
|
if (deviceStatusMap != null) {
|
// 这里简化处理,实际应该根据deviceCode查找设备ID
|
// 暂时跳过基于设备代码的依赖检查
|
}
|
}
|
}
|
|
if (missingDependencies.isEmpty()) {
|
return DependencyCheckResult.satisfied();
|
}
|
|
return DependencyCheckResult.unsatisfied(
|
"设备依赖条件不满足: " + String.join(", ", missingDependencies),
|
missingDependencies
|
);
|
}
|
|
@Override
|
public List<DeviceConfig> getDependentDevices(DeviceConfig device,
|
DeviceGroupConfig groupConfig) {
|
if (device == null || groupConfig == null) {
|
return Collections.emptyList();
|
}
|
|
// 从设备配置中读取依赖关系
|
Map<String, Object> deviceDependencies = getDeviceDependencies(device);
|
if (CollectionUtils.isEmpty(deviceDependencies)) {
|
return Collections.emptyList();
|
}
|
|
// 这里需要根据deviceCode查找对应的DeviceConfig
|
// 简化实现,返回空列表
|
// 实际应该查询设备组中的所有设备,然后根据deviceCode匹配
|
log.debug("获取设备依赖: deviceId={}, dependencies={}", device.getId(), deviceDependencies);
|
return Collections.emptyList();
|
}
|
|
/**
|
* 从设备配置中获取依赖关系
|
*/
|
private Map<String, Object> getDeviceDependencies(DeviceConfig device) {
|
String extraParams = device.getExtraParams();
|
if (!StringUtils.hasText(extraParams)) {
|
return Collections.emptyMap();
|
}
|
|
try {
|
Map<String, Object> extraParamsMap = objectMapper.readValue(extraParams, MAP_TYPE);
|
@SuppressWarnings("unchecked")
|
Map<String, Object> dependencies = (Map<String, Object>) extraParamsMap.get("dependencies");
|
return dependencies != null ? dependencies : Collections.emptyMap();
|
} catch (Exception e) {
|
log.warn("解析设备依赖关系失败, deviceId={}", device.getId(), e);
|
return Collections.emptyMap();
|
}
|
}
|
}
|