zhoushihao
2024-06-26 79cddf75458ebc5d8855f66ea9bf9ef073327b03
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
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
package com.mes.job;
 
import cn.hutool.core.lang.Assert;
import cn.smallbun.screw.core.util.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.mes.common.S7object;
import com.mes.common.config.Const;
import com.mes.device.PlcParameterObject;
import com.mes.downglassinfo.entity.DownGlassInfo;
import com.mes.downglassinfo.entity.DownGlassTask;
import com.mes.downglassinfo.service.DownGlassInfoService;
import com.mes.downglassinfo.service.DownGlassTaskService;
import com.mes.downstorage.entity.DownStorageCage;
import com.mes.downstorage.entity.DownStorageCageDetails;
import com.mes.downstorage.service.DownStorageCageDetailsService;
import com.mes.downstorage.service.DownStorageCageService;
import com.mes.downworkstation.entity.DownWorkstation;
import com.mes.downworkstation.entity.dto.DownGlassInfoDTO;
import com.mes.downworkstation.service.DownWorkstationService;
import com.mes.glassinfo.entity.GlassInfo;
import com.mes.glassinfo.service.GlassInfoService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
/**
 * @Author : zhoush
 * @Date: 2024/5/8 8:17
 * @Description:
 */
@Component
@Slf4j
public class DownLoadCacheGlassTask {
 
    @Autowired
    DownGlassTaskService downGlassTaskService;
    @Autowired
    GlassInfoService glassInfoService;
    @Autowired
    DownStorageCageDetailsService downStorageCageDetailsService;
    @Autowired
    DownStorageCageService downStorageCageService;
    @Autowired
    DownWorkstationService downWorkstationService;
    @Autowired
    DownGlassInfoService downGlassInfoService;
 
    @Value("${mes.threshold}")
    private Integer threshold;
 
    @Value("${mes.maxWidth}")
    private Integer maxWidth;
 
