11 小时以前 0541c0791acea41b584f71fc59e22d4d21ba0883
src/main/java/com/ruoyi/http/service/impl/RealTimeEnergyConsumptionServiceImpl.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.http.service.RealTimeEnergyConsumptionService;
import lombok.extern.slf4j.Slf4j;
@@ -49,11 +50,13 @@
    private static final String HISTORY_CACHE_PREFIX = "JCLY:HISTORY:";
    private static final String TOKEN_CACHE_KEY = "JCLY_TOKEN:";
    private static final String STATUS_KEY = "status";
    private static final String STATUS_MESSAGE_KEY = "statusMessage";
    private static final String STATUS_OK = "ok";
    private static final String STATUS_ONLINE = "在线";
    private static final String STATUS_OFFLINE = "offline";
@@ -111,7 +114,7 @@
                historyItem.put("monitorTimeStr", historyObj.getString("monitorTimeStr"));
                historyItem.put("position", historyObj.getString("position"));
                historyItem.put("address", historyObj.getString("address"));
                historyItem.put(STATUS_KEY, STATUS_OK);
                historyItem.put(STATUS_KEY, resolveStatusByAlarmState(historyObj.get("alarmState"), STATUS_ONLINE));
                JSONArray paramList = historyObj.getJSONArray("data");
                if (paramList != null && !paramList.isEmpty()) {
@@ -129,6 +132,8 @@
                            historyItem.put("humidity", fullValue);
                        } else if ("0130".equals(paramCode)) {
                            historyItem.put("co2", fullValue);
                        } else if ("0042".equals(paramCode)) {
                            historyItem.put("battery", fullValue);
                        } else if (paramCode != null) {
                            historyItem.put(paramCode, fullValue);
                        }
