huang
2025-10-22 3eaf0f2f1b909ac429cac9fc26af767ddecda065
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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
package com.mes.job;
 
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.xingshuangs.iot.protocol.s7.serializer.S7Serializer;
import com.mes.common.config.Const;
import com.mes.engineering.entity.Engineering;
import com.mes.engineering.mapper.EngineeringMapper;
import com.mes.opctask.entity.LoadGlassDeviceTask;
import com.mes.opctask.entity.LoadGlassDeviceTaskHistory;
import com.mes.opctask.service.LoadGlassDeviceTaskHistoryService;
import com.mes.opctask.service.LoadGlassDeviceTaskService;
import com.mes.pp.entity.OptimizeProject;
import com.mes.pp.service.OptimizeProjectService;
import com.mes.rawglassdetails.entity.RawGlassStorageDetails;
import com.mes.rawglassdetails.service.RawGlassStorageDetailsService;
import com.mes.s7.entity.S7DataSP;
import com.mes.uppattenusage.entity.UpPattenUsage;
import com.mes.uppattenusage.entity.vo.UpPattenUsageVO;
import com.mes.uppattenusage.mapper.UpPattenUsageMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
 
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
/**
 * @Author : zhoush
 * @Date: 2024/10/23 14:30
 * @Description:
 */
@Component
@Slf4j
public class OpcLoadGlassTask {
 
    @Resource
    private EngineeringMapper engineeringMapper;
 
    @Resource
    private LoadGlassDeviceTaskService loadGlassDeviceTaskService;
    @Resource
    private RawGlassStorageDetailsService rawGlassStorageDetailsService;
    @Resource
    private LoadGlassDeviceTaskHistoryService loadGlassDeviceTaskHistoryService;
    @Resource
    private UpPattenUsageMapper upPattenUsageMapper;
    @Resource
    private OptimizeProjectService optimizeProjectService;
 
    @Autowired
    @Qualifier("s7SerializerSP1")
    private S7Serializer s7SerializerSPOne;
 
    @Autowired
    @Qualifier("s7SerializerSP2")
    private S7Serializer s7SerializerSPTwo;
 
    private static final List<Integer> LOAD_STATION_01 = Arrays.asList(101, 102);
    private static final List<Integer> LOAD_STATION_02 = Arrays.asList(103, 104);
 
 
    private static final Integer LOAD_GLASS_ONE_DEVICE = 5;
    private static final Integer LOAD_GLASS_TWO_DEVICE = 6;
    private static final String LOAD_GLASS_DEVICE_ONE_TASK = "load_glass_device_one_task";
 
    private static final String LOAD_GLASS_DEVICE_TWO_TASK = "load_glass_device_two_task";
 
    //设备id   上片位信息   任务表不一致   历史任务表公用一张 新增任务/任务结束,后会在历史表中新增一条记录并在结束后更新任务  一个任务即可
    //定时任务扫描上片位有没有原片
    //1、是否有在执行的任务
    //2、1号上片位是否有原片,原片尺寸是否和上片待上片的尺寸一致
    //3、1号无原片,且没有架子,2号上片位尺寸是否和带上片尺寸一致
    //4、不一致可能出现玻璃破损导致的上一架原片数量不够
    @Scheduled(fixedDelay = 2000)
    public void opcLoadGlassOne() {
        opcLoadGlassChild(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE);
    }
 
//    @Scheduled(fixedDelay = 5000)
    public void opcLoadGlassTwo() {
        opcLoadGlassChild(LOAD_GLASS_DEVICE_TWO_TASK, LOAD_GLASS_TWO_DEVICE);
    }
 
    @Scheduled(fixedDelay = 2000)
    public void opcLoadGlassOneFinish() {
        opcLoadGlassFinishChid(LOAD_GLASS_DEVICE_ONE_TASK, LOAD_GLASS_ONE_DEVICE);
    }
 
//    @Scheduled(fixedDelay = 5000)
    public void opcLoadGlassTwoFinish() {
        opcLoadGlassFinishChid(LOAD_GLASS_DEVICE_TWO_TASK, LOAD_GLASS_TWO_DEVICE);
    }
 