    @Value("${mes.maxHeight}")
    private Integer maxHeight;
 
 
    @Scheduled(fixedDelay = 1000)
    public void plcHomeEdgTask() {
        PlcParameterObject plcParameterObject = S7object.getinstance().PlcMesObject;
        String requestWord = plcParameterObject.getPlcParameter("RequestWord").getValue();
        String glassIdeValue = plcParameterObject.getPlcParameter("G04ID").getValue();
        String confirmationWrodValue = plcParameterObject.getPlcParameter("MES_confirmation_word").getValue();
        //A08  A09表示线路相同  可做等价  无数据转int异常
        String out08Glassstate = plcParameterObject.getPlcParameter("A08_glass_status").getValue();
        String out10Glassstate = plcParameterObject.getPlcParameter("A10_glass_status").getValue();
        String confirmationWrodAddress = plcParameterObject.getPlcParameter("MES_confirmation_word").getAddress();
        String currentSlot = plcParameterObject.getPlcParameter("Current_slot").getValue();
 
        log.info("1、获取到的请求字为:{},获取到的扫描ID为:{},获取到的确认字为:{},获取到的出片状态分别为:A09:{}、A10:{},当前格子号为:{}",
                requestWord, glassIdeValue, confirmationWrodValue, out08Glassstate, out10Glassstate, currentSlot);
 
        if ("0".equals(requestWord)) {
            if ("0".equals(confirmationWrodValue)) {
                log.info("2、获取到的请求字为0,且确认字为0,不执行任务");
                return;
            }
            log.info("2、获取到的请求字为0,将确认字改为0");
            S7object.getinstance().plccontrol.writeWord(confirmationWrodAddress, (short) 0);
            return;
        }
        if (!"0".equals(confirmationWrodValue)) {
            log.info("2、获取到的请求字不为0,将确认字不为0,直接结束");
            return;
        }
        if ("1".equals(requestWord)) {
            log.info("2、进片请求,且确认字为0,执行进片任务");
            inTo(glassIdeValue, confirmationWrodAddress, currentSlot);
        } else if ("2".equals(requestWord)) {
            //09空闲 :1      10空闲 :2        都空闲:3    其他0
            log.info("2、出片请求,且确认字为0,执行进片任务");
            outTo(Integer.parseInt(out08Glassstate),
                    Integer.parseInt(out10Glassstate), confirmationWrodAddress, "", 0);
        } else if ("3".equals(requestWord)) {
            log.info("2、进片和出片都空闲,执行出片任务");
            //加笼子里面是否有玻璃,有先出,无玻璃先进
            boolean outFlase = outTo(Integer.parseInt(out08Glassstate),
                    Integer.parseInt(out10Glassstate), confirmationWrodAddress, glassIdeValue, Integer.parseInt(currentSlot));
            log.info("出片任务是否完成:{},失败且玻璃id:{}不为空则执行进片任务", outFlase, glassIdeValue);
            if (!outFlase && StringUtils.isNotBlank(glassIdeValue)) {
                inTo(glassIdeValue, confirmationWrodAddress, currentSlot);
            }
        }
    }
 
 
    private void inTo(String glassId, String confirmationWrodAddress, String currentSlot) {
        log.info("1、按照玻璃id:{}获取玻璃小片信息,当前格子为:{}", glassId, currentSlot);
        //添加进片任务  查找空格
        DownStorageCage nearestEmpty = downStorageCageService.selectCacheEmpty(Integer.parseInt(currentSlot), Boolean.FALSE);
        Assert.isTrue(null != nearestEmpty, "格子已满,无法执行进片操作");
        log.info("2、查询卧式理片笼里面的空格:{}", nearestEmpty);
        GlassInfo glassInfo = glassInfoService.getOne(new LambdaQueryWrapper<GlassInfo>().eq(GlassInfo::getGlassId, glassId));
        Assert.isFalse(null == glassInfo, "玻璃信息不存在");
        Boolean checkFlag = Boolean.FALSE;
        //todo:玻璃尺寸是否走人工下片
        if (glassInfo.getWidth() > maxWidth || glassInfo.getHeight() > maxHeight) {
            log.info("该玻璃尺寸走人工下片,直接进片");
        } else {
            log.info("该玻璃尺寸非人工下片");
            //获取该玻璃的流程卡是否已绑定架子
            DownWorkstation one = downWorkstationService.getOne(new LambdaQueryWrapper<DownWorkstation>()
                    .eq(DownWorkstation::getLayer, glassInfo.getLayer())
                    .eq(DownWorkstation::getFlowCardId, glassInfo.getFlowCardId()));
            Boolean isBind = Boolean.FALSE;
            if (null != one) {
                log.info("该流程卡已绑定架子");
                isBind = Boolean.TRUE;
                checkFlag = multilayerCheck(glassInfo);
            }
            if (!checkFlag && !isBind) {
                log.info("该玻璃的流程卡未绑定架子,获取是否有空架子");
                List<DownWorkstation> list = downWorkstationService.list(new LambdaQueryWrapper<DownWorkstation>()
                        .isNull(DownWorkstation::getFlowCardId));
                if (CollectionUtils.isNotEmpty(list)) {
                    log.info("有空架子,将流程卡与架子好绑定,执行进片任务 结束");
                    //绑定流程卡
                    downWorkstationService.update(new LambdaUpdateWrapper<DownWorkstation>().set(DownWorkstation::getFlowCardId, glassInfo.getFlowCardId())
                            .eq(DownWorkstation::getWorkstationId, list.get(0).getWorkstationId()));
                    checkFlag = Boolean.TRUE;
                }
            }
            if (!checkFlag) {
                log.info("无空架子,获取已绑定架子的流程卡信息,查看玻璃信息是否可被对调");
                List<DownGlassInfoDTO> downGlassInfoDTOList = downGlassInfoService.queryWorkStationIsIn(Boolean.FALSE);
                log.info("获取架子上已绑定流程卡落架的数量及未落架的玻璃数据:{}", downGlassInfoDTOList);
                Assert.isTrue(CollectionUtils.isNotEmpty(downGlassInfoDTOList), "已绑定流程卡均无未落架玻璃,请及时处理架子上的玻璃,清除流程卡");
                //替换玻璃信息
                endLoop:
                for (DownGlassInfoDTO e : downGlassInfoDTOList) {
                    List<GlassInfo> glassInfoList = e.getGlassInfoList();
                    for (GlassInfo item : glassInfoList) {
                        if (item.getWidth().equals(glassInfo.getWidth()) && item.getHeight().equals(glassInfo.getHeight())
                                && item.getThickness().equals(glassInfo.getThickness()) && item.getFilmsid().equals(glassInfo.getFilmsid())) {
                            //todo:玻璃是否为多层
                            checkFlag = multilayerCheck(item);
                            if (checkFlag) {
                                //玻璃替换 仅替换流程卡id及层数
                                String tempFlowCardId = item.getFlowCardId();
                                Integer tempLayer = item.getLayer();
                                String flowCardId = glassInfo.getFlowCardId();
                                Integer layer = glassInfo.getLayer();
                                log.info("替换流程卡信息,当前玻璃信息:{}的流程卡号{}及层数{},替换后玻璃信息:{}的流程卡号{}及层数{}",
                                        item, glassInfo, flowCardId, layer, tempFlowCardId, tempLayer);
                                glassInfo.setFlowCardId(tempFlowCardId);
                                glassInfo.setLayer(tempLayer);
                                glassInfoService.updateById(glassInfo);
                                item.setFlowCardId(flowCardId);
                                item.setLayer(layer);
                                glassInfoService.updateById(item);
                                break endLoop;
                            }
                        }
                    }
                }
            }
        }
        //将任务插入理片笼详情表
        DownStorageCageDetails downStorageCageDetails = new DownStorageCageDetails();
        BeanUtils.copyProperties(glassInfo, downStorageCageDetails);
        downStorageCageDetails.setState(Const.GLASS_STATE_IN);
        downStorageCageDetailsService.save(downStorageCageDetails);
//        生成进片任务
        initDownGlassTask(glassInfo, nearestEmpty.getSlot() + "", null, Const.GLASS_CACHE_TYPE_IN);
        //log.info("5、生成进片任务信息存入任务表是否完成:{}", taskCache);
//        S7object.getinstance().plccontrol.writeWord(confirmationWrodAddress, (short) 1);
//        log.info("6、发送确认字完成");
    }
 