@@ -176,7 +181,7 @@
    }
    public String getToken() {
        String cachedToken = sanitizeToken(redisTemplate.opsForValue().get("JCLY_TOKEN:"));
        String cachedToken = sanitizeToken(redisTemplate.opsForValue().get(TOKEN_CACHE_KEY));
        if (cachedToken != null) {
            return cachedToken;
        }
@@ -192,10 +197,11 @@
        if (Integer.valueOf(0).equals(map.get("code"))) {
            Object token = map.get("data");
            log.info("token:{}", token);
            redisTemplate.opsForValue().set("JCLY_TOKEN:", token.toString(), 60 * 60 * 24);
            redisTemplate.opsForValue().set(TOKEN_CACHE_KEY, token.toString(), 60 * 60 * 12);
            return token.toString();
        }
        return result;
        log.error("get token failed, response={}", result);
        return null;
    }
    private String sanitizeToken(String token) {
@@ -217,6 +223,64 @@
    private String stringValue(Object value) {
        return value == null ? null : String.valueOf(value);
    }
    private String refreshToken() {
        redisTemplate.delete(TOKEN_CACHE_KEY);
        return getToken();
    }
    private boolean isUnauthorizedException(Exception ex) {
        if (ex == null || ex.getMessage() == null) {
            return false;
        }
        String msg = ex.getMessage().toLowerCase();
        return msg.contains("401") || msg.contains("unauthorized");
    }
    private boolean isUnauthorizedResponse(String result) {
        if (result == null || result.trim().isEmpty()) {
            return false;
        }
        try {
            JSONObject obj = JSON.parseObject(result);
            if (obj == null) {
                return false;
            }
            Integer code = obj.getInteger("code");
            if (code != null && (code == 401 || code == 403)) {
                return true;
            }
            String msg = obj.getString("msg");
            return msg != null && msg.toLowerCase().contains("unauthorized");
        } catch (Exception ignore) {
            return result.contains("401");
        }
    }
    private String requestWithTokenRetry(String url, String payload, String token, String scene) {
        String usedToken = sanitizeToken(token);
        if (usedToken == null) {
            usedToken = refreshToken();
        }
        try {
            String result = HttpUtils.sendPostJson(url, payload, usedToken);
            if (!isUnauthorizedResponse(result) && StringUtils.isNotEmpty(result)) {
                return result;
            }
            log.warn("{} got unauthorized response, refresh token and retry once", scene);
        } catch (Exception ex) {
            if (!isUnauthorizedException(ex)) {
                throw ex;
            }
            log.warn("{} got 401 exception, refresh token and retry once", scene);
        }
        String newToken = refreshToken();
        if (newToken == null) {
            throw new RuntimeException("refresh token failed");
        }
        return HttpUtils.sendPostJson(url, payload, newToken);
    }
    private String concatValueWithUnit(String value, String unitCode) {
@@ -296,7 +360,6 @@
    }
    private Map<String, String> parseSingleDevice(JSONObject deviceObj, String fallbackGuid) {
        String[] targetCodes = {"0100", "0110", "0120", "0130"};
        Map<String, String> deviceData = new HashMap<>();
        String deviceGuid = firstNonBlank(
                deviceObj.getString("deviceGuid"),
@@ -316,12 +379,10 @@
            return deviceData;
        }
        deviceData.put(STATUS_KEY, STATUS_OK);
        for (String code : targetCodes) {
            JSONObject paramObj = getProbeParam(paramList, code);
            if (paramObj.isEmpty()) {
                continue;
            }
        deviceData.put(STATUS_KEY, resolveStatusByAlarmState(deviceObj.get("alarmState"), STATUS_ONLINE));
        for (int i = 0; i < paramList.size(); i++) {
            JSONObject paramObj = paramList.getJSONObject(i);
            String code = paramObj.getString("paramCode");
            String value = paramObj.getString("value");
            String unitCode = paramObj.getString("unitCode");
            String fullValue = concatValueWithUnit(value, unitCode);
@@ -333,9 +394,28 @@
                deviceData.put("humidity", fullValue);
            } else if ("0130".equals(code)) {
                deviceData.put("co2", fullValue);
            } else if ("0042".equals(code)) {
                deviceData.put("battery", fullValue);
            }
        }
        return deviceData;
    }
    private String resolveStatusByAlarmState(Object alarmState, String defaultStatus) {
        if (alarmState == null) {
            return defaultStatus;
        }
        if (alarmState instanceof Boolean) {
            return (Boolean) alarmState ? STATUS_OFFLINE : STATUS_ONLINE;
        }
        String normalized = String.valueOf(alarmState).trim().toLowerCase();
        if ("true".equals(normalized) || "1".equals(normalized)) {
            return STATUS_OFFLINE;
        }
        if ("false".equals(normalized) || "0".equals(normalized)) {
            return STATUS_ONLINE;
        }
        return defaultStatus;
    }
    public String getRealTimeData(String token, List<String> guidList) {
@@ -350,7 +430,7 @@
            log.info("hit realtime cache: {}", cacheKey);
            return cachedResult;
        }
        String result = HttpUtils.sendPostJson(URL + REAL_TIME_URL, JSON.toJSONString(param), token);
        String result = requestWithTokenRetry(URL + REAL_TIME_URL, JSON.toJSONString(param), token, "getRealTimeData");
        log.info("request realtime response: {}", result);
        cacheRemoteResponse(cacheKey, result);
        return result;
@@ -370,7 +450,7 @@
            log.info("hit history cache: {}", cacheKey);
            return cachedResult;
        }
        String result = HttpUtils.sendPostJson(REAL_HISTORY_URL, JSON.toJSONString(param), token);
        String result = requestWithTokenRetry(REAL_HISTORY_URL, JSON.toJSONString(param), token, "getHistoryData");
        log.info("request history response: {}", result);
        cacheRemoteResponse(cacheKey, result);
        return result;
@@ -382,4 +462,4 @@
        }
        redisTemplate.opsForValue().set(cacheKey, result, REMOTE_CACHE_TTL_SECONDS_30, TimeUnit.SECONDS);
    }
}
}