package com.vincent.rsf.openApi.service; import com.fasterxml.jackson.databind.JsonNode; import com.vincent.rsf.openApi.tv.TvMonitorRedisKeys; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import javax.annotation.Resource; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * RCS 推送:写入与电视机后台相同的 Redis 格式(不修改 zy-monitor-admin / 电视机) */ @Slf4j @Service public class RcsTvCallbackService { @Resource @Qualifier("tvMonitorStringRedisTemplate") private StringRedisTemplate tvMonitorStringRedisTemplate; @Value("${tv-monitor.rcs-callback-token:}") private String rcsCallbackToken; public void assertToken(String headerToken) { if (!StringUtils.hasText(rcsCallbackToken)) { return; } if (!rcsCallbackToken.equals(headerToken)) { throw new IllegalArgumentException("X-Rcs-Token 无效"); } } /** * 解析输送线异常列表,写入 {@link TvMonitorRedisKeys#TV_MANUAL_ERROR_MSG}(分号拼接,与推送端 join 风格一致) */ public Map handleStationError(JsonNode body) { if (body != null && body.isObject() && body.has("clear") && body.get("clear").asBoolean(false)) { tvMonitorStringRedisTemplate.delete(TvMonitorRedisKeys.TV_MANUAL_ERROR_MSG); return rcsOk(null); } JsonNode arr = resolveErrorArray(body); if (arr == null || !arr.isArray() || arr.size() == 0) { tvMonitorStringRedisTemplate.delete(TvMonitorRedisKeys.TV_MANUAL_ERROR_MSG); return rcsOk(null); } List parts = new ArrayList<>(); for (JsonNode item : arr) { if (item == null || !item.isObject()) { continue; } String staNo = text(item.get("staNo")); String err = text(item.get("error")); String plc = text(item.get("plcDesc")); String msg = StringUtils.hasText(err) ? err : plc; if (!StringUtils.hasText(msg)) { continue; } if (StringUtils.hasText(staNo)) { parts.add("[" + staNo + "]" + msg); } else { parts.add(msg); } } if (parts.isEmpty()) { tvMonitorStringRedisTemplate.delete(TvMonitorRedisKeys.TV_MANUAL_ERROR_MSG); return rcsOk(null); } String value = String.join(";", parts); tvMonitorStringRedisTemplate.opsForValue().set(TvMonitorRedisKeys.TV_MANUAL_ERROR_MSG, value); log.info("RCS 报警已写入 Redis tvManualErrorMsg,条数={}", parts.size()); return rcsOk(value); } private static JsonNode resolveErrorArray(JsonNode body) { if (body == null || body.isNull()) { return null; } if (body.isArray()) { return body; } if (body.isObject()) { if (body.has("data") && body.get("data").isArray()) { return body.get("data"); } if (body.has("errors") && body.get("errors").isArray()) { return body.get("errors"); } } return null; } private static String text(JsonNode n) { if (n == null || n.isNull()) { return ""; } String s = n.asText(""); return s == null ? "" : s.trim(); } /** * 站点任务号写入 Redis Hash,供后续扩展;电视机 led 任务号仍来自 WCS 站点轮询 */ public Map handleStationTaskNo(JsonNode body) { if (body == null || body.isNull() || !body.isObject()) { throw new IllegalArgumentException("body 须为 JSON 对象"); } JsonNode dataNode = body.get("data"); JsonNode src = (dataNode != null && dataNode.isObject()) ? dataNode : body; String staNo = text(body.get("staNo")); if (!StringUtils.hasText(staNo)) { staNo = text(src.get("staNo")); } String taskNo = text(src.get("taskNo")); if (!StringUtils.hasText(staNo)) { throw new IllegalArgumentException("staNo 不能为空"); } if (!StringUtils.hasText(taskNo)) { tvMonitorStringRedisTemplate.opsForHash().delete(TvMonitorRedisKeys.TV_RCS_STATION_TASK_NO, staNo); } else { tvMonitorStringRedisTemplate.opsForHash() .put(TvMonitorRedisKeys.TV_RCS_STATION_TASK_NO, staNo, taskNo); } log.info("RCS 任务号已写入 Redis Hash staNo={} taskNo={}", staNo, taskNo); Map payload = new LinkedHashMap<>(); payload.put("staNo", staNo); payload.put("taskNo", taskNo); return rcsOk(payload); } private Map rcsOk(Object data) { Map m = new LinkedHashMap<>(); m.put("code", 200); m.put("message", "请求成功"); m.put("timestamp", System.currentTimeMillis()); m.put("data", data); return m; } }