    private Boolean outTo(int parseInt, int parseInt1, String confirmationWrodAddress, String s, int i) {
        //定义笼内无法出片玻璃数量
        int glassCount = 0;
        String glassId = null;
        Boolean isBind = Boolean.FALSE;
 
        List<DownStorageCageDetails> list = downStorageCageDetailsService.list(new LambdaQueryWrapper<DownStorageCageDetails>()
                .eq(DownStorageCageDetails::getState, Const.GLASS_STATE_IN));
        log.info("笼内玻璃的数据有:{}", list);
        if (CollectionUtils.isEmpty(list)) {
            log.info("笼内没有玻璃,无法执行出片");
            return Boolean.FALSE;
        }
        for (DownStorageCageDetails item : list) {
            if (item.getWidth() > maxWidth || item.getHeight() > maxHeight) {
                log.info("玻璃宽度或高度超出阈值,执行人工下片");
                glassId = item.getGlassId();
                break;
            }
        }
        loop:
        if (glassId == null) {
            //获取正在落架的绑定流程卡的信息
            List<DownGlassInfoDTO> downGlassInfoDTOList = downGlassInfoService.queryWorkStationIsIn(Boolean.TRUE);
            List<String> downGlassFlowList = downGlassInfoDTOList.stream().map(item -> item.getFlowCardId() + ":" + item.getLayer()).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(downGlassFlowList)) {
                //获取架子玻璃都为空,出笼内子数量最多尺寸最大的玻璃
                DownStorageCageDetails downStorageCageDetails = downStorageCageDetailsService.getGlassInfoMaxCount();
                //绑定流程卡,更新玻璃状态,生成出片任务,
                glassId = downStorageCageDetails.getGlassId();
                isBind = Boolean.TRUE;
                break loop;
            }
            //将笼子内的玻璃进行过滤,仅获取无法落架的流程卡玻璃
            List<DownStorageCageDetails> noDownLoadList = list.stream().filter(item -> !downGlassFlowList.contains(item.getFlowCardId() + ":" + item.getLayer())).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(noDownLoadList)) {
                //是否有空架子
                List<DownWorkstation> emptyShelfList = downWorkstationService.list(new LambdaQueryWrapper<DownWorkstation>()
                        .isNull(DownWorkstation::getFlowCardId));
                if (CollectionUtils.isNotEmpty(emptyShelfList)) {
                    DownStorageCageDetails downStorageCageDetails = downStorageCageDetailsService.getGlassInfoMaxCount();
                    //绑定流程卡,更新玻璃状态,生成出片任务
                    glassId = downStorageCageDetails.getGlassId();
                    isBind = Boolean.TRUE;
                    break loop;
                }
                glassCount = noDownLoadList.size();
                if (glassCount > threshold) {
                    //更新玻璃状态,生成出片人工下片任务
                    glassId = noDownLoadList.get(0).getGlassId();
                    isBind = Boolean.FALSE;
                    break loop;
                }
            }
            //将笼子内的玻璃进行过滤,仅获取可落架的流程卡玻璃
            List<DownStorageCageDetails> downLoadList = list.stream().filter(item -> downGlassFlowList.contains(item.getFlowCardId() + ":" + item.getLayer())).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(downLoadList)) {
                //不执行出片任务,笼内没有合适的出片玻璃
                return Boolean.FALSE;
            }
            //将笼内玻璃的流程卡+层号 和落架的流程卡 去重,得出展示无法落架的玻璃,判断玻璃数是否超过阈值
            //笼内玻璃是否可落架:笼内是否有需要中空的
            List<DownStorageCageDetails> multiLayerList = list.stream().filter(item -> item.getTotalLayer() >= 2).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(multiLayerList)) {
                for (DownStorageCageDetails item : multiLayerList) {
                    DownGlassInfoDTO downGlassInfoDTO = downGlassInfoService.queryDownGlassMaxLayer(item.getFlowCardId());
                    if (null == downGlassInfoDTO) {
//                    落架玻璃查到相关流程卡玻璃信息,表明当前流程卡玻璃未落架
                        log.info("");
                        return Boolean.FALSE;
                    }
                    if (downGlassInfoDTO.getLayer().equals(downGlassInfoDTO.getLayer())) {
                        log.info("当前玻璃的流程在架子上落架最多,直接出片");
                        //更新玻璃状态,生成出片任务
                        glassId = noDownLoadList.get(0).getGlassId();
                        isBind = Boolean.FALSE;
                        break loop;
                    }
                    Integer sequence = downGlassInfoService.queryMaxSequence(item.getFlowCardId(), item.getLayer());
                    log.info("获取当前玻璃需要放的次序:笼内同流程 同层数的通达次序+1:{}", sequence);
                    DownGlassInfo downGlassInfo = downGlassInfoService.getOne(new LambdaQueryWrapper<DownGlassInfo>()
                            .eq(DownGlassInfo::getFlowCardId, downGlassInfoDTO.getFlowCardId())
                            .eq(DownGlassInfo::getLayer, downGlassInfoDTO.getLayer()).eq(DownGlassInfo::getSequence, sequence));
                    if (null != downGlassInfoDTO && downGlassInfo.getWidth().equals(item.getWidth()) && downGlassInfo.getHeight().equals(item.getHeight())) {
                        log.info("相同次序玻璃对应上,可执行进片任务");
                        //更新玻璃状态,生成出片任务
                        glassId = noDownLoadList.get(0).getGlassId();
                        isBind = Boolean.FALSE;
                        break loop;
                    } else {
                        log.info("同次序玻璃对应不上,需执行替换玻璃的操作");
                        glassCount += 1;
                        if (glassCount > threshold) {
                            glassId = noDownLoadList.get(0).getGlassId();
                            isBind = Boolean.FALSE;
                            break loop;
                        }
                        continue;
                    }
                }
            }
 
            Map<String, List<DownStorageCageDetails>> singleLayerMap = list.stream().filter(item -> item.getTotalLayer() == 1)
                    .collect(Collectors.groupingBy(item -> item.getFlowCardId() + item.getLayer(), Collectors.toList()));
            if (glassId == null) {
                if (CollectionUtils.isNotEmpty(singleLayerMap)) {
                    //获取已落架流程卡信息,按落架数量排序
                    for (DownGlassInfoDTO e : downGlassInfoDTOList) {
                        List<DownStorageCageDetails> downStorageCageDetails = singleLayerMap.get(e.getFlowCardId() + e.getLayer());
                        if (CollectionUtils.isNotEmpty(downStorageCageDetails)) {
                            glassId = downStorageCageDetails.get(0).getGlassId();
                            isBind = Boolean.FALSE;
                            break;
                        }
                    }
                }
            }
        }
        if (glassId == null) {
            log.info("没有找到可以下片的的玻璃,结束任务");
            return Boolean.FALSE;
        } else {
            //todo:按照出片的玻璃id更新笼内的玻璃状态为已出片
            return generateDownGlassOutTask(glassId, Const.GLASS_CACHE_TYPE_OUT, isBind);
        }
    }
 
    private Boolean multilayerCheck(GlassInfo glassInfo) {
        //查询该流程卡是否为多层
        if (glassInfo.getTotalLayer() > 1) {
            log.info("按照流程卡获取当前流程卡各层已落架数量");
            DownGlassInfoDTO downGlassInfoDTO = downGlassInfoService.queryDownGlassMaxLayer(glassInfo.getFlowCardId());
            if (null == downGlassInfoDTO) {
                log.info("架子已经占满,多层玻璃无法找到对应的格子,需执行替换玻璃的操作");
                return Boolean.FALSE;
            }
            if (downGlassInfoDTO.getLayer().equals(glassInfo.getLayer())) {
                log.info("当前玻璃的流程在架子上落架最多 直接进片");
                return Boolean.TRUE;
            }
            Integer sequence = downGlassInfoService.queryMaxSequence(glassInfo.getFlowCardId(), glassInfo.getLayer());
            log.info("获取当前玻璃需要放的次序:笼内同流程 同层数的通达次序+1:{}", sequence);
            DownGlassInfo downGlassInfo = downGlassInfoService.getOne(new LambdaQueryWrapper<DownGlassInfo>()
                    .eq(DownGlassInfo::getFlowCardId, downGlassInfoDTO.getFlowCardId())
                    .eq(DownGlassInfo::getLayer, downGlassInfoDTO.getLayer()).eq(DownGlassInfo::getSequence, sequence));
            log.info("拿当前版序获取玻璃信息{},按照次序判断当前玻璃是否尺寸对应的上(与数量最多的次序比较)。", downGlassInfo);
            if (null != downGlassInfoDTO && downGlassInfo.getWidth().equals(glassInfo.getWidth()) && downGlassInfo.getHeight().equals(glassInfo.getHeight())) {
                log.info("相同次序玻璃对应上,可执行进片任务");
                return Boolean.TRUE;
            } else {
                log.info("同次序玻璃对应不上,需执行替换玻璃的操作");
                return Boolean.FALSE;
            }
        } else {
            log.info("非多层玻璃,直接进片");
            return Boolean.TRUE;
        }
    }
 
    private Boolean generateDownGlassOutTask(String glassId, Integer taskType, Boolean isBind) {
        //按玻璃id获取玻璃信息
        DownStorageCageDetails downStorageCageDetails = downStorageCageDetailsService.getOne(new LambdaQueryWrapper<DownStorageCageDetails>()
                .eq(DownStorageCageDetails::getGlassId, glassId));
        String endCell = null;
        if (isBind) {
            //获取空架子信息,将空架子信息绑定流程卡
            DownWorkstation emptyDownWorkstation = downWorkstationService.getOne(new LambdaQueryWrapper<DownWorkstation>()
                    .isNull(DownWorkstation::getFlowCardId).orderByDesc(DownWorkstation::getWorkstationId).last("limit 1"));
            if (null != emptyDownWorkstation) {
                log.info("获取到空架子信息,绑定流程卡");
                emptyDownWorkstation.setFlowCardId(downStorageCageDetails.getFlowCardId());
                emptyDownWorkstation.setLayer(downStorageCageDetails.getLayer());
                downWorkstationService.updateById(emptyDownWorkstation);
                endCell = emptyDownWorkstation.getWorkstationId() + "";
            } else {
                log.info("没有空架子信息,无法绑定流程卡");
                return Boolean.FALSE;
            }
        } else {
            DownWorkstation workstation = downWorkstationService.getOne(new LambdaUpdateWrapper<DownWorkstation>()
                    .eq(DownWorkstation::getFlowCardId, downStorageCageDetails.getFlowCardId()).eq(DownWorkstation::getLayer, downStorageCageDetails.getLayer()));
            endCell = workstation.getWorkstationId() + "";
        }
        //更新详情表内的状态
        if (downStorageCageDetailsService.update(new LambdaUpdateWrapper<DownStorageCageDetails>()
                .set(DownStorageCageDetails::getState, Const.GLASS_STATE_OUT).eq(DownStorageCageDetails::getGlassId, glassId))) {
            log.info("更新详情表内的状态成功");
        } else {
            log.info("更新详情表内的状态失败");
            return Boolean.FALSE;
        }
        //生成任务信息
        GlassInfo glassInfo = new GlassInfo();
        BeanUtils.copyProperties(downStorageCageDetails, glassInfo);
        return initDownGlassTask(glassInfo, downStorageCageDetails.getSlot() + "", endCell, taskType);
    }
 
    private Boolean initDownGlassTask(GlassInfo glassInfo, String startCell, String endCell, Integer taskType) {
        log.info("玻璃{}生成进片任务", glassInfo.getGlassId());
        DownGlassTask downGlassTask = new DownGlassTask();
        BeanUtils.copyProperties(glassInfo, downGlassTask);
        downGlassTask.setStartCell(startCell);
        downGlassTask.setEndCell(endCell);
        downGlassTask.setTaskType(taskType + "");
        downGlassTask.setTaskStauts(0);
        downGlassTask.setCreateTime(new Date());
        return downGlassTaskService.save(downGlassTask);
    }
}