package com.usky.vpp.util; import com.usky.vpp.config.VppUnProperties; import com.usky.vpp.domain.VppResourcePoint; import com.usky.vpp.domain.VppSite; import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; /** * 构造运管平台标准响应报文(联调 JSON 实例) */ public final class VppUnMessageBuilder { private static final DateTimeFormatter CREATED_DATE_TIME = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); private static final DateTimeFormatter MOMENT_DATE_TIME = DateTimeFormatter.ISO_LOCAL_DATE_TIME; private VppUnMessageBuilder() { } public static Map buildTokenRequest(VppUnProperties properties) { return buildBaseRequest("TokenRequest", properties); } public static Map buildPollRequest(VppUnProperties properties) { return buildBaseRequest("Poll", properties); } public static Map buildCreateRegistrationRequest(VppUnProperties properties) { Map req = buildBaseRequest("CreateRegistrationRequest", properties); req.put("dnName", properties.getDnName()); if (StringUtils.hasText(properties.getRegistrationId())) { req.put("registrationID", properties.getRegistrationId()); } req.put("reportOnly", false); req.put("pullMode", true); req.put("signature", false); req.put("transport", "REST"); req.put("transportAddress", properties.getTransportAddress()); return req; } public static Map buildCreateOptRequest(String eventId, String optType, List> list, VppUnProperties properties) { Map req = buildBaseRequest("CreateOptRequest", properties); req.put("eventID", eventId); req.put("optType", optType); req.put("createdDateTime", CREATED_DATE_TIME.format(LocalDateTime.now())); req.put("priceDownCoeff", properties.getPriceDownCoeff()); if (list != null) { req.put("list", list); } return req; } public static Map buildCreateCqRequest(String eventId, String optType, List> list, VppUnProperties properties) { Map req = buildBaseRequest("CreateCqRequest", properties); req.put("eventID", eventId); req.put("optType", optType != null ? optType : "optIn"); req.put("createdDateTime", CREATED_DATE_TIME.format(LocalDateTime.now())); req.put("priceDownCoeff", properties.getPriceDownCoeff()); if (list != null) { req.put("list", list); } return req; } public static Map buildCreateReportResponse(Map request, VppUnProperties properties) { Map resp = new LinkedHashMap<>(); if (request != null) { resp.put("requestID", request.get("requestID")); } resp.put("root", "CreateReportResponse"); resp.put("version", 1); resp.put("code", 200); resp.put("description", "ok"); if (resp.get("requestID") == null) { resp.put("requestID", UUID.randomUUID().toString()); } resp.put("dnID", properties.getDnId()); Map pendingReports = new LinkedHashMap<>(); List reportRequestIds = new ArrayList<>(); reportRequestIds.add("MetaDataReport"); pendingReports.put("reportRequestID", reportRequestIds); resp.put("pendingReports", pendingReports); return resp; } /** * 构造 RegisterReportRequest:虚拟电厂量测点(含负荷预测)+ 站点/资源点有功功率(kW)。 */ public static Map buildRegisterReportRequest(VppUnProperties properties, List sites, List resources, Map deviceUnResourceIdMap) { Map req = buildBaseRequest("RegisterReportRequest", properties); req.put("reportRequestID", "MetaDataReport"); List> reports = new ArrayList<>(); String createdDateTime = CREATED_DATE_TIME.format(LocalDateTime.now()); for (VppUnRegisterReportIndex.Entry entry : VppUnRegisterReportIndex.buildRegisterEntries( properties, sites, resources, deviceUnResourceIdMap)) { String resourceId = resolveRegisterResourceId(entry, properties, deviceUnResourceIdMap); reports.add(buildVppMetadataReportItem(entry.getRid(), entry.getMetric(), resourceId, createdDateTime)); } req.put("report", reports); return req; } private static String resolveRegisterResourceId(VppUnRegisterReportIndex.Entry entry, VppUnProperties properties, Map deviceUnResourceIdMap) { if (entry.getScope() == VppUnRegisterReportIndex.Scope.SITE) { return entry.getSite().getUnResourceId(); } if (entry.getScope() == VppUnRegisterReportIndex.Scope.RESOURCE) { return deviceUnResourceIdMap.get(entry.getResource().getDeviceId()); } return properties.getDnId(); } public static Map buildIntervalDataReportRequest(VppUnProperties properties, Map createReportRequest, List> pointCurveData, LocalDateTime reportTime) { Map req = buildBaseRequest("IntervalDataReportRequest", properties); req.put("reportRequestID", resolveReportRequestIdFromPoll(createReportRequest, "IntervalDataReport")); LocalDateTime createdAt = reportTime != null ? reportTime : LocalDateTime.now(); req.put("createdDateTime", MOMENT_DATE_TIME.format(createdAt)); req.put("pointCurveData", pointCurveData != null ? pointCurveData : new ArrayList<>()); return req; } public static Map buildIntervalCurveDataEntry(int rid, List> values) { Map entry = new LinkedHashMap<>(); entry.put("rID", rid); Map irregular = new LinkedHashMap<>(); irregular.put("values", values != null ? values : new ArrayList<>()); entry.put("irregular", irregular); return entry; } public static Map buildIntervalCurveValue(BigDecimal value, LocalDateTime timestamp, String quality) { Map point = new LinkedHashMap<>(); point.put("value", value != null ? value : BigDecimal.ZERO); point.put("timestamp", MOMENT_DATE_TIME.format(timestamp != null ? timestamp : LocalDateTime.now())); point.put("quality", StringUtils.hasText(quality) ? quality : "good"); return point; } public static Map buildMomentDataReportRequest(VppUnProperties properties, Map createReportRequest, List> pointData, LocalDateTime reportTime) { Map req = buildBaseRequest("MomentDataReportRequest", properties); req.put("reportRequestID", resolveReportRequestIdFromPoll(createReportRequest, "MomentDataReport")); LocalDateTime createdAt = reportTime != null ? reportTime : LocalDateTime.now(); req.put("createdDateTime", MOMENT_DATE_TIME.format(createdAt)); req.put("pointData", pointData != null ? pointData : new ArrayList<>()); return req; } public static Map buildMomentDataPoint(int rid, BigDecimal value, LocalDateTime timestamp, String quality) { Map point = new LinkedHashMap<>(); point.put("rID", rid); point.put("value", value != null ? value : BigDecimal.ZERO); point.put("timestamp", MOMENT_DATE_TIME.format(timestamp != null ? timestamp : LocalDateTime.now())); point.put("quality", StringUtils.hasText(quality) ? quality : "good"); return point; } public static Map buildLoadForecastReportRequest(Map createReportRequest, List resources, Map siteMap, VppUnProperties properties) { Map req = buildBaseRequest("LoadForecastReportRequest", properties); req.put("reportRequestID", resolveReportRequestIdFromPoll(createReportRequest, "LoadForecastReport")); req.put("createdDateTime", CREATED_DATE_TIME.format(LocalDateTime.now())); req.put("pointData", buildPointData(resources, siteMap, properties)); return req; } public static Map buildRegulateForecastReportRequest(Map createReportRequest, List resources, Map siteMap, VppUnProperties properties) { Map req = buildBaseRequest("RegulateForecastReportRequest", properties); req.put("reportRequestID", resolveReportRequestIdFromPoll(createReportRequest, "RegulateForecastReport")); req.put("createdDateTime", CREATED_DATE_TIME.format(LocalDateTime.now())); req.put("pointData", buildPointData(resources, siteMap, properties)); return req; } private static Map buildVppMetadataReportItem(int rid, VppUnRegisterMetricDefinitions.RegisterMetric metric, String resourceId, String createdDateTime) { Map report = new LinkedHashMap<>(); report.put("createdDateTime", createdDateTime); Map description = new LinkedHashMap<>(); description.put("rID", rid); Map metricBody = new LinkedHashMap<>(); metricBody.put("metricName", metric.getMetricName()); if (StringUtils.hasText(metric.getMultiplier())) { metricBody.put("multiplier", metric.getMultiplier()); } metricBody.put("symbol", metric.getSymbol()); description.put("metric", metricBody); Map dataSource = new LinkedHashMap<>(); dataSource.put("resourceID", java.util.Collections.singletonList(resourceId)); description.put("reportDataSource", dataSource); report.put("reportDescription", description); return report; } private static List> buildPointData(List resources, Map siteMap, VppUnProperties properties) { List> pointData = new ArrayList<>(); if (resources == null || resources.isEmpty()) { Map point = new LinkedHashMap<>(); point.put("resourceID", properties.getDnId()); point.put("value", "0"); point.put("timestamp", CREATED_DATE_TIME.format(LocalDateTime.now())); pointData.add(point); return pointData; } String timestamp = CREATED_DATE_TIME.format(LocalDateTime.now()); for (VppResourcePoint resource : resources) { Map point = new LinkedHashMap<>(); VppSite site = siteMap != null ? siteMap.get(resource.getSiteId()) : null; point.put("resourceID", resolveUnResourceId(resource, site, properties)); BigDecimal value = resource.getMaxUpKw() != null ? resource.getMaxUpKw() : BigDecimal.ZERO; point.put("value", value.stripTrailingZeros().toPlainString()); point.put("timestamp", timestamp); pointData.add(point); } return pointData; } private static String resolveUnResourceId(VppResourcePoint resource, VppSite site, VppUnProperties properties) { if (site != null && StringUtils.hasText(site.getUnResourceId())) { return site.getUnResourceId(); } if (StringUtils.hasText(resource.getResourceCode())) { return resource.getResourceCode(); } return properties.getDnId(); } @SuppressWarnings("unchecked") private static String resolveReportRequestIdFromPoll(Map createReportRequest, String fallback) { if (createReportRequest == null) { return fallback; } Object reportRequest = createReportRequest.get("reportRequest"); if (reportRequest instanceof List && !((List) reportRequest).isEmpty()) { Object first = ((List) reportRequest).get(0); if (first instanceof Map) { String id = VppUnPayloadHelper.getString((Map) first, "reportRequestID", "reportRequestId"); if (StringUtils.hasText(id)) { return id; } } } String id = VppUnPayloadHelper.getString(createReportRequest, "reportRequestID", "reportRequestId"); return StringUtils.hasText(id) ? id : fallback; } public static Map buildOptListItem(String account, BigDecimal loadKw, String needZk) { Map item = new LinkedHashMap<>(); item.put("account", account); item.put("load", loadKw != null ? loadKw.stripTrailingZeros().toPlainString() : "0"); if (StringUtils.hasText(needZk)) { item.put("needzk", needZk); } return item; } private static Map buildBaseRequest(String root, VppUnProperties properties) { Map req = new LinkedHashMap<>(); req.put("root", root); req.put("version", 1); req.put("requestID", UUID.randomUUID().toString()); req.put("dnID", properties.getDnId()); return req; } public static Map buildCreateOptResponse(Map request, VppUnProperties properties) { Map resp = copyRequestAsResponse(request, "CreateOptResponse"); fillCommon(resp, properties); resp.put("code", 200); resp.put("description", "ok"); return resp; } public static Map buildCreateCqResponse(Map request, VppUnProperties properties) { Map resp = copyRequestAsResponse(request, "CreateCqResponse"); fillCommon(resp, properties); resp.put("code", 200); resp.put("description", "ok"); return resp; } public static Map buildCreateEventResponse(String eventId, String requestId, String optType, VppUnProperties properties) { Map resp = new LinkedHashMap<>(); resp.put("root", "CreateEventResponse"); resp.put("version", 1); resp.put("code", 200); resp.put("description", "ok"); resp.put("requestID", requestId != null ? requestId : UUID.randomUUID().toString()); resp.put("dnID", properties.getDnId()); Map eventResponse = new LinkedHashMap<>(); eventResponse.put("optType", optType != null ? optType : "optIn"); eventResponse.put("code", 200); eventResponse.put("description", "ok"); eventResponse.put("requestID", UUID.randomUUID().toString()); Map qualifiedEventId = new HashMap<>(); qualifiedEventId.put("eventID", eventId); qualifiedEventId.put("modificationNumber", 0); eventResponse.put("qualifiedEventID", qualifiedEventId); List> eventResponses = new ArrayList<>(); eventResponses.add(eventResponse); resp.put("eventResponses", eventResponses); return resp; } private static Map copyRequestAsResponse(Map request, String root) { Map resp = new LinkedHashMap<>(); if (request != null) { resp.putAll(request); } resp.put("root", root); resp.put("version", request != null && request.get("version") != null ? request.get("version") : 1); return resp; } private static void fillCommon(Map resp, VppUnProperties properties) { if (resp.get("requestID") == null) { resp.put("requestID", UUID.randomUUID().toString()); } resp.put("dnID", properties.getDnId()); } }