自动化立体仓库 - WMS系统
zwl
3 天以前 fd6f8822717ae6d32e1aef27f79da567915a2440
src/main/java/com/zy/api/service/impl/WcsApiServiceImpl.java
@@ -8,6 +8,9 @@
import com.core.exception.CoolException;
import com.zy.api.controller.params.ReceviceTaskParams;
import com.zy.api.controller.params.WorkTaskParams;
import com.zy.api.entity.CrnProtocol;
import com.zy.api.entity.DeviceStatusVo;
import com.zy.api.entity.StationProtocol;
import com.zy.api.service.WcsApiService;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
@@ -23,15 +26,17 @@
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Slf4j
@Service
public class WcsApiServiceImpl implements WcsApiService {
    private static final Long WCS_SYNC_USER = 9999L;
    private static final String YES = "Y";
    private static final String NO = "N";
    @Autowired
    private BasDeviceService basDeviceService;
@@ -62,6 +67,18 @@
    private String createLocMoveTask;
    @Autowired
    private CommonService commonService;
    @Value("${wcs.address.getDeviceStatus:/openapi/getDeviceStatus}")
    private String getDeviceStatus;
    @Value("${wcs.status-sync.method:GET}")
    private String deviceStatusMethod;
    @Value("${wcs.switch}")
    private String switchValue;
    @Autowired
    private BasDevpService basDevpService;
    @Autowired
    private BasCrnpService basCrnpService;
    /**
     * 通知WCS锁定库位,及禁止当前库位的一切操作
@@ -123,9 +140,9 @@
//       if (!wrkMastService.updateById(mast)) {
//           throw new CoolException("任务状态更新失败!!");
//       }
        workService.backLocOperation(mast.getWrkNo() + "", mast.getAppeUser());
        return R.ok("接收成功,执行回库中...");
        return workService.backLocOperation(mast.getWrkNo() + "", mast.getAppeUser());
    }
    /**
@@ -207,23 +224,25 @@
                        wrkMastService.updateById(wrkMast);
                        //出库为机台工位时,冻结相对有的库位,及相邻库位
                        String s = Utils.convertLocFormat(params.getLocNo());
                        LocAroundBind bind = locAroundBindService.selectOne(new EntityWrapper<LocAroundBind>()
                                .eq("b_loc_no", s));
                        if (!Objects.isNull(bind)&&Cools.isEmpty(wrkMast.getStaNo())) {
                            bind.setFreeze(1);
                            locAroundBindService.updateById(bind);
                            //冻结相邻库位
                            Integer[] aroundIds = freezeLocAround(bind.getOrderNo());
                            if (aroundIds != null) {
                                for (Integer id : aroundIds) {
                                    if (id != null && id > 0) {
                                        LocAroundBind aroundBind = locAroundBindService.selectOne(
                                                new EntityWrapper<LocAroundBind>()
                                                        .eq("dev_id", bind.getDevId())
                                                        .eq("order_no", id));
                                        if (aroundBind != null) {
                                            aroundBind.setFreeze(1);
                                            locAroundBindService.updateById(aroundBind);
                        if(Cools.isEmpty(wrkMast.getLocNo())){
                            LocAroundBind bind = locAroundBindService.selectOne(new EntityWrapper<LocAroundBind>()
                                    .eq("b_loc_no", s));
                            if (!Objects.isNull(bind)) {
                                bind.setFreeze(1);
                                locAroundBindService.updateById(bind);
                                //冻结相邻库位
                                Integer[] aroundIds = freezeLocAround(bind.getOrderNo());
                                if (aroundIds != null) {
                                    for (Integer id : aroundIds) {
                                        if (id != null && id > 0) {
                                            LocAroundBind aroundBind = locAroundBindService.selectOne(
                                                    new EntityWrapper<LocAroundBind>()
                                                            .eq("dev_id", bind.getDevId())
                                                            .eq("order_no", id));
                                            if (aroundBind != null) {
                                                aroundBind.setFreeze(1);
                                                locAroundBindService.updateById(aroundBind);
                                            }
                                        }
                                    }
                                }
@@ -322,10 +341,25 @@
                        LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>()
                                .eq("zpallet", mast.getBarcode())
                                .eq("loc_no", mast.getSourceLocNo()));
                        if (Objects.isNull(locDetl)) {
                        WrkDetl mainWrkDetl = null;
                        if (Objects.isNull(locDetl) && !Cools.isEmpty(mast.getWrkCode())) {
                            mainWrkDetl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>()
                                    .eq("wrk_no", mast.getWrkCode())
                                    .eq("zpallet", mast.getBarcode()));
                            if (Objects.isNull(mainWrkDetl)) {
                                mainWrkDetl = wrkDetlService.selectOne(new EntityWrapper<WrkDetl>()
                                        .eq("wrk_no", mast.getWrkCode()));
                            }
                            if (!Objects.isNull(mainWrkDetl)) {
                                log.info("locDetl为空,回退查询主任务明细,wrkNo={}, mainWrkNo={}, barcode={}",
                                        mast.getWrkNo(), mast.getWrkCode(), mast.getBarcode());
                            }
                        }
                        if (Objects.isNull(locDetl) && Objects.isNull(mainWrkDetl)) {
                            throw new CoolException("明细数据不存在!!");
                        }
                        Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", locDetl.getMatnr()));
                        String matnrNo = Objects.isNull(locDetl) ? mainWrkDetl.getMatnr() : locDetl.getMatnr();
                        Mat matnr = matService.selectOne(new EntityWrapper<Mat>().eq("matnr", matnrNo));
                        if (Objects.isNull(matnr)) {
                            throw new CoolException("物料基础信息不存在!!");
                        }
@@ -333,9 +367,15 @@
                            Double val = Math.round((weight - matnr.getSafeQty()) * 10000) / 10000.0;
                            if (val.compareTo(0.0) > 0) {
                                WrkDetl wrkDetl = new WrkDetl();
                                BeanUtils.copyProperties(locDetl, wrkDetl);
                                if (Objects.isNull(locDetl)) {
                                    BeanUtils.copyProperties(mainWrkDetl, wrkDetl);
                                    wrkDetl.setStockQty(Cools.isEmpty(mainWrkDetl.getStockQty()) ? mainWrkDetl.getAnfme() : mainWrkDetl.getStockQty());
                                    wrkDetl.setZpallet(mast.getBarcode());
                                } else {
                                    BeanUtils.copyProperties(locDetl, wrkDetl);
                                    wrkDetl.setStockQty(locDetl.getAnfme());
                                }
                                wrkDetl.setWrkNo(mast.getWrkNo());
                                wrkDetl.setStockQty(locDetl.getAnfme());
                                wrkDetl.setIoTime(new Date());
                                wrkDetl.setWeight(weight);
                                wrkDetl.setIoTime(mast.getIoTime());
@@ -401,7 +441,7 @@
                        }
                        Double realQty = Math.round((wrkDetl.getStockQty() - wrkDetl.getAnfme()) * 10000) / 10000.0;
                        if (!Cools.isEmpty(weight)) {
                            Double val = Math.round((weight - 2.35) * 10000) / 10000.0;
                            Double val = Math.round((weight - 2.5) * 10000) / 10000.0;
                            //称重后,计算出真实长度
                            realQty = val * matnr.getVolume();
                            if (realQty<matnr.getSafeQty()){
@@ -525,6 +565,142 @@
        }
        return locAround;
    }
    @Override
    public R syncDeviceStatusFromWcs() {
        if (!Boolean.parseBoolean(String.valueOf(switchValue))) {
            return R.ok("WCS开关关闭");
        }
        String response = null;
        try {
            response = requestDeviceStatusFromWcs();
            JSONObject jsonObject = JSON.parseObject(response == null ? "{}" : response);
            Integer code = jsonObject.getInteger("code");
            if (!Objects.equals(code, 200)) {
                String msg = jsonObject.getString("msg");
                return R.error(Cools.isEmpty(msg) ? "获取WCS设备状态失败" : msg);
            }
            JSONObject data = jsonObject.getJSONObject("data");
            DeviceStatusVo deviceStatusVo = data == null
                    ? new DeviceStatusVo()
                    : JSON.parseObject(data.toJSONString(), DeviceStatusVo.class);
            int stationCount = syncStationStatus(deviceStatusVo.getStationList());
            int crnCount = syncCrnStatus(deviceStatusVo.getCrnList());
            Map<String, Object> result = new LinkedHashMap<>();
            result.put("stationCount", stationCount);
            result.put("crnCount", crnCount);
            log.info("同步WCS设备状态成功, stationCount={}, crnCount={}", stationCount, crnCount);
            return R.ok("同步成功").add(result);
        } catch (Exception e) {
            log.error("同步WCS设备状态异常, response={}", response, e);
            return R.error("同步WCS设备状态失败: " + e.getMessage());
        }
    }
    private String requestDeviceStatusFromWcs() throws IOException {
        HttpHandler.Builder builder = new HttpHandler.Builder()
                .setUri(wcs_address)
                .setPath(getDeviceStatus)
                .setTimeout(10, TimeUnit.SECONDS);
        String method = Cools.isEmpty(deviceStatusMethod) ? "POST" : deviceStatusMethod.trim().toUpperCase(Locale.ROOT);
        if ("POST".equals(method)) {
            return builder.setJson("{}").build().doPost();
        }
        return builder.build().doGet();
    }
    private int syncStationStatus(List<StationProtocol> stationList) {
        if (stationList == null || stationList.isEmpty()) {
            return 0;
        }
        int count = 0;
        Date now = new Date();
        for (StationProtocol stationProtocol : stationList) {
            if (stationProtocol == null || stationProtocol.getStationId() == null) {
                continue;
            }
            BasDevp basDevp = basDevpService.selectById(stationProtocol.getStationId());
            boolean isNew = Objects.isNull(basDevp);
            if (isNew) {
                basDevp = new BasDevp();
                basDevp.setDevNo(stationProtocol.getStationId());
                basDevp.setAppeUser(WCS_SYNC_USER);
                basDevp.setAppeTime(now);
            }
            basDevp.setInEnable(toFlag(stationProtocol.isInEnable()));
            basDevp.setOutEnable(toFlag(stationProtocol.isOutEnable()));
            basDevp.setAutoing(toFlag(stationProtocol.isAutoing()));
            basDevp.setLoading(toFlag(stationProtocol.isLoading()));
            basDevp.setCanining(toFlag(stationProtocol.isEnableIn()));
            basDevp.setCanouting(toFlag(!stationProtocol.isRunBlock()));
            basDevp.setWrkNo(defaultZero(stationProtocol.getTaskNo()));
            basDevp.setBarcode(normalizeText(stationProtocol.getBarcode()));
            basDevp.setGrossWt(stationProtocol.getWeight() == null ? 0D : stationProtocol.getWeight());
            basDevp.setModiUser(WCS_SYNC_USER);
            basDevp.setModiTime(now);
            if (isNew) {
                if (!basDevpService.insert(basDevp)) {
                    throw new CoolException("新增站点状态失败, stationId=" + stationProtocol.getStationId());
                }
            } else if (!basDevpService.updateById(basDevp)) {
                throw new CoolException("更新站点状态失败, stationId=" + stationProtocol.getStationId());
            }
            count++;
        }
        return count;
    }
    private int syncCrnStatus(List<CrnProtocol> crnList) {
        if (crnList == null || crnList.isEmpty()) {
            return 0;
        }
        int count = 0;
        Date now = new Date();
        for (CrnProtocol crnProtocol : crnList) {
            if (crnProtocol == null || crnProtocol.getCrnNo() == null) {
                continue;
            }
            BasCrnp basCrnp = basCrnpService.selectById(crnProtocol.getCrnNo());
            boolean isNew = Objects.isNull(basCrnp);
            if (isNew) {
                basCrnp = new BasCrnp();
                basCrnp.setCrnNo(crnProtocol.getCrnNo());
                basCrnp.setInEnable(YES);
                basCrnp.setOutEnable(YES);
                basCrnp.setAppeUser(WCS_SYNC_USER);
                basCrnp.setAppeTime(now);
            }
            // crn_sts 本地表存的是“堆垛机模式(手动/自动/电脑)”,因此必须写 mode,不能写 status。
            basCrnp.setCrnSts(defaultZero(crnProtocol.getMode()));
            basCrnp.setWrkNo(defaultZero(crnProtocol.getTaskNo()));
            basCrnp.setCrnErr(crnProtocol.getAlarm() == null ? 0L : Long.valueOf(crnProtocol.getAlarm()));
            basCrnp.setModiUser(WCS_SYNC_USER);
            basCrnp.setModiTime(now);
            if (isNew) {
                if (!basCrnpService.insert(basCrnp)) {
                    throw new CoolException("新增堆垛机状态失败, crnNo=" + crnProtocol.getCrnNo());
                }
            } else if (!basCrnpService.updateById(basCrnp)) {
                throw new CoolException("更新堆垛机状态失败, crnNo=" + crnProtocol.getCrnNo());
            }
            count++;
        }
        return count;
    }
    private Integer defaultZero(Integer value) {
        return value == null ? 0 : value;
    }
    private String normalizeText(String value) {
        return Cools.isEmpty(value) ? "" : value;
    }
    private String toFlag(boolean value) {
        return value ? YES : NO;
    }
}