package com.zy.asrs.service.impl; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.core.common.Cools; import com.zy.asrs.entity.BasCrnp; import com.zy.asrs.entity.dto.WcsCrnDto; import com.zy.asrs.entity.dto.WcsCrnSyncResult; import com.zy.asrs.enums.CrnModeType; import com.zy.asrs.enums.CrnStatusType; import com.zy.asrs.service.BasCrnpService; import com.zy.asrs.service.WcsCrnSyncService; import com.zy.asrs.utils.CrnUtils; import com.zy.common.utils.HttpHandler; import com.zy.system.entity.Config; import com.zy.system.service.ConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; @Slf4j @Service("wcsCrnSyncService") public class WcsCrnSyncServiceImpl implements WcsCrnSyncService { private static final String WCS_DEVICE_STATUS_URL_CODE = "wcsDeviceStatusUrl"; @Autowired private ConfigService configService; @Autowired private BasCrnpService basCrnpService; @Autowired private CrnUtils crnUtils; @Override public synchronized WcsCrnSyncResult sync() { WcsCrnSyncResult result = new WcsCrnSyncResult(); String now = nowText(); List basCrnps = basCrnpService.list(new QueryWrapper() .eq("status", 1) .orderBy(true, true, "crn_no")); Set enabledCrnNos = new HashSet<>(); for (BasCrnp basCrnp : basCrnps) { if (basCrnp != null && basCrnp.getCrnNo() != null) { enabledCrnNos.add(basCrnp.getCrnNo()); } } crnUtils.crnMap.keySet().removeIf(crnNo -> !enabledCrnNos.contains(crnNo)); result.setRequestCount(enabledCrnNos.size()); if (enabledCrnNos.isEmpty()) { crnUtils.setLastSyncTime(now); crnUtils.setLastSyncError(null); result.setSuccess(true); result.setMessage("暂无启用的堆垛机配置"); result.setLastSyncTime(now); return result; } Config config = configService.getOne(new QueryWrapper().eq("code", WCS_DEVICE_STATUS_URL_CODE)); String deviceStatusUrl = config == null ? null : config.getValue(); if (Cools.isEmpty(deviceStatusUrl)) { return markSyncError(enabledCrnNos, now, result, "未配置WCS堆垛机状态接口地址"); } HashMap requestParam = new HashMap<>(); requestParam.put("crnNos", new ArrayList<>(enabledCrnNos)); String response; try { response = new HttpHandler.Builder() .setUri(deviceStatusUrl) // .setHttps(deviceStatusUrl.startsWith("https://")) .setJson(JSON.toJSONString(requestParam)) .setTimeout(30, TimeUnit.SECONDS) .build() .doPost(); } catch (Exception e) { log.error("同步堆垛机状态失败", e); return markSyncError(enabledCrnNos, now, result, "调用WCS接口失败: " + e.getMessage()); } if (Cools.isEmpty(response)) { return markSyncError(enabledCrnNos, now, result, "WCS接口无响应"); } JSONObject responseObj; try { responseObj = JSON.parseObject(response); } catch (Exception e) { log.error("解析堆垛机状态响应失败: {}", response, e); return markSyncError(enabledCrnNos, now, result, "WCS接口响应解析失败"); } if (responseObj == null) { return markSyncError(enabledCrnNos, now, result, "WCS接口响应为空"); } if (responseObj.getInteger("code") == null || responseObj.getInteger("code") != 200) { return markSyncError(enabledCrnNos, now, result, Cools.isEmpty(responseObj.getString("msg")) ? "WCS接口返回失败" : responseObj.getString("msg")); } JSONObject dataObj = responseObj.getJSONObject("data"); JSONArray crnList = dataObj == null ? null : dataObj.getJSONArray("crnList"); Set returnedCrnNos = new HashSet<>(); int updateCount = 0; if (crnList != null) { for (Object item : crnList) { if (!(item instanceof JSONObject)) { continue; } JSONObject crnObj = (JSONObject) item; Integer crnNo = crnObj.getInteger("crnNo"); if (crnNo == null || !enabledCrnNos.contains(crnNo)) { continue; } returnedCrnNos.add(crnNo); crnUtils.crnMap.put(crnNo, buildOnlineDto(crnObj, now)); updateCount++; } } for (Integer crnNo : enabledCrnNos) { if (returnedCrnNos.contains(crnNo)) { continue; } crnUtils.crnMap.put(crnNo, buildOfflineDto(crnNo, now, null)); } crnUtils.setLastSyncTime(now); crnUtils.setLastSyncError(null); result.setSuccess(true); result.setMessage("同步成功"); result.setUpdateCount(updateCount); result.setLastSyncTime(now); return result; } private WcsCrnSyncResult markSyncError(Set configuredCrnNos, String now, WcsCrnSyncResult result, String error) { crnUtils.setLastSyncTime(now); crnUtils.setLastSyncError(error); for (Integer crnNo : configuredCrnNos) { WcsCrnDto current = crnUtils.crnMap.get(crnNo); if (current == null) { current = buildOfflineDto(crnNo, now, error); } else { current.setLastSyncTime(now); current.setSyncError(error); } crnUtils.crnMap.put(crnNo, current); } result.setSuccess(false); result.setMessage(error); result.setLastSyncTime(now); return result; } private WcsCrnDto buildOnlineDto(JSONObject crnObj, String now) { WcsCrnDto dto = new WcsCrnDto(); Integer mode = crnObj.getInteger("mode"); Integer status = crnObj.getInteger("status"); dto.setCrnNo(crnObj.getInteger("crnNo")); dto.setOnline(1); dto.setMode(mode); dto.setModeDesc(CrnModeType.get(mode).desc); dto.setStatus(status); dto.setStatusDesc(CrnStatusType.get(status).desc); dto.setTaskNo(crnObj.getInteger("taskNo")); dto.setAlarm(crnObj.getInteger("alarm")); dto.setLastSyncTime(now); dto.setSyncError(null); return dto; } private WcsCrnDto buildOfflineDto(Integer crnNo, String now, String syncError) { WcsCrnDto dto = new WcsCrnDto(); dto.setCrnNo(crnNo); dto.setOnline(0); dto.setMode(null); dto.setModeDesc("离线"); dto.setStatus(null); dto.setStatusDesc("离线"); dto.setTaskNo(null); dto.setAlarm(null); dto.setLastSyncTime(now); dto.setSyncError(syncError); return dto; } private String nowText() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); } }