chen.lin
昨天 8f8b6a47ce277cad0b640c328ab3962419e1c024
rsf-open-api/src/main/java/com/vincent/rsf/openApi/service/impl/WmsRcsServiceImpl.java
@@ -11,11 +11,17 @@
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.openApi.config.PlatformProperties;
import com.vincent.rsf.openApi.entity.Loc;
import com.vincent.rsf.openApi.entity.constant.WmsConstant;
import com.vincent.rsf.openApi.entity.dto.CommonResponse;
import com.vincent.rsf.openApi.entity.constant.RcsConstant;
import com.vincent.rsf.openApi.entity.dto.SyncLocsDto;
import com.vincent.rsf.openApi.entity.dto.LocationAllocateResponse;
import com.vincent.rsf.openApi.entity.params.ExMsgCallbackParams;
import com.vincent.rsf.openApi.entity.params.LocSiteParams;
import com.vincent.rsf.openApi.entity.params.LocationAllocateParams;
import com.vincent.rsf.openApi.entity.params.RcsPubTaskParams;
import com.vincent.rsf.openApi.entity.params.SyncRcsLocsParam;
import com.vincent.rsf.openApi.entity.params.TaskReportParams;
import com.vincent.rsf.openApi.mapper.LocMapper;
import com.vincent.rsf.openApi.service.WmsRcsService;
import lombok.extern.slf4j.Slf4j;
@@ -39,9 +45,11 @@
    @Autowired
    private PlatformProperties rcsApi;
    @Autowired
    private PlatformProperties.WmsApi wmsApi;
    @Autowired
    private RestTemplate restTemplate;
    /**
@@ -52,31 +60,60 @@
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R pubTasks(RcsPubTaskParams params)  {
    public CommonResponse pubTasks(RcsPubTaskParams params)  {
        /**RCS基础配置链接*/
        String rcsUrl =  rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.pubTask;
        log.info("任务下发,请求地址: {}, 请求参数: {}", rcsUrl , JSONObject.toJSONString(params));
        log.info("========== 开始下发任务到RCS ==========");
        log.info("RCS请求地址:{}", rcsUrl);
        if (params != null) {
            log.info("批次编号:{}", params.getBatchNo());
            if (params.getTasks() != null) {
                log.info("任务数量:{}", params.getTasks().size());
            }
        }
        log.info("请求参数:{}", JSONObject.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        HttpEntity httpEntity = new HttpEntity(params, headers);
        long startTime = System.currentTimeMillis();
        ResponseEntity<String> exchange = restTemplate.exchange(rcsUrl, HttpMethod.POST, httpEntity, String.class);
        log.info("任务下发后,响应结果: {}", exchange);
        long endTime = System.currentTimeMillis();
        log.info("RCS响应耗时:{}ms", (endTime - startTime));
        log.info("RCS响应状态码:{}", exchange.getStatusCode());
        log.info("RCS响应头:{}", exchange.getHeaders());
        log.info("RCS响应体:{}", exchange.getBody());
        if (Objects.isNull(exchange.getBody())) {
            throw new CoolException("任务下发失败!!");
            log.error("========== RCS任务下发失败 ==========");
            log.error("RCS响应体为空,无法解析响应结果");
            log.error("请求地址:{}", rcsUrl);
            log.error("请求参数:{}", JSONObject.toJSONString(params));
            throw new CoolException("任务下发失败,RCS响应体为空!!");
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                log.info("RCS响应解析结果 - code:{},msg:{},data:{}",
                        result.getCode(), result.getMsg(), result.getData());
                if (result.getCode() == 200) {
                    return R.ok();
                    log.info("========== RCS任务下发成功 ==========");
                    return result;
                } else {
                    throw new CoolException("任务下发失败!!");
                    log.error("========== RCS任务下发失败 ==========");
                    log.error("RCS返回错误 - code:{},msg:{},data:{}",
                            result.getCode(), result.getMsg(), result.getData());
                    return result;
                }
            } catch (JsonProcessingException e) {
                throw new CoolException(e.getMessage());
                log.error("========== RCS任务下发异常 ==========");
                log.error("解析RCS响应失败,响应体:{}", exchange.getBody(), e);
                throw new CoolException("解析RCS响应失败:" + e.getMessage());
            } catch (Exception e) {
                log.error("========== RCS任务下发异常 ==========");
                log.error("任务下发过程中发生异常", e);
                throw e;
            }
        }
    }
