package com.ruoyi.other.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.other.domain.TPlatformConfig; import com.ruoyi.other.service.TPlatformConfigService; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.Collections; import java.util.List; /** * 华为:光伏数据对接 * * @author Lux * @version 1.0.0 * @since 2026/9/7 17:38 */ @Slf4j @Service public class HuWeiUtils { private static final String API_HOST = "https://cn.fusionsolar.huawei.com"; private static final String DEFAULT_USER_NAME = "mxxnycd"; private static final String DEFAULT_SYSTEM_CODE = "mxxny888888"; private static final String LOGIN_PATH = "/thirdData/login"; private static final String STATIONS_PATH = "/thirdData/stations"; private static final String DEV_LIST_PATH = "/thirdData/getDevList"; private static final String Kpi_STATION_DAY_PATH = "/thirdData/getKpiStationDay"; @Resource private RestTemplate restTemplate; @Resource private TPlatformConfigService platformConfigService; /** 登录华为 FusionSolar 并取得 XSRF-TOKEN。 */ public String getXsrfToken() { TPlatformConfig config = platformConfigService.getOne(Wrappers.lambdaQuery(TPlatformConfig.class) .eq(TPlatformConfig::getType, 1) .eq(TPlatformConfig::getPlatformName, "华为")); if (config == null || StringUtils.isBlank(config.getAccount()) || StringUtils.isBlank(config.getPassword())) { return getXsrfToken(DEFAULT_USER_NAME, DEFAULT_SYSTEM_CODE); } return getXsrfToken(config.getAccount(), config.getPassword()); } /** 使用指定账号登录并取得 XSRF-TOKEN。 */ public String getXsrfToken(String userName, String systemCode) { JSONObject body = new JSONObject(); body.put("userName", userName); body.put("systemCode", systemCode); HttpHeaders headers = new HttpHeaders(); headers.set(HttpHeaders.CONTENT_TYPE, "application/json"); ResponseEntity response = restTemplate.exchange(API_HOST + LOGIN_PATH, HttpMethod.POST, new HttpEntity<>(body.toJSONString(), headers), String.class); String token = response.getHeaders().getFirst("XSRF-TOKEN"); if (token == null) { List cookies = response.getHeaders().get(HttpHeaders.SET_COOKIE); if (cookies != null) { for (String cookie : cookies) { if (cookie.startsWith("XSRF-TOKEN=")) { token = cookie.substring("XSRF-TOKEN=".length()).split(";", 2)[0]; break; } } } } if (token == null || token.trim().isEmpty()) { throw new IllegalStateException("华为登录未返回XSRF-TOKEN"); } return token; } /** * 获取电站列表 * * @param pageNo 当前页 * @param token 登陆后的token * @return 列表数据 */ public JSONArray getStations(Integer pageNo, String token) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(org.springframework.http.MediaType.APPLICATION_JSON)); headers.set("XSRF-TOKEN", token); headers.set(HttpHeaders.COOKIE, "XSRF-TOKEN=" + token); JSONObject body = new JSONObject(); body.put("pageNo", pageNo == null || pageNo < 1 ? 1 : pageNo); ResponseEntity response = restTemplate.exchange(API_HOST + STATIONS_PATH, HttpMethod.POST, new HttpEntity<>(body.toJSONString(), headers), String.class); JSONObject result = JSON.parseObject(response.getBody()); if (result == null || !Boolean.TRUE.equals(result.getBoolean("success"))) { throw new IllegalStateException("华为电站列表接口调用失败:" + (result == null ? "空响应" : result.getString("message"))); } JSONObject data = result.getJSONObject("data"); return data == null || data.getJSONArray("list") == null ? new JSONArray() : data.getJSONArray("list"); } /** * 获取设备列表 * * @param stationCodes 电站ID,多个用逗号分隔 * @param token 登陆后的token * @return 列表数据 */ public JSONArray getDevList(String stationCodes, String token) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(org.springframework.http.MediaType.APPLICATION_JSON)); headers.set("XSRF-TOKEN", token); headers.set(HttpHeaders.COOKIE, "XSRF-TOKEN=" + token); JSONObject body = new JSONObject(); body.put("stationCodes", stationCodes); ResponseEntity response = restTemplate.exchange(API_HOST + DEV_LIST_PATH, HttpMethod.POST, new HttpEntity<>(body.toJSONString(), headers), String.class); JSONObject result = JSON.parseObject(response.getBody()); if (result == null || !Boolean.TRUE.equals(result.getBoolean("success"))) { throw new IllegalStateException("华为设备列表接口调用失败:" + (result == null ? "空响应" : result.getString("message"))); } JSONArray dataList = result.getJSONArray("data"); return dataList == null ? new JSONArray() : dataList; } /** * 获取设备列表 * * @param stationCodes 电站ID,多个用逗号分隔 * @param token 登陆后的token * @return 列表数据 */ public JSONArray getKpiStationDay(String stationCodes, Long collectTime, String token) { HttpHeaders headers = new HttpHeaders(); headers.setContentType(org.springframework.http.MediaType.APPLICATION_JSON); headers.setAccept(Collections.singletonList(org.springframework.http.MediaType.APPLICATION_JSON)); headers.set("XSRF-TOKEN", token); headers.set(HttpHeaders.COOKIE, "XSRF-TOKEN=" + token); JSONObject body = new JSONObject(); body.put("stationCodes", stationCodes); body.put("collectTime", collectTime); ResponseEntity response = restTemplate.exchange(API_HOST + Kpi_STATION_DAY_PATH, HttpMethod.POST, new HttpEntity<>(body.toJSONString(), headers), String.class); JSONObject result = JSON.parseObject(response.getBody()); if (result == null || !Boolean.TRUE.equals(result.getBoolean("success"))) { throw new IllegalStateException("华为电站列表接口调用失败:" + (result == null ? "空响应" : result.getString("message"))); } JSONArray dataList = result.getJSONArray("data"); return dataList == null ? new JSONArray() : dataList; } }