package com.doumee.core.conditoner; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.doumee.core.conditoner.model.ConditionerConstant; import com.doumee.core.conditoner.model.request.*; import com.doumee.core.conditoner.model.response.*; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.util.EntityUtils; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; /** * 智精灵空调平台 HTTP 工具类。 *

* 协议:GET 读取(Query 参数);POST 控制/写入(JSON Body)。 * 成功标识 {@code code=200}。登录后公共参数 {@code kt_token}、{@code kt_dwid}、{@code kt_sonid}。 *

*/ @Slf4j public class ConditionerUtil { private static final int HTTP_RETRY = 3; private ConditionerUtil() { } // ==================== 二、基础控制 ==================== public static ConditionerBaseResponse login() { return login(null); } public static ConditionerBaseResponse login(LoginRequest req) { LoginRequest r = req != null ? req : new LoginRequest(); JSONObject body = new JSONObject(); body.put("username", StringUtils.isNotBlank(r.getUsername()) ? r.getUsername() : ConditionerConstant.username); body.put("password", StringUtils.isNotBlank(r.getPassword()) ? r.getPassword() : ConditionerConstant.password); try { String raw = doPostRaw("/login", body.toJSONString()); ConditionerBaseResponse resp = parseObjectResponse(raw, LoginDataResponse.class); applyLoginSession(resp); return resp; } catch (Exception e) { log.error("conditioner login failed", e); return null; } } public static ConditionerBaseResponse> getDevList(ConditionerSessionRequest req) { return getList("/getDevList", req, DeviceStatusResponse.class); } public static ConditionerBaseResponse getDevOne(GetDevOneRequest req) { if (req == null) { return null; } req.fillSessionDefaults(); try { String raw = doGetRaw("/getDevOne", toQueryMap(req)); return parseObjectResponse(raw, DeviceStatusResponse.class); } catch (Exception e) { log.error("conditioner getDevOne failed", e); return null; } } public static ConditionerBaseResponse devCtr(DevControlRequest req) { return postJson("/devCtr", req, Object.class); } public static ConditionerBaseResponse devManyCtr(DevManyControlRequest req) { return postJson("/devManyCtr", req, Object.class); } public static ConditionerBaseResponse devLockManyCtr(DevLockControlRequest req) { return postJson("/devManyCtr", req, Object.class); } // ==================== 三、设备管理 ==================== public static ConditionerBaseResponse> getWg(ConditionerSessionRequest req) { return getList("/getWg", req, GatewayInfoResponse.class); } public static ConditionerBaseResponse addWg(WgManageRequest req) { return postJson("/addWg", req, Object.class); } public static ConditionerBaseResponse changeWg(WgManageRequest req) { return postJson("/changeWg", req, Object.class); } public static ConditionerBaseResponse delWg(WgManageRequest req) { return postJson("/delWg", req, Object.class); } public static ConditionerBaseResponse wgWithArea(WgWithAreaRequest req) { return postJson("/wgWithArea", req, Object.class); } public static ConditionerBaseResponse> getDev(ConditionerSessionRequest req) { return getList("/getDev", req, DeviceArchiveResponse.class); } public static ConditionerBaseResponse addDev(DevManageRequest req) { return postJson("/addDev", req, Object.class); } public static ConditionerBaseResponse changeDev(DevManageRequest req) { return postJson("/changeDev", req, Object.class); } public static ConditionerBaseResponse delDev(DevManageRequest req) { return postJson("/delDev", req, Object.class); } // ==================== 四、区域管理 ==================== public static ConditionerBaseResponse> getRoom(ConditionerSessionRequest req) { return getList("/getRoom", req, RoomInfoResponse.class); } public static ConditionerBaseResponse addRoom(RoomManageRequest req) { return postJson("/addRoom", req, Object.class); } public static ConditionerBaseResponse changeRoom(RoomManageRequest req) { return postJson("/changeRoom", req, Object.class); } public static ConditionerBaseResponse delRoom(RoomManageRequest req) { return postJson("/delRoom", req, Object.class); } public static ConditionerBaseResponse> getFloor(ConditionerPageRequest req) { return getList("/getFloor", req, FloorInfoResponse.class); } public static ConditionerBaseResponse addFloor(FloorManageRequest req) { return postJson("/addFloor", req, Object.class); } public static ConditionerBaseResponse changeFloor(FloorManageRequest req) { return postJson("/changeFloor", req, Object.class); } public static ConditionerBaseResponse delFloor(FloorManageRequest req) { return postJson("/delFloor", req, Object.class); } public static ConditionerBaseResponse> getUnit(ConditionerPageRequest req) { return getList("/getUnit", req, UnitInfoResponse.class); } public static ConditionerBaseResponse addUnit(UnitManageRequest req) { return postJson("/addUnit", req, Object.class); } public static ConditionerBaseResponse changeUnit(UnitManageRequest req) { return postJson("/changeUnit", req, Object.class); } public static ConditionerBaseResponse delUnit(UnitManageRequest req) { return postJson("/delUnit", req, Object.class); } public static ConditionerBaseResponse> getBuilding(ConditionerPageRequest req) { return getList("/getBuilding", req, BuildingInfoResponse.class); } public static ConditionerBaseResponse addBuilding(BuildingManageRequest req) { return postJson("/addBuilding", req, Object.class); } public static ConditionerBaseResponse changeBuilding(BuildingManageRequest req) { return postJson("/changeBuilding", req, Object.class); } public static ConditionerBaseResponse delBuilding(BuildingManageRequest req) { return postJson("/delBuilding", req, Object.class); } public static ConditionerBaseResponse> getArea(ConditionerPageRequest req) { return getList("/getArea", req, AreaInfoResponse.class); } public static ConditionerBaseResponse addArea(AreaManageRequest req) { return postJson("/addArea", req, Object.class); } public static ConditionerBaseResponse changeArea(AreaManageRequest req) { return postJson("/changeArea", req, Object.class); } public static ConditionerBaseResponse delArea(AreaManageRequest req) { return postJson("/delArea", req, Object.class); } // ==================== 五、定时管理 ==================== public static ConditionerBaseResponse> getTiming(ConditionerSessionRequest req) { return getList("/getTiming", req, TimingInfoResponse.class); } public static ConditionerBaseResponse addTiming(TimingManageRequest req) { return postJson("/addTiming", req, Object.class); } public static ConditionerBaseResponse changeTiming(TimingManageRequest req) { return postJson("/changeTiming", req, Object.class); } public static ConditionerBaseResponse delTiming(TimingManageRequest req) { return postJson("/delTiming", req, Object.class); } public static ConditionerBaseResponse timingWithArea(TimingWithAreaRequest req) { return postJson("/timingWithArea", req, Object.class); } // ==================== 六、数据查询 ==================== public static ConditionerBaseResponse> getLogWg(LogQueryRequest req) { return getList("/getLogWg", req, Object.class); } public static ConditionerBaseResponse> getLogDev(LogQueryRequest req) { return getList("/getLogDev", req, Object.class); } // ==================== 七、计量管理 ==================== public static ConditionerBaseResponse> getDlSjXs(ConditionerSessionRequest req) { return getList("/getDlSjXs", req, DlSjXsResponse.class); } public static ConditionerBaseResponse changeDlSjXs(ChangeDlSjXsRequest req) { return postJson("/changeDlSjXs", req, Object.class); } public static ConditionerBaseResponse> getDb(MeterDbManageRequest req) { return getList("/glDb/getDb", req, MeterDbInfoResponse.class); } public static ConditionerBaseResponse addDb(MeterDbManageRequest req) { return postJson("/glDb/addDb", req, Object.class); } public static ConditionerBaseResponse changeDb(MeterDbManageRequest req) { return postJson("/glDb/changeDb", req, Object.class); } public static ConditionerBaseResponse delDb(MeterDbManageRequest req) { return postJson("/glDb/delDb", req, Object.class); } public static ConditionerBaseResponse> getDbDaySum(DbDaySumQueryRequest req) { return getList("/getDbDaySum", req, Object.class); } public static ConditionerBaseResponse> getDayDl(DayDlQueryRequest req) { return getList("/getDayDl", req, Object.class); } public static ConditionerBaseResponse> getMoonDl(MoonDlQueryRequest req) { return getList("/getMoonDl", req, Object.class); } public static ConditionerBaseResponse> getGs(CompanyGsManageRequest req) { return getList("/getGs", req, CompanyGsInfoResponse.class); } public static ConditionerBaseResponse addGs(CompanyGsManageRequest req) { if (req == null) { return null; } req.fillSessionDefaults(); JSONObject body = new JSONObject(true); putSessionFields(body, req); body.put("is_pwr", req.getIs_pwr() != null ? req.getIs_pwr() : 1); if (req.getLi_dev() != null && !req.getLi_dev().isEmpty()) { body.put("li_dev", req.getLi_dev()); } if (req.getD_dev() != null && !req.getD_dev().isEmpty()) { body.put("d_dev", req.getD_dev()); } body.put("gs_name", req.getGs_name()); body.put("is_rest_stop", req.getIs_rest_stop() != null ? req.getIs_rest_stop() : 0); body.put("gs_bz", StringUtils.defaultString(req.getGs_bz())); putStopMoney(body, req.getStop_money()); return postJsonBody("/addGs", body, Object.class); } public static ConditionerBaseResponse changeGs(CompanyGsManageRequest req) { if (req == null || req.getId() == null) { return null; } req.fillSessionDefaults(); JSONObject body = new JSONObject(true); body.put("id", req.getId()); body.put("is_pwr", req.getIs_pwr() != null ? req.getIs_pwr() : 1); body.put("is_rest_stop", req.getIs_rest_stop() != null ? req.getIs_rest_stop() : 0); body.put("gs_name", req.getGs_name()); if (req.getLeft_money() != null) { body.put("left_money", req.getLeft_money()); } body.put("is_stop", req.getIs_stop() != null ? req.getIs_stop() : 0); body.put("li_dev", req.getLi_dev()); body.put("d_dev", req.getD_dev()); body.put("gs_bz", StringUtils.defaultString(req.getGs_bz())); putStopMoney(body, req.getStop_money()); return postJsonBody("/changeGs", body, Object.class); } private static void putStopMoney(JSONObject body, Object stopMoney) { if (stopMoney != null) { body.put("stop_money", stopMoney); } } public static ConditionerBaseResponse delGs(CompanyGsManageRequest req) { return postJson("/delGs", req, Object.class); } public static ConditionerBaseResponse gsWithArea(GsWithAreaRequest req) { return postJson("/gsWithArea", req, Object.class); } public static ConditionerBaseResponse addMoney(AddMoneyRequest req) { if (req == null) { return null; } req.fillSessionDefaults(); JSONObject body = new JSONObject(true); putSessionFields(body, req); body.put("id", req.getId()); body.put("cz_money", req.getCz_money()); return postJsonBody("/addMoney", body, Object.class); } public static ConditionerBaseResponse cleanMoney(CompanyGsManageRequest req) { if (req == null || req.getId() == null) { return null; } req.fillSessionDefaults(); JSONObject body = new JSONObject(true); putSessionFields(body, req); body.put("id", req.getId()); return postJsonBody("/cleanMoney", body, Object.class); } public static ConditionerBaseResponse> getCzLog(LogQueryRequest req) { return getList("/getCzLog", req, Object.class); } // ==================== 八、账号管理 ==================== public static ConditionerBaseResponse> getUser(ConditionerSessionRequest req) { return getList("/getUser", req, UserInfoResponse.class); } public static ConditionerBaseResponse addUser(UserManageRequest req) { return postJson("/addUser", req, Object.class); } public static ConditionerBaseResponse changeUser(UserManageRequest req) { return postJson("/changeUser", req, Object.class); } public static ConditionerBaseResponse changeUserPwd(UserManageRequest req) { return postJson("/changeUserPwd", req, Object.class); } public static ConditionerBaseResponse delUser(UserManageRequest req) { return postJson("/delUser", req, Object.class); } // ==================== 会话 ==================== public static void applyLoginSession(ConditionerBaseResponse resp) { if (resp == null || !resp.isSuccess() || resp.getData() == null) { return; } LoginDataResponse data = resp.getData(); if (StringUtils.isNotBlank(data.getKt_token())) { ConditionerConstant.kt_token = data.getKt_token(); } if (data.getKt_dwid() != null) { ConditionerConstant.kt_dwid = String.valueOf(data.getKt_dwid()); } if (data.getKt_sonid() != null) { ConditionerConstant.kt_sonid = String.valueOf(data.getKt_sonid()); } } // ==================== HTTP / 解析 ==================== private static ConditionerBaseResponse> getList(String path, ConditionerSessionRequest req, Class itemClass) { if (req != null) { req.fillSessionDefaults(); } else { req = new ConditionerSessionRequest(); req.fillSessionDefaults(); } try { String raw = doGetRaw(path, toQueryMap(req)); return parseListResponse(raw, itemClass); } catch (Exception e) { log.error("conditioner GET {} failed", path, e); return null; } } private static ConditionerBaseResponse postJson(String path, ConditionerSessionRequest req, Class dataClass) { if (req != null) { req.fillSessionDefaults(); } try { String raw = doPostRaw(path, JSON.toJSONString(req)); return parseObjectResponse(raw, dataClass); } catch (Exception e) { log.error("conditioner POST {} failed", path, e); return null; } } private static ConditionerBaseResponse postJsonBody(String path, JSONObject body, Class dataClass) { try { String raw = doPostRaw(path, body.toJSONString()); return parseObjectResponse(raw, dataClass); } catch (Exception e) { log.error("conditioner POST {} failed", path, e); return null; } } private static void putSessionFields(JSONObject body, ConditionerSessionRequest req) { body.put("kt_token", req.getKt_token()); body.put("kt_dwid", req.getKt_dwid()); body.put("kt_unit", StringUtils.defaultIfBlank(req.getKt_unit(), ConditionerConstant.DEFAULT_KT_UNIT)); body.put("kt_sonid", req.getKt_sonid()); } private static String resolveUrl(String path) { String base = StringUtils.defaultIfBlank(ConditionerConstant.base_url, ConditionerConstant.DEFAULT_BASE_URL); if (base.endsWith("/")) { base = base.substring(0, base.length() - 1); } if (!path.startsWith("/")) { path = "/" + path; } return base + path; } private static String doGetRaw(String path, Map params) throws Exception { String url = buildGetUrl(path, params); log.info("conditioner GET url={}", maskUrl(url)); HttpClient client = HttpClientBuilder.create().build(); HttpGet get = new HttpGet(url); HttpResponse response = executeWithRetry(client, get); String resp = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("conditioner GET response={}", abbreviate(resp)); return resp; } private static String doPostRaw(String path, String jsonBody) throws Exception { String url = resolveUrl(path); log.info("conditioner POST url={}, body={}", url, maskJson(jsonBody)); HttpClient client = HttpClientBuilder.create().build(); HttpPost post = new HttpPost(url); post.setHeader("Content-Type", "application/json;charset=UTF-8"); post.setEntity(new StringEntity(jsonBody, StandardCharsets.UTF_8)); HttpResponse response = executeWithRetry(client, post); String resp = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8); log.info("conditioner POST response={}", abbreviate(resp)); return resp; } private static HttpResponse executeWithRetry(HttpClient client, org.apache.http.client.methods.HttpUriRequest request) throws Exception { HttpResponse execute = null; int retry = HTTP_RETRY; while (retry-- > 0) { try { execute = client.execute(request); break; } catch (Exception e) { if (retry <= 0) { throw e; } Thread.sleep(5000); } } if (execute == null) { throw new Exception("conditioner http request failed"); } return execute; } private static String buildGetUrl(String path, Map params) throws Exception { StringBuilder sb = new StringBuilder(resolveUrl(path)); if (params == null || params.isEmpty()) { return sb.toString(); } sb.append("?"); boolean first = true; for (Map.Entry entry : params.entrySet()) { if (StringUtils.isBlank(entry.getValue())) { continue; } if (!first) { sb.append("&"); } sb.append(urlEncode(entry.getKey())).append("=").append(urlEncode(entry.getValue())); first = false; } return sb.toString(); } private static Map toQueryMap(Object obj) { Map map = new LinkedHashMap<>(); if (obj == null) { return map; } JSONObject json = (JSONObject) JSON.toJSON(obj); for (Map.Entry entry : json.entrySet()) { Object val = entry.getValue(); if (val != null) { map.put(entry.getKey(), String.valueOf(val)); } } return map; } private static ConditionerBaseResponse parseObjectResponse(String raw, Class dataClass) { if (StringUtils.isBlank(raw)) { return null; } try { JSONObject root = JSON.parseObject(raw); ConditionerBaseResponse resp = new ConditionerBaseResponse<>(); resp.setCode(root.getInteger("code")); resp.setMessage(root.getString("message")); Object data = root.get("data"); if (data != null && dataClass != null) { if (data instanceof JSONObject) { resp.setData(((JSONObject) data).toJavaObject(dataClass)); } else if (data instanceof String) { String text = ((String) data).trim(); if (text.startsWith("{")) { resp.setData(JSON.parseObject(text, dataClass)); } } else if (!(data instanceof JSONArray)) { resp.setData(JSON.parseObject(JSON.toJSONString(data), dataClass)); } } return resp; } catch (Exception e) { log.error("conditioner parse object response failed: {}", abbreviate(raw), e); return null; } } private static ConditionerBaseResponse> parseListResponse(String raw, Class itemClass) { if (StringUtils.isBlank(raw)) { return null; } try { JSONObject root = JSON.parseObject(raw); ConditionerBaseResponse> resp = new ConditionerBaseResponse<>(); resp.setCode(root.getInteger("code")); resp.setMessage(root.getString("message")); Object data = root.get("data"); if (data instanceof JSONArray) { resp.setData(((JSONArray) data).toJavaList(itemClass)); } else if (data instanceof String) { String text = ((String) data).trim(); if (text.startsWith("[")) { resp.setData(JSON.parseArray(text, itemClass)); } } return resp; } catch (Exception e) { log.error("conditioner parse list response failed: {}", abbreviate(raw), e); return null; } } private static String urlEncode(String value) throws Exception { return URLEncoder.encode(value, StandardCharsets.UTF_8.name()); } private static String maskUrl(String url) { if (url == null) { return null; } return url.replaceAll("(kt_token=)[^&]+", "$1***"); } private static String maskJson(String json) { if (json == null) { return null; } return json.replaceAll("(\\\"password\\\"\\s*:\\s*\\\")[^\\\"]+(\\\")", "$1***$2") .replaceAll("(\\\"kt_token\\\"\\s*:\\s*\\\")[^\\\"]+(\\\")", "$1***$2"); } private static String abbreviate(String text) { if (text == null) { return null; } return text.length() > 500 ? text.substring(0, 500) + "..." : text; } }