@@ -88,8 +125,66 @@
     * @version 1.0
     */
    @Override
    public R cancelTasks(Map<String, Object> params) {
        return  R.ok();
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse cancelTasks(Map<String, Object> params) {
        /**RCS基础配置链接*/
        String rcsUrl = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.cancelTask;
        log.info("========== 开始取消RCS任务(open-rcs接口) ==========");
        log.info("RCS取消任务请求地址:{}", rcsUrl);
        log.info("RCS取消任务请求参数:{}", JSONObject.toJSONString(params));
        // 打印详细的请求参数信息
        if (params != null) {
            Object batchNo = params.get("batchNo");
            Object tasks = params.get("tasks");
            if (batchNo != null) {
                log.info("批次编号:{}", batchNo);
            }
            if (tasks != null) {
                if (tasks instanceof List) {
                    log.info("任务数量:{}", ((List<?>) tasks).size());
                    log.info("任务编号列表:{}", tasks);
                } else {
                    log.info("任务参数:{}", tasks);
                }
            }
        }
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        HttpEntity httpEntity = new HttpEntity(params, headers);
        long startTime = System.currentTimeMillis();
        ResponseEntity<String> exchange = restTemplate.exchange(rcsUrl, HttpMethod.POST, httpEntity, String.class);
        long endTime = System.currentTimeMillis();
        log.info("RCS取消任务响应耗时:{}ms", (endTime - startTime));
        log.info("RCS取消任务响应状态码:{}", exchange.getStatusCode());
        log.info("RCS取消任务响应头:{}", exchange.getHeaders());
        log.info("RCS取消任务响应体:{}", exchange.getBody());
        if (Objects.isNull(exchange.getBody())) {
            throw new CoolException("取消任务失败!!");
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                if (result.getCode() == 200) {
                    log.info("========== RCS任务取消成功(open-rcs接口) ==========");
                    log.info("成功取消的任务编号:{}", params.get("tasks"));
                    return result;
                } else {
                    log.error("========== RCS任务取消失败(open-rcs接口) ==========");
                    log.error("RCS返回错误码:{},错误信息:{}", result.getCode(), result.getMsg());
                    throw new CoolException("取消任务失败!!" + (result.getMsg() != null ? ":" + result.getMsg() : ""));
                }
            } catch (JsonProcessingException e) {
                log.error("RCS取消任务响应解析失败:{}", e.getMessage(), e);
                throw new CoolException("RCS取消任务响应解析失败:" + e.getMessage());
            }
        }
    }
    /**
@@ -99,8 +194,52 @@
     * @version 1.0
     */
    @Override
    public R callBackEvent(Map<String, Object> params) {
        return R.ok();
    public CommonResponse callBackEvent(ExMsgCallbackParams params) {
        // 参数校验
        if (Objects.isNull(params)) {
            log.error("RCS回调事件参数为空!");
            throw new CoolException("参数不能为空!!");
        }
        // 详细记录接收到的参数
        log.info("RCS回调事件接收参数 - seqNum: {}, eventType: {}, robotCode: {}, zpallet: {}",
                params.getSeqNum(), params.getEventType(), params.getRobotCode(), params.getZpallet());
        // 检查关键字段是否为空
        if (Objects.isNull(params.getSeqNum()) || params.getSeqNum().isEmpty()) {
            log.warn("RCS回调事件参数seqNum为空!完整参数:{}", JSONObject.toJSONString(params));
        }
        if (Objects.isNull(params.getEventType()) || params.getEventType().isEmpty()) {
            log.warn("RCS回调事件参数eventType为空!完整参数:{}", JSONObject.toJSONString(params));
        }
        String callUrl =  wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.callBack;
        /**WMS基础配置链接*/
        log.info("任务执行状态上报,请求地址: {}, 请求参数: {}", callUrl , JSONObject.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        HttpEntity httpEntity = new HttpEntity(params, headers);
        ResponseEntity<String> exchange = restTemplate.exchange(callUrl, HttpMethod.POST, httpEntity, String.class);
        log.info("任务执行状态上报,响应结果: {}", exchange);
        if (Objects.isNull(exchange.getBody())) {
            return new CommonResponse();
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                if (result.getCode() == 200) {
                    return result;
                } else {
                    return result;
//                    throw new CoolException("任务执行状态上报失败!!");
                }
            } catch (JsonProcessingException e) {
                throw new CoolException(e.getMessage());
            }
        }
    }
    /**
@@ -114,6 +253,43 @@
         return syncRcsLocs(params);
    }
    /**
     * @author Ryan
     * @date 2025/11/10
     * @description: 修改库位或站点状态
     * @version 1.0
     */
    @Override
    public R modifyLocOrSite(LocSiteParams params) {
        /**RCS基础配置链接*/
        String rcsUrl =  rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.modifystatus;
        log.info("库位或站点状态修改,请求地址: {}, 请求参数: {}", rcsUrl , JSONObject.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        HttpEntity httpEntity = new HttpEntity(params, headers);
        ResponseEntity<String> exchange = restTemplate.exchange(rcsUrl, HttpMethod.POST, httpEntity, String.class);
        log.info("库位或站点状态修改,响应结果: {}", exchange);
        if (Objects.isNull(exchange.getBody())) {
            throw new CoolException("状态修改失败!!");
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                if (result.getCode() == 200) {
                    return R.ok();
                } else {
                    throw new CoolException("状态修改失败!!");
                }
            } catch (JsonProcessingException e) {
                throw new CoolException(e.getMessage());
            }
        }
    }
    /**
     * @author Ryan
     * @date 2025/8/28
@@ -124,7 +300,7 @@
    public List<SyncLocsDto> syncRcsLocs(SyncRcsLocsParam  params) {
        /**RCS基础配置链接*/
        String rcsUrl =  rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.syncLocs;
        log.info("任务下发,请求地址: {}, 请求参数: {}", rcsUrl , JSONObject.toJSONString(params));
        log.info("任务下发,请求地址2: {}, 请求参数: {}", rcsUrl , JSONObject.toJSONString(params));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
@@ -152,4 +328,154 @@
            }
        }
    }
    /**
     * @author Ryan
     * @date 2026/2/3
     * @description: 任务执行通知上报(RCS回调接口)
     * @version 1.0
     */
    @Override
    public CommonResponse reportTask(TaskReportParams params) {
        log.info("RCS回调,请求参数: {}", JSONObject.toJSONString(params));
        // 参数校验
        if (Objects.isNull(params)) {
            throw new CoolException("参数不能为空!!");
        }
        if (Objects.isNull(params.getBatchNo()) || params.getBatchNo().isEmpty()) {
            throw new CoolException("任务批次不能为空!!");
        }
        if (Objects.isNull(params.getTaskNo()) || params.getTaskNo().isEmpty()) {
            throw new CoolException("任务编号不能为空!!");
        }
        if (Objects.isNull(params.getTimestamp()) || params.getTimestamp().isEmpty()) {
            throw new CoolException("时间戳不能为空!!");
        }
        // 将TaskReportParams转换为ExMsgParams格式(taskNo -> seqNum)
        // 根据RCS新接口规范,taskNo对应旧接口的seqNum
        JSONObject exMsgParams = new JSONObject();
        exMsgParams.put("seqNum", params.getTaskNo()); // taskNo映射到seqNum
        // eventType设置为END,表示任务完成(根据业务需求可能需要调整)
        exMsgParams.put("eventType", "END");
        exMsgParams.put("robotCode", null);
        exMsgParams.put("zpallet", null);
        // 将任务上报回调转发到WMS系统
        String callUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + WmsConstant.callBack;
        log.info("RCS回调-WMS-SERVER任务上报-,请求地址: {}, 转换后参数: {}", callUrl, exMsgParams.toJSONString());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("api-version", "v2.0");
        HttpEntity httpEntity = new HttpEntity(exMsgParams, headers);
        ResponseEntity<String> exchange = restTemplate.exchange(callUrl, HttpMethod.POST, httpEntity, String.class);
        log.info("RCS回调-WMS-SERVER任务上报-,响应结果: {}", exchange);
        if (Objects.isNull(exchange.getBody())) {
            // 回调失败,抛出异常
            log.error("========== RCS回调-WMS-SERVER任务上报-失败 ==========");
            log.error("RCS回调-WMS-SERVER任务上报-响应体为空,无法解析响应结果");
            log.error("RCS回调-WMS-SERVER任务上报-请求地址:{}", callUrl);
            log.error("RCS回调-WMS-SERVER任务上报-请求参数:{}", exMsgParams.toJSONString());
            log.error("RCS回调-WMS-SERVER任务上报-失败的任务编号:{},批次:{}", params.getTaskNo(), params.getBatchNo());
            throw new CoolException("RCS回调-WMS-SERVER任务上报-失败,WMS响应体为空!任务编号:" + params.getTaskNo() + ",批次:" + params.getBatchNo());
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class);
                if (result.getCode() == 200) {
                    log.info("RCS回调-WMS-SERVER任务上报-成功,任务编号:{},批次:{}", params.getTaskNo(), params.getBatchNo());
                    return result;
                } else {
                    log.warn("RCS回调-WMS-SERVER任务上报-返回非200状态,任务编号:{},批次:{},响应:{}", params.getTaskNo(), params.getBatchNo(), exchange.getBody());
                    return result;
                }
            } catch (JsonProcessingException e) {
                log.error("RCS回调-WMS-SERVER任务上报-响应解析失败,任务编号:{},批次:{},错误:{}", params.getTaskNo(), params.getBatchNo(), e.getMessage());
                // 解析失败时返回成功响应,避免RCS重复回调
                CommonResponse response = new CommonResponse();
                response.setCode(200);
                response.setMsg("接收成功");
                return response;
            }
        }
    }
    /**
     * @author Ryan
     * @date 2026/2/6
     * @description: 申请入库任务,分配库位
     * @version 1.0
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R allocateLocation(LocationAllocateParams params) {
        log.info("========== 开始申请入库任务,分配库位 ==========");
        log.info("料箱码:{},入库站点:{},入库类型:{}", params.getBarcode(), params.getStaNo(), params.getType());
        // 调用WMS server内部接口进行库位分配
        String wmsUrl = wmsApi.getHost() + ":" + wmsApi.getPort() + "/rsf-server/wcs/allocate/location";
        log.info("WMS请求地址:{}", wmsUrl);
        // 构建请求参数
        JSONObject requestParams = new JSONObject();
        requestParams.put("barcode", params.getBarcode());
        requestParams.put("staNo", params.getStaNo());
        requestParams.put("type", params.getType());
        log.info("请求参数:{}", requestParams.toJSONString());
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        HttpEntity httpEntity = new HttpEntity(requestParams, headers);
        long startTime = System.currentTimeMillis();
        ResponseEntity<String> exchange = restTemplate.exchange(wmsUrl, HttpMethod.POST, httpEntity, String.class);
        long endTime = System.currentTimeMillis();
        log.info("WMS响应耗时:{}ms", (endTime - startTime));
        log.info("WMS响应状态码:{}", exchange.getStatusCode());
        log.info("WMS响应体:{}", exchange.getBody());
        if (Objects.isNull(exchange.getBody())) {
            log.error("========== 申请入库任务失败 ==========");
            log.error("WMS响应体为空,无法解析响应结果");
            return R.error("申请入库任务失败,WMS响应体为空!!");
        } else {
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.coercionConfigDefaults()
                    .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
            try {
                JSONObject responseJson = JSONObject.parseObject(exchange.getBody());
                Integer code = responseJson.getInteger("code");
                String msg = responseJson.getString("msg");
                if (code != null && code == 200) {
                    JSONObject data = responseJson.getJSONObject("data");
                    if (data != null) {
                        String locNo = data.getString("locNo");
                        log.info("========== 申请入库任务成功 ==========");
                        log.info("分配库位号:{}", locNo);
                        LocationAllocateResponse response = new LocationAllocateResponse();
                        response.setLocNo(locNo);
                        return R.ok(response);
                    } else {
                        log.error("========== 申请入库任务失败 ==========");
                        log.error("响应数据为空");
                        return R.error("申请入库任务失败,响应数据为空!!");
                    }
                } else {
                    log.error("========== 申请入库任务失败 ==========");
                    log.error("WMS返回错误 - code:{},msg:{}", code, msg);
                    return R.error(msg != null ? msg : "申请入库任务失败!!");
                }
            } catch (Exception e) {
                log.error("========== 申请入库任务异常 ==========");
                log.error("解析WMS响应失败,响应体:{}", exchange.getBody(), e);
                return R.error("解析WMS响应失败:" + e.getMessage());
            }
        }
    }
}