    /**
     * 定时任务扫码已完成上片的工程,将工程状态改为已完成,同步pp表的工程表,状态改为300
     */
    @Scheduled(fixedDelay = 5000)
    public void updateEngineerState() {
        log.info("修改已完成工程状态任务开始执行");
        List<Engineering> engineerings = engineeringMapper.selectList(new LambdaQueryWrapper<Engineering>().eq(Engineering::getState, Const.ENGINEERING_RUNNING));
        for (Engineering engineering : engineerings) {
            Integer count = upPattenUsageMapper.selectCount(new LambdaQueryWrapper<UpPattenUsage>()
                    .eq(UpPattenUsage::getEngineeringId, engineering.getEngineerId()).ne(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS));
            OptimizeProject project = optimizeProjectService.getOne(new LambdaUpdateWrapper<OptimizeProject>()
                    .eq(OptimizeProject::getProjectNo, 200)
                    .eq(OptimizeProject::getState, engineering.getEngineerId()));
            if (count == 0 && project != null) {
                engineeringMapper.update(null, new LambdaUpdateWrapper<Engineering>().set(Engineering::getState, Const.ENGINEERING_SUCCESS)
                        .eq(Engineering::getEngineerId, engineering.getEngineerId()));
                optimizeProjectService.update(null, new LambdaUpdateWrapper<OptimizeProject>().set(OptimizeProject::getState, 300)
                        .eq(OptimizeProject::getProjectNo, engineering.getEngineerId()));
            }
        }
    }
 
    private void opcLoadGlassChild(String tableName, Integer deviceId) {
        S7DataSP s7DataSP = new S7DataSP();
//        s7DataSP.setPlcRequest(1);
//        s7DataSP.setMesConfirm(0);
        if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) {
            s7DataSP = s7SerializerSPOne.read(S7DataSP.class);
        } else {
            s7DataSP = s7SerializerSPTwo.read(S7DataSP.class);
        }
        log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP);
 
        if (s7DataSP.getPlcRequest() == 0) {
            if (s7DataSP.getMesSend() != 0) {
                S7DataSP resetSend = new S7DataSP();
                resetSend.setMesSend(0);
                s7SerializerSPOne.write(resetSend);
                log.info("{}上片线,PLC请求清零,MES同步清零mesSend", deviceId);
            }
            return;
        }
 
        // 当PLC请求新任务(plcRequest=1)且无未确认汇报(mesConfirm=0)时处理
        if (s7DataSP.getPlcRequest() != 1 || s7DataSP.getMesConfirm() != 0) {
            log.info("{}上片线,PLC未请求新任务或存在未确认汇报,跳过本次处理", deviceId);
            return;
        }
 
        Engineering engineering = engineeringMapper.selectOne(new LambdaQueryWrapper<Engineering>()
                .eq(Engineering::getState, Const.ENGINEERING_RUNNING)
                .eq(Engineering::getStationCell, deviceId));
        if (null == engineering) {
            log.info("{}上片线,没有工程任务", deviceId);
            return;
        }
 
        List<UpPattenUsageVO> pattenUsageList = upPattenUsageMapper.queryRawGlassByEngineeringId(engineering.getEngineerId());
        log.info("获取正在需要上片的原片信息有:{}", pattenUsageList);
        if (CollectionUtils.isEmpty(pattenUsageList)) {
            log.info("当前工程需要上片的原片信息为空,任务已结束");
            return;
        }
        // 有无正在执行的任务
        UpPattenUsage runningTask = upPattenUsageMapper.selectOne(
                new LambdaQueryWrapper<UpPattenUsage>()
                        .eq(UpPattenUsage::getEngineeringId, engineering.getEngineerId())
                        .eq(UpPattenUsage::getState, 101)
                        .last("limit 1") // 只取一条
        );
        if (runningTask != null) {
            log.info("当前工程存在正在执行的上片任务,跳过本次处理");
            return;
        }
 
        Map<String, List<UpPattenUsageVO>> upListMap = pattenUsageList.stream()
                .collect(Collectors.groupingBy(UpPattenUsageVO::getGroupNumber));
        log.info("获取当前需要上片的原片数据");
        List<UpPattenUsageVO> usageVOS = upListMap.get("1");
