package com.vincent.rsf.openApi.tv;
|
|
import com.fasterxml.jackson.databind.JsonNode;
|
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;
|
|
/**
|
* 定时:GET RCS /station/getTaskNo;POST RCS /station/getError;任务号存在时调 WMS queryTask 合并料箱与物料明细进 Redis
|
*/
|
@Slf4j
|
@Service
|
public class TvRcsStationPollService {
|
|
@Resource
|
private RestTemplate restTemplate;
|
@Resource
|
private ObjectMapper objectMapper;
|
@Resource
|
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);
|
String taskNo = applyTaskNoResponse(raw, stationId);
|
enrichSnapshotFromWms(stationId, taskNo);
|
} catch (RestClientException e) {
|
log.warn("RCS 任务号轮询 HTTP 失败: {}", e.getMessage());
|
} catch (Exception e) {
|
log.warn("RCS 任务号轮询处理失败", e);
|
}
|
}
|
if (StringUtils.hasText(pollProperties.getErrorPollUrl())) {
|
try {
|
String raw = pollErrorRaw();
|
applyErrorResponse(raw, pollProperties.getErrorStationId());
|
} catch (RestClientException e) {
|
log.warn("RCS 异常轮询 HTTP 失败: {}", e.getMessage());
|
} catch (Exception e) {
|
log.warn("RCS 异常轮询处理失败", e);
|
}
|
}
|
}
|
|
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 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) {
|
if (root == null || root.isNull()) {
|
return null;
|
}
|
if (root.isValueNode()) {
|
return textNode(root);
|
}
|
String[] paths = {"taskNo", "task_no", "taskCode", "seqNum"};
|
for (String p : paths) {
|
JsonNode n = root.get(p);
|
if (n != null && !n.isNull() && StringUtils.hasText(textNode(n))) {
|
return textNode(n);
|
}
|
}
|
JsonNode data = root.get("data");
|
if (data != null && !data.isNull()) {
|
if (data.isObject()) {
|
for (String p : paths) {
|
JsonNode n = data.get(p);
|
if (n != null && !n.isNull() && StringUtils.hasText(textNode(n))) {
|
return textNode(n);
|
}
|
}
|
} else if (data.isValueNode()) {
|
return textNode(data);
|
}
|
}
|
JsonNode result = root.get("result");
|
if (result != null && result.isObject()) {
|
for (String p : paths) {
|
JsonNode n = result.get(p);
|
if (n != null && !n.isNull() && StringUtils.hasText(textNode(n))) {
|
return textNode(n);
|
}
|
}
|
}
|
return null;
|
}
|
|
private static String textNode(JsonNode n) {
|
if (n == null || n.isNull()) {
|
return "";
|
}
|
String s = n.asText("");
|
return s == null ? "" : s.trim();
|
}
|
|
private void applyErrorResponse(String raw, String defaultStaNo) throws Exception {
|
JsonNode body = buildErrorCallbackBody(raw, defaultStaNo);
|
rcsTvCallbackService.handleStationError(body);
|
}
|
|
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);
|
}
|
if (root.isObject()) {
|
if (root.has("data") && root.get("data").isArray()) {
|
ObjectNode o = objectMapper.createObjectNode();
|
o.set("data", fillStaNo((ArrayNode) root.get("data"), defaultStaNo));
|
return o;
|
}
|
if (root.has("errors") && root.get("errors").isArray()) {
|
ObjectNode o = objectMapper.createObjectNode();
|
o.set("data", fillStaNo((ArrayNode) root.get("errors"), defaultStaNo));
|
return o;
|
}
|
String msg = firstMessageField(root);
|
if (StringUtils.hasText(msg)) {
|
return wrapSingleError(defaultStaNo, msg);
|
}
|
JsonNode data = root.get("data");
|
if (data != null && data.isTextual()) {
|
return wrapSingleError(defaultStaNo, data.asText());
|
}
|
}
|
return wrapSingleError(defaultStaNo, trimmed);
|
}
|
|
private JsonNode wrapSingleError(String staNo, String msg) {
|
ArrayNode arr = objectMapper.createArrayNode();
|
ObjectNode item = objectMapper.createObjectNode();
|
if (StringUtils.hasText(staNo)) {
|
item.put("staNo", staNo);
|
}
|
item.put("error", msg);
|
arr.add(item);
|
ObjectNode body = objectMapper.createObjectNode();
|
body.set("data", arr);
|
return body;
|
}
|
|
private static String firstMessageField(JsonNode o) {
|
String[] keys = {"errorMsg", "message", "msg", "error", "plcDesc", "desc"};
|
for (String k : keys) {
|
JsonNode n = o.get(k);
|
if (n != null && !n.isNull() && StringUtils.hasText(n.asText("").trim())) {
|
return n.asText("").trim();
|
}
|
}
|
return "";
|
}
|
|
private ArrayNode fillStaNo(ArrayNode arr, String defaultStaNo) {
|
for (int i = 0; i < arr.size(); i++) {
|
JsonNode el = arr.get(i);
|
if (!el.isObject()) {
|
continue;
|
}
|
ObjectNode obj = (ObjectNode) el;
|
if (!StringUtils.hasText(textNode(obj.get("staNo"))) && StringUtils.hasText(defaultStaNo)) {
|
obj.put("staNo", defaultStaNo);
|
}
|
}
|
return arr;
|
}
|
}
|