huang
2025-11-26 792236ef78c2cdd3a989fb40a7f2e2487c4e17b6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
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();
        }
    }
}