| | |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.fasterxml.jackson.databind.node.ArrayNode; |
| | | import com.fasterxml.jackson.databind.node.ObjectNode; |
| | | import com.vincent.rsf.openApi.feign.wms.WmsServerFeignClient; |
| | | import com.vincent.rsf.openApi.service.RcsTvCallbackService; |
| | | import com.vincent.rsf.openApi.service.WcsStationStatusService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.client.RestClientException; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * 调用 RCS 站点接口,结果写入电视机 Redis,由 zy-monitor-admin WebSocket 推送到电视机 |
| | | * 定时:GET RCS /station/getTaskNo;POST RCS /station/getError;任务号存在时调 WMS queryTask 合并料箱与物料明细进 Redis |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | |
| | | private RcsTvCallbackService rcsTvCallbackService; |
| | | @Resource |
| | | private TvRcsStationPollProperties pollProperties; |
| | | @Resource |
| | | private WcsStationStatusService wcsStationStatusService; |
| | | @Resource |
| | | private WmsServerFeignClient wmsServerFeignClient; |
| | | |
| | | public void pollOnce() { |
| | | String stationId = pollProperties.getTaskNoStationId(); |
| | | if (StringUtils.hasText(pollProperties.getTaskNoPollUrl())) { |
| | | try { |
| | | String raw = restTemplate.getForObject(pollProperties.getTaskNoPollUrl(), String.class); |
| | | applyTaskNoResponse(raw, pollProperties.getTaskNoStationId()); |
| | | String taskNo = applyTaskNoResponse(raw, stationId); |
| | | enrichSnapshotFromWms(stationId, taskNo); |
| | | } catch (RestClientException e) { |
| | | log.warn("RCS 任务号轮询 HTTP 失败: {}", e.getMessage()); |
| | | } catch (Exception e) { |
| | |
| | | } |
| | | if (StringUtils.hasText(pollProperties.getErrorPollUrl())) { |
| | | try { |
| | | String raw = restTemplate.getForObject(pollProperties.getErrorPollUrl(), String.class); |
| | | String raw = pollErrorRaw(); |
| | | applyErrorResponse(raw, pollProperties.getErrorStationId()); |
| | | } catch (RestClientException e) { |
| | | log.warn("RCS 异常轮询 HTTP 失败: {}", e.getMessage()); |
| | |
| | | } |
| | | } |
| | | |
| | | private void applyTaskNoResponse(String raw, String staNo) { |
| | | if (!StringUtils.hasText(staNo)) { |
| | | private void enrichSnapshotFromWms(String stationId, String taskNo) { |
| | | if (!pollProperties.isEnrichTaskFromWms()) { |
| | | return; |
| | | } |
| | | if (!StringUtils.hasText(stationId)) { |
| | | return; |
| | | } |
| | | if (!StringUtils.hasText(taskNo) || "0".equals(taskNo.trim())) { |
| | | wcsStationStatusService.clearStationSnapshot(stationId); |
| | | return; |
| | | } |
| | | Map<String, Object> req = new HashMap<>(); |
| | | req.put("taskNo", taskNo); |
| | | try { |
| | | Map<String, Object> res = wmsServerFeignClient.openAsrsQueryTask(req); |
| | | if (res == null) { |
| | | wcsStationStatusService.upsertFromRcsPoll(stationId, taskNo, null); |
| | | return; |
| | | } |
| | | Object codeObj = res.get("code"); |
| | | int code = parseCode(codeObj); |
| | | if (code != 200) { |
| | | log.debug("WMS queryTask 非成功 code={} msg={}", code, res.get("msg")); |
| | | wcsStationStatusService.upsertFromRcsPoll(stationId, taskNo, null); |
| | | return; |
| | | } |
| | | Object data = res.get("data"); |
| | | @SuppressWarnings("unchecked") |
| | | Map<String, Object> dataMap = data instanceof Map ? (Map<String, Object>) data : null; |
| | | wcsStationStatusService.upsertFromRcsPoll(stationId, taskNo, dataMap); |
| | | } catch (Exception e) { |
| | | log.warn("WMS queryTask 调用失败: {}", e.getMessage()); |
| | | wcsStationStatusService.upsertFromRcsPoll(stationId, taskNo, null); |
| | | } |
| | | } |
| | | |
| | | private static int parseCode(Object codeObj) { |
| | | if (codeObj == null) { |
| | | return 0; |
| | | } |
| | | if (codeObj instanceof Number) { |
| | | return ((Number) codeObj).intValue(); |
| | | } |
| | | try { |
| | | return Integer.parseInt(String.valueOf(codeObj)); |
| | | } catch (Exception e) { |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private String pollErrorRaw() throws Exception { |
| | | if (pollProperties.isErrorPollUsePost()) { |
| | | ObjectNode body = objectMapper.createObjectNode(); |
| | | body.put("staNo", pollProperties.getErrorStationId()); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.setContentType(MediaType.APPLICATION_JSON); |
| | | HttpEntity<String> entity = new HttpEntity<>(objectMapper.writeValueAsString(body), headers); |
| | | ResponseEntity<String> resp = restTemplate.exchange( |
| | | pollProperties.getErrorPollUrl(), HttpMethod.POST, entity, String.class); |
| | | return resp.getBody(); |
| | | } |
| | | return restTemplate.getForObject(pollProperties.getErrorPollUrl(), String.class); |
| | | } |
| | | |
| | | /** 写入 tvRcs 任务号 Hash;返回解析出的 taskNo(用于 WMS 合并) */ |
| | | private String applyTaskNoResponse(String raw, String staNo) { |
| | | if (!StringUtils.hasText(staNo)) { |
| | | return null; |
| | | } |
| | | if (!StringUtils.hasText(raw)) { |
| | | rcsTvCallbackService.writeStationTaskNo(staNo, null); |
| | | return; |
| | | return null; |
| | | } |
| | | String trimmed = raw.trim(); |
| | | try { |
| | | JsonNode root = objectMapper.readTree(trimmed); |
| | | if (!httpSuccess(root)) { |
| | | rcsTvCallbackService.writeStationTaskNo(staNo, null); |
| | | return null; |
| | | } |
| | | String taskNo = extractTaskNo(root); |
| | | rcsTvCallbackService.writeStationTaskNo(staNo, taskNo); |
| | | return taskNo; |
| | | } catch (Exception e) { |
| | | rcsTvCallbackService.writeStationTaskNo(staNo, trimmed); |
| | | return trimmed; |
| | | } |
| | | } |
| | | |
| | | private static boolean httpSuccess(JsonNode root) { |
| | | if (root == null || !root.isObject()) { |
| | | return true; |
| | | } |
| | | JsonNode c = root.get("code"); |
| | | if (c == null || c.isNull()) { |
| | | return true; |
| | | } |
| | | return c.asInt(200) == 200; |
| | | } |
| | | |
| | | private static String extractTaskNo(JsonNode root) { |
| | |
| | | rcsTvCallbackService.handleStationError(body); |
| | | } |
| | | |
| | | /** |
| | | * 归一成 {@link com.vincent.rsf.openApi.service.RcsTvCallbackService#handleStationError} 可识别的 data 数组 |
| | | */ |
| | | private JsonNode buildErrorCallbackBody(String raw, String defaultStaNo) throws Exception { |
| | | if (!StringUtils.hasText(raw)) { |
| | | return objectMapper.createArrayNode(); |
| | | } |
| | | String trimmed = raw.trim(); |
| | | JsonNode root = objectMapper.readTree(trimmed); |
| | | if (!httpSuccess(root)) { |
| | | return objectMapper.createArrayNode(); |
| | | } |
| | | if (root.isArray()) { |
| | | return fillStaNo((ArrayNode) root, defaultStaNo); |
| | | } |