//        获取1号上片位是有架子且有玻璃
        List<Integer> loadStation = LOAD_GLASS_DEVICE_ONE_TASK.equals(tableName) ? LOAD_STATION_01 : LOAD_STATION_02;
        List<RawGlassStorageDetails> loadStationList = rawGlassStorageDetailsService.list(new LambdaQueryWrapper<RawGlassStorageDetails>()
                .inSql(RawGlassStorageDetails::getSlot, "select slot from raw_glass_storage_station where enable_state = 1")
                .in(RawGlassStorageDetails::getState, Const.RAW_GLASS_STATE_IN)
                .eq(RawGlassStorageDetails::getDeviceId, deviceId));
        if (CollectionUtils.isEmpty(loadStationList)) {
            log.info("当前上片线路两个上片位都没有原片信息,结束本次上片任务,等待仓储调度任务");
            return;
        }
        RawGlassStorageDetails oneLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(0))).findFirst().orElse(null);
        if (null == oneLoadStation) {
            RawGlassStorageDetails twoLoadStation = loadStationList.stream().filter(e -> e.getSlot().equals(loadStation.get(1))).findFirst().orElse(null);
            if (!compareRawSize(usageVOS.get(0), twoLoadStation)) {
                log.info("二号上片位有架子,原片数量为0或者原片信息与待上片尺寸不一致,结束本次上片任务,等待仓储调度任务");
                return;
            }
            int number = Math.min(twoLoadStation.getRemainQuantity(), usageVOS.size());
            //生成上片任务
            LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory();
            task.setTotalCount(number);
            task.setTaskRunning(1);
            task.setRawGlassWidth((int) usageVOS.get(0).getWidth());
            task.setRawGlassHeight((int) usageVOS.get(0).getHeight());
            task.setSlot(1);
            task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId());
            task.setEngineeringId(usageVOS.get(0).getEngineeringId());
            saveHistoryTask(task, deviceId);
 
            S7DataSP s7DataSPWrite = new S7DataSP();
            s7DataSPWrite.setMesSend(1);
            s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth());
            s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight());
            s7DataSPWrite.setSlot(1);
            if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) {
                s7SerializerSPOne.write(s7DataSPWrite);
            } else {
                s7SerializerSPTwo.write(s7DataSPWrite);
            }
            return;
        }
        //尺寸不一样或者原片数量大于0
        if (!compareRawSize(usageVOS.get(0), oneLoadStation)) {
            log.info("一号上片位有架子,原片数量为0或者原片信息与待上片尺寸不一致,结束本次上片任务,等待仓储调度任务");
            return;
        }
        //生成上片任务
        int number = Math.min(oneLoadStation.getRemainQuantity(), usageVOS.size());
        LoadGlassDeviceTaskHistory task = new LoadGlassDeviceTaskHistory();
        task.setTotalCount(number);
        task.setTaskRunning(1);
        task.setRawGlassWidth((int) usageVOS.get(0).getWidth());
        task.setRawGlassHeight((int) usageVOS.get(0).getHeight());
        task.setRawGlassThickness((int) usageVOS.get(0).getThickness());
        task.setSlot(1);
        task.setRawGlassFilmsId(usageVOS.get(0).getFilmsId());
        task.setEngineeringId(usageVOS.get(0).getEngineeringId());
        saveHistoryTask(task, deviceId);
 
        UpPattenUsage upPattenUsage = upPattenUsageMapper.selectById(usageVOS.get(0).getId());
        upPattenUsage.setState(101);
        upPattenUsageMapper.updateById(upPattenUsage);
 
        S7DataSP s7DataSPWrite = new S7DataSP();
        s7DataSPWrite.setMesSend(1);
        s7DataSPWrite.setRawGlassWidth((int) usageVOS.get(0).getWidth());
        s7DataSPWrite.setRawGlassHeight((int) usageVOS.get(0).getHeight());
        s7DataSPWrite.setSlot(1);
        if (LOAD_GLASS_ONE_DEVICE.equals(deviceId)) {
            s7SerializerSPOne.write(s7DataSPWrite);
        } else {
            s7SerializerSPTwo.write(s7DataSPWrite);
        }
    }
 
    private void opcLoadGlassFinishChid(String tableName, Integer deviceId) {
        S7DataSP s7DataSP = new S7DataSP();
//        s7DataSP.setPlcReport(1);
//        s7DataSP.setMesConfirm(0);
        if (tableName.equals(LOAD_GLASS_DEVICE_ONE_TASK)) {
            s7DataSP = s7SerializerSPOne.read(S7DataSP.class);
        } else {
            s7DataSP = s7SerializerSPTwo.read(S7DataSP.class);
        }
        log.info("{}上片线,当前上片位信息:{}", deviceId, s7DataSP);
 
        if (s7DataSP.getPlcReport() == 0) {
            if (s7DataSP.getMesConfirm() != 0) {
                S7DataSP resetConfirm = new S7DataSP();
                resetConfirm.setMesConfirm(0);
                s7SerializerSPOne.write(resetConfirm);
                log.info("{}上片线,PLC汇报清零,MES同步清零mesConfirm", deviceId);
            }
            return;
        }
 
        if (s7DataSP.getPlcReport() == 0 || s7DataSP.getMesConfirm() != 0) {
            log.info("{}上片线,无PLC汇报或已确认,跳过本次处理", deviceId);
            return;
        }
        LoadGlassDeviceTaskHistory unconfirmedTask = loadGlassDeviceTaskHistoryService.getOne(
                new LambdaQueryWrapper<LoadGlassDeviceTaskHistory>()
                        .eq(LoadGlassDeviceTaskHistory::getStation, deviceId)
                        .eq(LoadGlassDeviceTaskHistory::getTaskState, Const.RAW_GLASS_TASK_RUNNING)
        );
        String upUsageId = unconfirmedTask.getEngineeringId();
        if (s7DataSP.getPlcReport() == 1) {
            // 汇报成功:更新上片记录为“成功”
            upPattenUsageMapper.update(null,
                    new LambdaUpdateWrapper<UpPattenUsage>()
                            .set(UpPattenUsage::getState, Const.LOAD_RAW_GLASS_SUCCESS)
                            .eq(UpPattenUsage::getEngineeringId, upUsageId)
                            .eq(UpPattenUsage::getState, 101)
            );
            unconfirmedTask.setTaskState(Const.RAW_GLASS_TASK_SUCCESS);
            unconfirmedTask.setFinishCount(unconfirmedTask.getFinishCount() + 1);
            log.info("{}上片线,任务汇报成功,更新上片记录[{}]为成功", deviceId, upUsageId);
 
            // PLC确认字1
            s7DataSP.setMesConfirm(1);
            s7SerializerSPOne.write(s7DataSP);
        } else if (s7DataSP.getPlcReport() == 2) {
            // 汇报失败
            unconfirmedTask.setTaskState(2);
//            unconfirmedTask.setDamageCount(unconfirmedTask.getDamageCount() + 1);
            log.warn("{}上片线,任务汇报失败,上片记录[{}]标记为失败", deviceId,  upUsageId);
 
            // PLC确认字2
            s7DataSP.setMesConfirm(2);
            s7SerializerSPOne.write(s7DataSP);
        }else if (s7DataSP.getPlcReport() == 3) {
            // 汇报破损
            unconfirmedTask.setTaskState(3);
            unconfirmedTask.setDamageCount(unconfirmedTask.getDamageCount() + 1);
            log.warn("{}上片线,任务汇报破损,上片记录[{}]标记为破损", deviceId,  upUsageId);
 
            // PLC确认字3
            s7DataSP.setMesConfirm(3);
            s7SerializerSPOne.write(s7DataSP);
        }
        unconfirmedTask.setUpdateTime(new Date());
        loadGlassDeviceTaskHistoryService.updateById(unconfirmedTask);
 
        //更新当前架子上的原片剩余情况
        rawGlassStorageDetailsService.update(new UpdateWrapper<RawGlassStorageDetails>()
                .inSql("slot", "select slot from raw_glass_storage_station where enable_state = 1")
//                .eq("slot", task.getSlot())
                .eq("slot", 101)
                .eq("state", Const.RAW_GLASS_STATE_IN)
                .setSql("remain_quantity = GREATEST(remain_quantity - 1, 0)"));
    }
 
    private boolean saveHistoryTask(LoadGlassDeviceTaskHistory task, Integer deviceId) {
        LoadGlassDeviceTaskHistory taskHistory = new LoadGlassDeviceTaskHistory();
        BeanUtils.copyProperties(task, taskHistory);
        taskHistory.setStation(deviceId);
        taskHistory.setCreateTime(new Date());
        taskHistory.setTaskState(Const.RAW_GLASS_TASK_RUNNING);
        loadGlassDeviceTaskHistoryService.save(taskHistory);
        return Boolean.TRUE;
    }
 
    /**
     * 尺寸一样并且原片数量大于0
     *
     * @param upPattenUsage
     * @param details
     * @return
     */
    private boolean compareRawSize(UpPattenUsage upPattenUsage, RawGlassStorageDetails details) {
        boolean flag = upPattenUsage.getWidth() == details.getPatternWidth() && upPattenUsage.getHeight() == details.getPatternHeight() &&
                upPattenUsage.getThickness() == details.getPatternThickness() && upPattenUsage.getFilmsId().equals(details.getFilmsId());
        return flag && details.getRemainQuantity() > 0;
    }
 
}