| | |
| | | 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; |
| | |
| | | |
| | | 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"; |
| | | |
| | |
| | | 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()) { |
| | |
| | | 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); |
| | | } |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | |
| | | 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) { |
| | |
| | | |
| | | 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) { |
| | |
| | | } |
| | | |
| | | 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"), |
| | |
| | | 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); |
| | |
| | | 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) { |
| | |
| | | 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; |
| | |
| | | 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; |