diff --git a/jsowell-admin/src/main/java/com/jsowell/api/thirdparty/JiLinPlatformController.java b/jsowell-admin/src/main/java/com/jsowell/api/thirdparty/JiLinPlatformController.java index c277ec313..e8f64430b 100644 --- a/jsowell-admin/src/main/java/com/jsowell/api/thirdparty/JiLinPlatformController.java +++ b/jsowell-admin/src/main/java/com/jsowell/api/thirdparty/JiLinPlatformController.java @@ -6,10 +6,7 @@ import com.jsowell.common.enums.thirdparty.ThirdPartyReturnCodeEnum; import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.response.RestApiResponse; -import com.jsowell.pile.dto.QueryEquipmentDTO; -import com.jsowell.pile.dto.QueryOperatorInfoDTO; -import com.jsowell.pile.dto.QueryStartChargeDTO; -import com.jsowell.pile.dto.QueryStationInfoDTO; +import com.jsowell.pile.dto.*; import com.jsowell.pile.thirdparty.CommonParamsDTO; import com.jsowell.thirdparty.lianlian.common.CommonResult; import com.jsowell.thirdparty.platform.service.ThirdPartyPlatformService; @@ -236,6 +233,158 @@ public class JiLinPlatformController extends ThirdPartyBaseController{ } + /** + * 查询业务策略信息 + * + * @param dto + */ + @RequestMapping("/v1/query_equip_business_policy") + public CommonResult query_equip_business_policy(HttpServletRequest request , @RequestBody CommonParamsDTO dto) { + logger.info("{}-查询业务策略信息 params:{}" , platformName , JSON.toJSONString(dto)); + try { + // 校验令牌 + if (!verifyToken(request.getHeader("Authorization"))) { + // 校验失败 + return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR); + } + + // 校验签名 + if (!verifySignature(dto)) { + // 签名错误 + return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR); + } + + // 解析入参 + QueryStartChargeDTO queryStartChargeDTO = parseParamsDTO(dto , QueryStartChargeDTO.class); + + // 执行逻辑 + Map map = platformLogic.queryEquipBusinessPolicy(queryStartChargeDTO); + logger.info("{}-查询业务策略信息 result:{}" , platformName , map); + return CommonResult.success(0 , "查询业务策略信息成功!" , map.get("Data") , map.get("Sig")); + } catch (Exception e) { + logger.info("{}-查询业务策略信息 error:" , platformName , e); + } + return CommonResult.failed("查询业务策略信息发生异常"); + } + + + + + /** + * 查询充电状态 + * http://localhost:8080/xindiantu/query_equip_charge_status/{startChargeSeq} + * @param dto + * @return + */ + @PostMapping("/v1/query_equip_charge_status") + public CommonResult query_equip_charge_status(HttpServletRequest request, @RequestBody CommonParamsDTO dto) { + logger.info("{}-查询充电状态 params:{}", platformName, JSON.toJSONString(dto)); + try { + // 校验令牌 + if (!verifyToken(request.getHeader("Authorization"))) { + // 校验失败 + return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR); + } + dto.setPlatformType(platformType); + + // 校验签名 + if (!verifySignature(dto)) { + // 签名错误 + return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR); + } + + // 解析入参 + QueryEquipChargeStatusDTO queryEquipChargeStatusDTO = parseParamsDTO(dto, QueryEquipChargeStatusDTO.class); + + // 执行逻辑 + Map map = platformLogic.queryEquipChargeStatus(queryEquipChargeStatusDTO); + logger.info("{}-查询充电状态 result:{}", platformName, map); + return CommonResult.success(Integer.parseInt(map.get("Ret")), map.get("Msg"), map.get("Data"), map.get("Sig")); + } catch (Exception e) { + logger.error("{}-查询充电状态 error:", platformName, e); + } + return CommonResult.failed("查询充电状态发生异常"); + + } + + + + + /** + * 请求停止充电 + * + * @param request + * @param dto + * @return + */ + @PostMapping("/v1/stop_charge") + public CommonResult query_stop_charge(HttpServletRequest request, @RequestBody CommonParamsDTO dto) { + logger.info("{}-请求停止充电 params :{}", platformName, JSON.toJSONString(dto)); + try { + // 校验令牌 + if (!verifyToken(request.getHeader("Authorization"))) { + // 校验失败 + return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR); + } + + // 校验签名 + if (!verifySignature(dto)) { + // 签名错误 + return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR); + } + + // 解析入参 + QueryStartChargeDTO queryStartChargeDTO = parseParamsDTO(dto, QueryStartChargeDTO.class); + logger.info("{}-请求停止充电 params :{}", platformName, JSON.toJSONString(dto)); + // 执行逻辑 + Map map = platformLogic.queryStopCharge(queryStartChargeDTO); + + return CommonResult.success(0, "请求停止充电成功!", map.get("Data"), map.get("Sig")); + } catch (Exception e) { + logger.error("{}-请求停止充电 error", platformName, e); + } + return CommonResult.failed("{}-请求停止充电发生异常"); + } + + + /** + * 统计信息查询 query_station_stats + * + * @param request + * @param dto + * @return + */ + @PostMapping("/v1/query_station_stats") + public CommonResult query_station_stats(HttpServletRequest request , @RequestBody CommonParamsDTO dto) { + logger.info("{}-查询统计信息 params:{}" , platformName , JSON.toJSONString(dto)); + try { + // 校验令牌 + if (!verifyToken(request.getHeader("Authorization"))) { + // 校验失败 + return CommonResult.failed(ThirdPartyReturnCodeEnum.TOKEN_ERROR); + } + + // 校验签名 + if (!verifySignature(dto)) { + // 签名错误 + return CommonResult.failed(ThirdPartyReturnCodeEnum.SIGN_ERROR); + } + + // 解析入参 + QueryStationInfoDTO queryStationInfoDTO = parseParamsDTO(dto , QueryStationInfoDTO.class); + // 执行逻辑 + Map map = platformLogic.queryStationStats(queryStationInfoDTO); + logger.info("{}-查询统计信息 result:{}" , platformName , map); + return CommonResult.success(0 , "查询统计信息成功!" , map.get("Data") , map.get("Sig")); + } catch (Exception e) { + logger.info("{}-查询统计信息 error:" , platformName , e); + } + return CommonResult.failed("查询统计信息发生异常"); + } + + + + /** * 推送启动充电结果 @@ -262,5 +411,4 @@ public class JiLinPlatformController extends ThirdPartyBaseController{ return response; } - } diff --git a/jsowell-common/src/main/java/com/jsowell/common/util/DateUtils.java b/jsowell-common/src/main/java/com/jsowell/common/util/DateUtils.java index 0fb72ba21..a7fecf48d 100644 --- a/jsowell-common/src/main/java/com/jsowell/common/util/DateUtils.java +++ b/jsowell-common/src/main/java/com/jsowell/common/util/DateUtils.java @@ -1196,4 +1196,16 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { ).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } + + /** + * 将字符串yyyy-MM-dd格式的日期转换为yyyy-MM-dd HH:mm:ss格式的日期字符串 + * @param dateStr + * @return + */ + public static String convertDateToDateTime(String dateStr) { + LocalDate endLocalDate = LocalDate.parse(dateStr); + LocalDateTime endLocalDateTime = endLocalDate.atStartOfDay(); + return endLocalDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + } + } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryEquipChargeStatusDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryEquipChargeStatusDTO.java index 76f041a16..d63c04a19 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryEquipChargeStatusDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryEquipChargeStatusDTO.java @@ -17,6 +17,6 @@ public class QueryEquipChargeStatusDTO { @JsonProperty(value = "OperatorID") private String OperatorID; - @JsonProperty(value = "orderNo") + @JsonProperty(value = "OrderNo") private String orderNo; } diff --git a/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryStartChargeDTO.java b/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryStartChargeDTO.java index b40467aa4..1590e464f 100644 --- a/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryStartChargeDTO.java +++ b/jsowell-pile/src/main/java/com/jsowell/pile/dto/QueryStartChargeDTO.java @@ -103,6 +103,6 @@ public class QueryStartChargeDTO { /** * 充电订单号 格式“运营商ID+唯一编号” */ - @JsonProperty(value = "OrderNO") - private String orderNO; + @JsonProperty(value = "OrderNo") + private String orderNo; } diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryChargingStatusVO.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryChargingStatusVO.java index f7af4c37b..3c01d985a 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryChargingStatusVO.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryChargingStatusVO.java @@ -147,6 +147,46 @@ public class QueryChargingStatusVO { @JSONField(name = "ChargeDetails") private List chargeDetails; + + /** + * 充电订单号 + */ + @JSONField(name = "OrderNo") + private String orderNo; + + /** + * 标识状态 + */ + @JSONField(name = "SuccStat") + private int succStat; + + /** + * 充电订单状态 + */ + @JSONField(name = "OrderStatus") + private int orderStatus; + + /** + * 充电站编码 + */ + @JSONField(name = "StationID") + private String stationID; + + /** + * 充电设备编码(桩号) + */ + @JSONField(name = "EquipmentID") + private String equipmentID; + + /** + * 推送时间 + */ + @JSONField(name = "PushTimeStamp") + private String pushTimeStamp; + + + + /** * 充电明细信息体 */ diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryStartChargeVO.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryStartChargeVO.java index 8e3ee83b8..95d9c6bff 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryStartChargeVO.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/lianlian/vo/QueryStartChargeVO.java @@ -52,20 +52,20 @@ public class QueryStartChargeVO { /** * 充电订单号 */ - @JSONField(name = "orderNo") + @JSONField(name = "OrderNo") private String orderNo; /** * 充电订单状态 * 1:启动中; 2:充电中; 3:停止中; 4:充电完成;5:订单挂起;6:充电异常 结束;7:启动失败 */ - @JSONField(name = "orderStatus") + @JSONField(name = "OrderStatus") private Integer orderStatus; /** * 充电启动超时时间 */ - @JSONField(name = "overTime") + @JSONField(name = "OverTime") private Integer overTime; /** diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/StationStatusInfo.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/StationStatusInfo.java new file mode 100644 index 000000000..58cacc130 --- /dev/null +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/domain/StationStatusInfo.java @@ -0,0 +1,27 @@ +package com.jsowell.thirdparty.platform.domain; + +import com.alibaba.fastjson2.annotation.JSONField; +import com.jsowell.thirdparty.lianlian.domain.ConnectorStatusInfo; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.List; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class StationStatusInfo implements Serializable { + private static final long serialVersionUID = 1L; + + @JSONField(name = "StationId") + private String stationId; + + @JSONField(name = "ConnectorStatusInfos") + private List connectorStatusInfos; + + +} diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/dto/ChargeOrderInfoDTO.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/dto/ChargeOrderInfoDTO.java new file mode 100644 index 000000000..cf5cfc1ef --- /dev/null +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/dto/ChargeOrderInfoDTO.java @@ -0,0 +1,310 @@ +package com.jsowell.thirdparty.platform.dto; + +import com.alibaba.fastjson2.annotation.JSONField; + +import com.jsowell.thirdparty.platform.domain.SupChargeDetails; +import lombok.AllArgsConstructor; +import lombok.Builder; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class ChargeOrderInfoDTO implements Serializable { + private static final long serialVersionUID = 1L; + /** + * 平台运营商ID + * OperatorID + * 充换电平台运营商ID + * 是 + * 字符串 + * 9字符 + */ + @JSONField(name = "OperatorID") + private String operatorID; + + /** + * 设备分类 + * 1:车辆充电设备 + * 2:换电站内的电池箱充电设备 + */ + @JSONField(name = "EquipmentClassification") + private Integer equipmentClassification; + + + /** + * 设备所属方 + * IDEquipmentOwnerID + * 场站属主的组织机构代码 + * 是 + * 字符串 + * 9字符 + */ + @JSONField(name = "EquipmentOwnerID") + private String equipmentOwnerID; + + /** + * 充电站 + * IDStationID + * 运营商自定义的唯一编码 + * 是 + * 字符串 + * ≤64字符 + */ + @JSONField(name = "StationID") + private String stationID; + + /** + * 充电设备 + * IDEquipmentID + * 充电设备唯一标识,运营商自定义,同一个OperatorID内唯一 + * 是 + * 字符串 + * ≤64字符 + */ + @JSONField(name = "EquipmentID") + private String equipmentID; + + /** + * 充电订单号 + * OrderNo + * 格式“运营商ID+唯一编号”,不超过64个字符 + * 是 + * 字符串 + * ≤64字符 + */ + @JSONField(name = "OrderNo") + private String orderNo; + + /** + * 充电接口唯一标识 + * ConnectorID + * 充电接口唯一标识,运营商自定义,同一个OperatorID内唯一 + * 是 + * 字符串 + * ≤64字符 + */ + @JSONField(name = "ConnectorID") + private String connectorID; + + /** + * 车牌号 + * LicensePlate + * 否 + * 字符串 + * ≤20字符 + */ + @JSONField(name = "LicensePlate") + private String licensePlate; + + /** + * 车辆唯一识别码 + * VIN + * 参照GB/T27930标准规定 + * 否 + * 字符串 + * ≤17个字符 + */ + @JSONField(name = "VIN") + private String vin; + + + /** + * 本单开始充电时间 + * StartTime + * yyyy-MM-ddHH:mm:ss + * 是 + * 字符串 + * ≤24字符 + */ + @JSONField(name = "StartTime") + private String startTime; + + /** + * 结束充电时间 + * EndTime + * yyyy-MM-ddHH:mm:ss + * 是 + * 字符串 + * ≤24字符 + */ + @JSONField(name = "EndTime") + private String endTime; + + /** + * 累计充电量 + * TotalPower + * 单位kWh + * 是 + * 浮点数≤8字符,小数点后4位 + */ + @JSONField(name = "TotalPower") + private BigDecimal totalPower; + + /** + * 尖阶段电量 + * CuspElect + * 单位kWh + * 否 + * 浮点型 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "CuspElect") + private BigDecimal cuspElect; + + /** + * 峰阶段电量 + * PeakElect + * 单位kWh + * 否 + * 浮点型 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "PeakElect") + private BigDecimal peakElect; + + /** + * 平阶段电量 + * FlatElect + * 单位kWh + * 否 + * 浮点型 + * ≤8字符 + */ + @JSONField(name = "FlatElect") + private BigDecimal flatElect; + + /** + * 谷阶段电量 + * ValleyElect + * 单位kWh + * 否 + * 浮点型 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "ValleyElect") + private BigDecimal valleyElect; + + /** + * 推送时间 + * PushTimeStamp + * yyyy-MM-ddHH:mm:ss,充电设备推送给运营商平台时间 + * 是 + * 字符串 + * ≤24字符 + */ + @JSONField(name = "PushTimeStamp") + private String pushTimeStamp; + + /** + * 总电费 + * TotalElecMoney + * 本单总电费,单位:元,小数点后4位 + * 是 + * 浮点数 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "TotalElecMoney") + private BigDecimal totalElecMoney; + + /** + * 总服务费 + * TotalSeviceMoney + * 本单总服务费,单位:元,小数点后4位 + * 是 + * 浮点数 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "TotalSeviceMoney") + private BigDecimal totalSeviceMoney; + + /** + * 总服务费 + * TotalSeviceMoney + * 本单总服务费,单位:元,小数点后4位 + * 是 + * 浮点数 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "TotalServiceMoney") + private BigDecimal totalServiceMoney; + + /** + * 累计总金额 + * TotalMoney + * 本单总金额,单位:元,小数点后4位 + * 是 + * 浮点数 + * ≤8字符,小数点后4位 + */ + @JSONField(name = "TotalMoney") + private BigDecimal totalMoney; + + /** + * 充电结束原因 + * StopReason + * 0:用户手动停止充电1:客户归属地运营商平台停止充电2:BMS停止充电3:充电机设备故障4:连接器断开5~99:自定义 + * 是 + * 整型 + * ≤4字符 + */ + @JSONField(name = "StopReason") + private Integer stopReason; + + /** + * 充电结束原因描述 + * StopDesc + * 充电结束原因为自定义时必填 + * 是 + * 字符串 + * ≤500字符 + */ + @JSONField(name = "StopDesc") + private String stopDesc; + + /** + * 时段数 + * SumPeriod + * 此单跨越的分段计价的不同时段,范围:0~32 + * 否 + * 整型 + * ≤2字符 + */ + @JSONField(name = "SumPeriod") + private Integer sumPeriod; + + /** + * 充电明细信息列表 + * ChargeDetails + * 详见充电明细信息(SupChargeDetails) + * 否 + * SupChargeDetails数组 + */ + @JSONField(name = "ChargeDetails") + private List chargeDetails; + + + /** + * 充电开始 Soc + * 保留一位小数 + */ + @JSONField(name = "StartSoc") + private BigDecimal startSoc; + + /** + * 充电结束 Soc + * 保留一位小数 + */ + @JSONField(name = "EndSoc") + private BigDecimal endSoc; + + + +} diff --git a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/JiLinPlatformServiceImpl.java b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/JiLinPlatformServiceImpl.java index af8ddd709..ec75d07f3 100644 --- a/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/JiLinPlatformServiceImpl.java +++ b/jsowell-thirdparty/src/main/java/com/jsowell/thirdparty/platform/service/impl/JiLinPlatformServiceImpl.java @@ -9,12 +9,10 @@ import com.google.common.collect.Maps; import com.jsowell.common.constant.Constants; import com.jsowell.common.core.domain.ykc.RealTimeMonitorData; import com.jsowell.common.enums.lianlian.LianLianPileStatusEnum; +import com.jsowell.common.enums.lianlian.PayChannelEnum; import com.jsowell.common.enums.thirdparty.BusinessInformationExchangeEnum; import com.jsowell.common.enums.thirdparty.ThirdPlatformTypeEnum; -import com.jsowell.common.enums.ykc.OrderStatusEnum; -import com.jsowell.common.enums.ykc.PileConnectorDataBaseStatusEnum; -import com.jsowell.common.enums.ykc.PileStatusEnum; -import com.jsowell.common.enums.ykc.ReturnCodeEnum; +import com.jsowell.common.enums.ykc.*; import com.jsowell.common.exception.BusinessException; import com.jsowell.common.util.*; import com.jsowell.pile.domain.*; @@ -26,26 +24,25 @@ import com.jsowell.pile.thirdparty.*; import com.jsowell.pile.thirdparty.EquipmentInfoDTO; import com.jsowell.pile.thirdparty.dto.ConnectorInfoDTO; import com.jsowell.pile.util.MerchantUtils; +import com.jsowell.pile.vo.SupStationStatsVO; import com.jsowell.pile.vo.ThirdPartySecretInfoVO; import com.jsowell.pile.vo.base.ConnectorInfoVO; import com.jsowell.pile.vo.base.MerchantInfoVO; import com.jsowell.pile.vo.base.ThirdPartyStationInfoVO; +import com.jsowell.pile.vo.lianlian.AccumulativeInfoVO; import com.jsowell.pile.vo.uniapp.customer.BillingPriceVO; import com.jsowell.pile.vo.web.PileConnectorInfoVO; import com.jsowell.pile.vo.web.PileMerchantInfoVO; import com.jsowell.pile.vo.web.PileModelInfoVO; import com.jsowell.pile.vo.web.PileStationVO; import com.jsowell.pile.vo.zdl.EquipBusinessPolicyVO; -import com.jsowell.thirdparty.lianlian.domain.ConnectorStatusInfo; -import com.jsowell.thirdparty.lianlian.domain.StationStatusInfo; -import com.jsowell.thirdparty.lianlian.vo.AccessTokenVO; -import com.jsowell.thirdparty.lianlian.vo.EquipmentAuthVO; -import com.jsowell.thirdparty.lianlian.vo.QueryChargingStatusVO; -import com.jsowell.thirdparty.lianlian.vo.QueryStartChargeVO; -import com.jsowell.thirdparty.platform.domain.ChargeOrderInfo; -import com.jsowell.thirdparty.platform.domain.SupConnectorStatusInfo; -import com.jsowell.thirdparty.platform.domain.SupOperatorInfo; -import com.jsowell.thirdparty.platform.domain.SupStationInfo; +import com.jsowell.thirdparty.lianlian.domain.*; +import com.jsowell.thirdparty.lianlian.vo.*; +import com.jsowell.thirdparty.platform.common.ChargeDetail; +import com.jsowell.thirdparty.platform.common.OrderInfo; +import com.jsowell.thirdparty.platform.domain.*; +import com.jsowell.thirdparty.platform.domain.StationStatusInfo; +import com.jsowell.thirdparty.platform.dto.ChargeOrderInfoDTO; import com.jsowell.thirdparty.platform.dto.SupStationInfoDTO; import com.jsowell.thirdparty.platform.factory.ThirdPartyPlatformFactory; import com.jsowell.thirdparty.platform.service.ThirdPartyPlatformService; @@ -57,12 +54,21 @@ import com.yi.business.geo.GeoCodeInfo; import com.yi.business.geo.TermRelationTreeCoordinate; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; +import org.bouncycastle.crypto.CryptoException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.Serializable; import java.math.BigDecimal; import java.math.RoundingMode; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.spec.InvalidKeySpecException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.logging.Logger; import java.util.stream.Collectors; @Service @@ -457,11 +463,11 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { // 调用中电联平台接口 String url = urlAddress + "notification_station_info"; - JSONObject data = new JSONObject(); - data.put("SupStationInfos", stationInfos); +/* JSONObject data = new JSONObject(); + data.put("StationInfo", stationInfos);*/ + + String jsonString = JSON.toJSONString(stationInfos); - String jsonString = JSON.toJSONString(data); - System.out.println("jsonString : " + jsonString); // 获取令牌 String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); @@ -514,9 +520,23 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { } } + List stationStatusInfos = new ArrayList<>(); + for (String stationId : stationIds) { + //每个站点对应的充电设备接口状态列表 + StationStatusInfo stationStatusInfo = new StationStatusInfo(); + List connectorStatusInfoList = new ArrayList<>(); + for (Object connectorStatusInfo : connectorStatusInfos) { + if (((ConnectorStatusInfo) connectorStatusInfo).getStationId().equals(stationId)){ + connectorStatusInfoList.add((ConnectorStatusInfo) connectorStatusInfo); + } + } + stationStatusInfo.setStationId(stationId); + stationStatusInfo.setConnectorStatusInfos(connectorStatusInfoList); + stationStatusInfos.add(stationStatusInfo); + } + Map map = new LinkedHashMap<>(); - map.put("StationID", stationIds); - map.put("ConnectorStatusInfos", connectorStatusInfos); + map.put("StationStatusInfos", stationStatusInfos); Map resultMap = ThirdPartyPlatformUtils.generateResultMap(map, thirdPartySecretInfoVO.getOurDataSecret(), thirdPartySecretInfoVO.getOurDataSecretIv(), thirdPartySecretInfoVO.getTheirSigSecret()); @@ -689,7 +709,7 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { String failReasonMsg = ""; //失败原因 //吉林平台使用orderNo字段接收订单号 - String orderNO = dto.getOrderNO(); + String orderNO = dto.getOrderNo(); //设置到原本的订单号字段 dto.setStartChargeSeq(orderNO); @@ -773,9 +793,9 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { String url = urlAddress + BusinessInformationExchangeEnum.NOTIFICATION_START_CHARGE_RESULT.getValue(); // 拼装参数 JSONObject json = new JSONObject(); - json.put("orderNo", orderCode); + json.put("OrderNo", orderCode); json.put("ConnectorID", orderInfo.getPileConnectorCode()); - json.put("orderStatus", 2); // 一定要给 2-充电中 + json.put("OrderStatus", 2); // 一定要给 2-充电中 json.put("StartTime", DateUtils.getDateTime()); // 充电开始时间 json.put("PushTimeStamp", DateUtils.getDateTime()); // 推送时间 @@ -798,6 +818,8 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { @Override public Map queryEquipChargeStatus(QueryEquipChargeStatusDTO dto) { String operatorID = dto.getOperatorID(); + String orderNo = dto.getOrderNo(); + dto.setStartChargeSeq(orderNo); // 通过订单号查询订单信息 OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(dto.getStartChargeSeq()); // logger.info(operatorName + "查询订单信息 orderInfo:{}", orderInfo); @@ -820,8 +842,11 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { }else if (StringUtils.equals(orderStatus, OrderStatusEnum.ORDER_COMPLETE.getValue())) { // 充电完成 orderStatus = "4"; + } else if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { + // 未开始充电 + orderStatus= "7"; //启动失败 } else { - // 直接给 5-未知 + // 直接给 5-订单挂起 orderStatus = "5"; } String status = data.getConnectorStatus(); @@ -837,24 +862,29 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { connectorStatus = Integer.parseInt(PileConnectorDataBaseStatusEnum.FAULT.getValue()); } String soc = data.getSOC() == null ? Constants.ZERO : data.getSOC(); + BigDecimal totalElectricityAmount = orderDetail.getTotalElectricityAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalElectricityAmount(); BigDecimal totalServiceAmount = orderDetail.getTotalServiceAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalServiceAmount(); + BigDecimal current = data.getOutputCurrent() == null ? BigDecimal.ZERO : new BigDecimal(data.getOutputCurrent()); + BigDecimal voltage = data.getOutputVoltage() == null ? BigDecimal.ZERO : new BigDecimal(data.getOutputVoltage()); + BigDecimal totalPower = data.getChargingDegree() == null ? BigDecimal.ZERO : new BigDecimal(data.getChargingDegree()); + BigDecimal totalMoney = data.getChargingAmount() == null ? BigDecimal.ZERO : new BigDecimal(data.getChargingAmount()); // 拼装联联平台数据 vo = QueryChargingStatusVO.builder() - .startChargeSeq(dto.getStartChargeSeq()) // 订单号 - .startChargeSeqStat(Integer.parseInt(orderStatus)) // 订单状态 + .orderNo(orderInfo.getOrderCode()) //订单号 + .succStat(0) // 成功状态 + .orderStatus(Integer.parseInt(orderStatus)) // 订单状态 .connectorID(orderInfo.getPileConnectorCode()) // 枪口编码 .connectorStatus(connectorStatus) // 枪口状态 - .currentA(new BigDecimal(data.getOutputCurrent())) // 电流 - .voltageA(new BigDecimal(data.getOutputVoltage())) // 电压 - .soc(new BigDecimal(soc)) + .currentA(current.setScale(1, BigDecimal.ROUND_HALF_UP)) // 电流 + .voltageA(voltage.setScale(1, BigDecimal.ROUND_HALF_UP)) // 电压 + .soc(new BigDecimal(soc).setScale(1, BigDecimal.ROUND_HALF_UP)) .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime())) // 开始时间 .endTime(DateUtils.getDateTime()) // 本次采样时间 - .totalPower(new BigDecimal(data.getChargingDegree()).setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计充电量 + .totalPower(totalPower.setScale(3, BigDecimal.ROUND_HALF_UP)) // 累计充电量 .elecMoney(totalElectricityAmount.setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计电费 .seviceMoney(totalServiceAmount.setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计服务费 - .totalMoney(new BigDecimal(data.getChargingAmount())) // 已充金额 - + .totalMoney(totalMoney.setScale(2, BigDecimal.ROUND_HALF_UP)) // 已充金额 .build(); } log.info("返回参数:{}", JSON.toJSONString(vo)); @@ -862,6 +892,731 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { } + /** + * 推送充电状态 notification_equip_charge_status + * @param orderCode 订单编号 + * @return + */ + @Override + public String notificationEquipChargeStatus(String orderCode) { + // 根据订单号查询订单信息 + OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderInfo.getOrderCode()); + // 查询枪口状态 + PileConnectorInfoVO info = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(orderInfo.getPileConnectorCode()); + + // 查询相关配置信息 + ThirdPartySecretInfoVO thirdPartySecretInfoVO = getJiLinSecretInfo(); + + String operatorId = Constants.OPERATORID_JIANG_SU; + String operatorSecret = thirdPartySecretInfoVO.getTheirOperatorSecret(); + String signSecret = thirdPartySecretInfoVO.getTheirSigSecret(); + String dataSecret = thirdPartySecretInfoVO.getTheirDataSecret(); + String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv(); + String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix(); + + // 通过订单号查询实时数据 + List realTimeData = orderBasicInfoService.getChargingRealTimeData(orderInfo.getTransactionCode()); + QueryChargingStatusVO vo; + if (CollectionUtils.isEmpty(realTimeData)) { + vo = new QueryChargingStatusVO(); + } else { + RealTimeMonitorData data = realTimeData.get(0); + String orderStatus = orderInfo.getOrderStatus(); + if (StringUtils.equals(orderStatus, OrderStatusEnum.IN_THE_CHARGING.getValue())) { + // 充电中 + orderStatus = "2"; + }else if (StringUtils.equals(orderStatus, OrderStatusEnum.ORDER_COMPLETE.getValue())) { + // 充电完成 + orderStatus = "4"; + } else if (StringUtils.equals(orderStatus, OrderStatusEnum.NOT_START.getValue())) { + // 未开始充电 + orderStatus= "7"; //启动失败 + } else { + // 直接给 5-订单挂起 + orderStatus = "5"; + } + String status = data.getConnectorStatus(); + int connectorStatus = 0; + if (StringUtils.isBlank(status)) { + // 查询当前枪口状态 + PileConnectorInfoVO connectorInfoVO = pileConnectorInfoService.getPileConnectorInfoByConnectorCode(orderInfo.getPileConnectorCode()); + connectorStatus = connectorInfoVO.getStatus(); + }else { + connectorStatus = Integer.parseInt(status); + } + if(connectorStatus == Integer.parseInt(PileConnectorDataBaseStatusEnum.OFF_NETWORK.getValue())){ + connectorStatus = Integer.parseInt(PileConnectorDataBaseStatusEnum.FAULT.getValue()); + } + String soc = data.getSOC() == null ? Constants.ZERO : data.getSOC(); + + //填写的是最终的电费和服务费 + BigDecimal totalElectricityAmount = orderDetail.getTotalElectricityAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalElectricityAmount(); + BigDecimal totalServiceAmount = orderDetail.getTotalServiceAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalServiceAmount(); + BigDecimal current = data.getOutputCurrent() == null ? BigDecimal.ZERO : new BigDecimal(data.getOutputCurrent()); + BigDecimal voltage = data.getOutputVoltage() == null ? BigDecimal.ZERO : new BigDecimal(data.getOutputVoltage()); + + // 拼装联联平台数据 + vo = QueryChargingStatusVO.builder() + .orderNo(orderInfo.getOrderCode()) //订单号 + .succStat(0) // 成功状态 + .orderStatus(Integer.parseInt(orderStatus)) // 订单状态 + .connectorID(orderInfo.getPileConnectorCode()) // 枪口编码 + .connectorStatus(connectorStatus) // 枪口状态 + .currentA(current.setScale(1, BigDecimal.ROUND_HALF_UP)) // 电流 + .voltageA(voltage.setScale(1, BigDecimal.ROUND_HALF_UP)) // 电压 + .soc(new BigDecimal(soc).setScale(1, BigDecimal.ROUND_HALF_UP)) + .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderInfo.getChargeStartTime())) // 开始时间 + .endTime(DateUtils.getDateTime()) // 本次采样时间 + .totalPower(new BigDecimal(data.getChargingDegree()).setScale(4, BigDecimal.ROUND_HALF_UP)) // 累计充电量 + .elecMoney(totalElectricityAmount.setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计电费 + .seviceMoney(totalServiceAmount.setScale(2, BigDecimal.ROUND_HALF_UP)) // 累计服务费 + .totalMoney(new BigDecimal(data.getChargingAmount()).setScale(2, BigDecimal.ROUND_HALF_UP)) // 已充金额 + .build(); + } + String url = urlAddress + BusinessInformationExchangeEnum.NOTIFICATION_EQUIP_CHARGE_STATUS.getValue(); + // 调用平台接口 + String jsonString = JSON.toJSONString(vo); + log.info("请求参数:{}", jsonString); + + String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); + String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + + return result; + } + + + /** + * 请求停止充电 query_stop_charge + * @param dto + * @return + */ + @Override + public Map queryStopCharge(QueryStartChargeDTO dto) { + //使用orderNo接收的数据 + String orderCode = dto.getOrderNo(); + + int orderStatus = 2; + int succStat = 1; + ThirdPartySecretInfoVO jiLinSecretInfo = getJiLinSecretInfo(); + // 根据订单号查询订单信息 + OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + if (orderInfo == null) { + return null; + } + // 若状态为充电中,则发送停机指令 + if (StringUtils.equals(OrderStatusEnum.IN_THE_CHARGING.getValue(), orderInfo.getOrderStatus())) { + // 充电中 + pileRemoteService.remoteStopCharging(orderInfo.getPileSn(), orderInfo.getConnectorCode(), orderInfo.getTransactionCode()); + orderStatus = 4; + succStat = 0; + } + JSONObject json = new JSONObject(); + json.put("OrderNo", orderCode); + json.put("OrderStatus", orderStatus); // 一定要给 2-充电中 + json.put("SuccStat",succStat); + json.put("OverTime",0); //充电停止超时时间 + + + log.info("请求参数:{}", JSON.toJSONString(json)); + return ThirdPartyPlatformUtils.generateResultMapV2(json, jiLinSecretInfo.getOurDataSecret() + , jiLinSecretInfo.getOurDataSecretIv(), jiLinSecretInfo.getOurSigSecret()); + } + + + /** + * 推送停止充电结果 notification_stop_charge_result + * @param orderCode 订单编号 + * @return + */ + @Override + public String notificationStopChargeResult(String orderCode) { + // 根据订单号查询订单信息 + OrderBasicInfo orderInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + if (orderInfo == null) { + return null; + } + ThirdPartySecretInfoVO getJiLinSecretInfo = getJiLinSecretInfo(); + String operatorId = Constants.OPERATORID_JIANG_SU; + String operatorSecret = getJiLinSecretInfo.getTheirOperatorSecret(); + String signSecret = getJiLinSecretInfo.getTheirSigSecret(); + String dataSecret = getJiLinSecretInfo.getTheirDataSecret(); + String dataSecretIv = getJiLinSecretInfo.getTheirDataSecretIv(); + String urlAddress = getJiLinSecretInfo.getTheirUrlPrefix(); + + String url = urlAddress + BusinessInformationExchangeEnum.NOTIFICATION_STOP_CHARGE_RESULT.getValue(); + + // 拼装联联平台参数 + JSONObject json = new JSONObject(); + json.put("OrderNo", orderCode); + json.put("OrderStatus", 4); // 只能给 4-已结束 + json.put("ConnectorID", orderInfo.getPileConnectorCode()); + json.put("PushTimeStamp", DateUtils.getDateTime()); + + String jsonString = JSON.toJSONString(json); + + log.info("请求参数:{}", jsonString); + + String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); + String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + + return result; + } + + + /** + * 订单信息推送 notification_orderInfo + * + * @param orderCode + * @throws UnsupportedOperationException 未实现异常 + */ + @Override + public String notificationChargeOrderInfo(String orderCode) { + // 根据订单号查询出信息 + OrderBasicInfo orderBasicInfo = orderBasicInfoService.getOrderInfoByOrderCode(orderCode); + OrderDetail orderDetail = orderBasicInfoService.getOrderDetailByOrderCode(orderCode); + // 通过站点id查询相关配置信息 + ThirdPartySecretInfoVO thirdPartySecretInfoVO = getJiLinSecretInfo(); + + String operatorId = Constants.OPERATORID_LIANLIAN; + String operatorSecret = thirdPartySecretInfoVO.getTheirOperatorSecret(); + String signSecret = thirdPartySecretInfoVO.getTheirSigSecret(); + String dataSecret = thirdPartySecretInfoVO.getTheirDataSecret(); + String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv(); + String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix(); + + String url = urlAddress + "notification_charge_order_info"; + + ChargeOrderInfoDTO chargeOrderInfo = transformChargeOrderInfo(orderBasicInfo , orderDetail); + + // 获取令牌 + String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); + if (StringUtils.isBlank(token)) { + return null; + } + + String jsonString = JSON.toJSONString(chargeOrderInfo); + + String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + return result; + } + + + /** + * 查询统计信息 query_station_stats + * + * @param dto 查询站点信息dto + * @throws UnsupportedOperationException 未实现异常 + */ + @Override + public Map queryStationStats(QueryStationInfoDTO dto) { + + ThirdPartySecretInfoVO thirdPartySecretInfoVO = getJiLinSecretInfo(); + String startTime = dto.getStartTime(); + String endTime = dto.getEndTime(); + String stationId = dto.getStationID(); + + //时间格式化 + startTime = DateUtils.convertDateToDateTime(startTime); + endTime = DateUtils.convertDateToDateTime(endTime); + + List orderBasicInfos; + try { + orderBasicInfos = orderBasicInfoService.queryOrderListByStationIdAndTime(stationId, startTime, endTime); + if (CollectionUtils.isEmpty(orderBasicInfos)) { + log.info("站点{}没有查询到前一日的订单信息", stationId); + return null; + } + log.info("站点{}查询到{}条订单信息", stationId, orderBasicInfos.size()); + } catch (Exception e) { + log.error("查询站点{}订单信息失败", stationId, e); + return null; + } + + // 3. 统计站点充电数据 + BigDecimal stationTotalElectricity = BigDecimal.ZERO; + int stationTotalChargeTime = 0; + String startChargeTime = null; + String endChargeTime = null; + + for (SupStationStatsVO orderVO : orderBasicInfos) { + // 处理用电量 + BigDecimal power = orderVO.getTotalPower(); + if (power != null) { + stationTotalElectricity = stationTotalElectricity.add(power); + } + + // 处理充电时长 + String start = orderVO.getStartTime(); + String end = orderVO.getEndTime(); + if (start != null && end != null) { + try { + long chargeTime = DateUtils.intervalTime(start, end); + stationTotalChargeTime += (int) chargeTime; + + // 更新统计开始和结束时间 + if (startChargeTime == null || start.compareTo(startChargeTime) < 0) { + startChargeTime = start; + } + if (endChargeTime == null || end.compareTo(endChargeTime) > 0) { + endChargeTime = end; + } + } catch (Exception e) { + log.error("计算订单{}充电时长失败", orderVO.getOrderCode(), e); + } + } + } + + // 如果未获取到统计开始或结束时间,使用默认值 + if (startChargeTime == null) { + startChargeTime = startTime; + } + if (endChargeTime == null) { + endChargeTime = endTime; + } + + // 4. 按枪口分组统计 + Map> collect = orderBasicInfos.stream() + .filter(vo -> vo.getPileConnectorCode() != null) // 仅过滤枪号为空的订单 + .collect(Collectors.groupingBy(SupStationStatsVO::getPileConnectorCode)); + TreeMap> sortedMap = new TreeMap<>(collect); + + + List equipmentStatsInfoList = new ArrayList<>(); + String currentPileSn = ""; // 当前处理的桩编号 + BigDecimal currentPilePower = BigDecimal.ZERO; // 当前桩的总电量 + int currentPileChargeTime = 0; // 当前桩的总充电时长 + List currentConnectorList = new ArrayList<>(); + + // 遍历每个枪口分组 + for (Map.Entry> entry : sortedMap.entrySet()) { + String pileConnectorCode = entry.getKey(); + List connectorOrders = entry.getValue(); + + // 处理该枪号下的所有订单 + for (SupStationStatsVO order : connectorOrders) { + // 创建并初始化枪口统计信息 + SupStationStatsInfo.EquipmentStatsInfo.ConnectorStatsInfo connectorStatsInfo = + new SupStationStatsInfo.EquipmentStatsInfo.ConnectorStatsInfo(); + connectorStatsInfo.setConnectorId(pileConnectorCode); + connectorStatsInfo.setEquipmentClassification(1); + + // 设置枪口用电量(如果不为空) + BigDecimal power = order.getTotalPower(); + if (power != null) { + connectorStatsInfo.setConnectorElectricity(power.setScale(1, RoundingMode.HALF_UP)); + } + + // 获取当前订单的桩编号(处理可能为空的情况) + String pileSn = order.getPileSn() != null ? order.getPileSn() : "unknown_pile"; + + // 检查是否需要创建新的桩统计信息 + if (!pileSn.equals(currentPileSn)) { + // 如果不是第一个桩,保存之前的桩统计信息 + if (!currentPileSn.isEmpty()) { + saveCurrentPileStats( + currentPileSn, + currentPilePower, + currentPileChargeTime, + currentConnectorList, + equipmentStatsInfoList + ); + } + + // 初始化新桩的统计信息 + currentPileSn = pileSn; + currentPilePower = BigDecimal.ZERO; + currentPileChargeTime = 0; + currentConnectorList = new ArrayList<>(); + } + + // 累加当前桩的总电量和总充电时长 + if (power != null) { + currentPilePower = currentPilePower.add(power); + } + + String startTimeStr = order.getStartTime(); + String endTimeStr = order.getEndTime(); + int chargeTime = 0; + + if (startTimeStr != null && endTimeStr != null) { + try { + chargeTime = (int) DateUtils.intervalTime(startTimeStr, endTimeStr); + currentPileChargeTime += chargeTime; + } catch (Exception e) { + log.error("计算订单{}充电时长失败", order.getOrderCode(), e); + } + } + connectorStatsInfo.setConnectorTotalChargeTime(chargeTime); + connectorStatsInfo.setConnectorTotalChargeNum(connectorOrders.size()); + connectorStatsInfo.setConnectorTotalWarningNum(0); + + currentConnectorList.add(connectorStatsInfo); + } + } + if (!currentPileSn.isEmpty() && !currentConnectorList.isEmpty()) { + saveCurrentPileStats( + currentPileSn, + currentPilePower, + currentPileChargeTime, + currentConnectorList, + equipmentStatsInfoList + ); + log.info("站点{}最终统计到{}个充电桩数据", stationId, equipmentStatsInfoList.size()); + } else { + log.warn("站点{}未统计到任何充电桩数据!", stationId); + } + + SupStationStatsInfo supStationStatsInfo = SupStationStatsInfo.builder() + .stationId(stationId) + .startTime(startChargeTime) + .endTime(endChargeTime) + .stationElectricity(stationTotalElectricity.setScale(2, BigDecimal.ROUND_HALF_UP)) + .stationTotalChargeNum(orderBasicInfos.size()) + .stationTotalChargeTime(stationTotalChargeTime) + .stationTotalWarningNum(0) + .equipmentStatsInfos(equipmentStatsInfoList) + .supEquipmentStatsInfos(equipmentStatsInfoList) + .build(); + + Map map = new LinkedHashMap<>(); + map.put("StationStats", supStationStatsInfo); + + Map resultMap = ThirdPartyPlatformUtils.generateResultMapV2(map, thirdPartySecretInfoVO.getOurDataSecret(), + thirdPartySecretInfoVO.getOurDataSecretIv(), thirdPartySecretInfoVO.getTheirSigSecret()); + return resultMap; + } + + + + @Override + public String notificationOperationStatsInfo(String stationId) { + // 1. 获取统计时间范围(前一日的00:00:00至23:59:59) + LocalDate yesterday = LocalDate.now().minusDays(1); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + LocalDateTime startOfYesterday = yesterday.atStartOfDay(); + LocalDateTime endOfYesterday = yesterday.atTime(23, 59, 59); + String startTime = startOfYesterday.format(formatter); + String endTime = endOfYesterday.format(formatter); + + // 2. 查询站点下时间段的订单 + List orderBasicInfos; + try { + orderBasicInfos = orderBasicInfoService.queryOrderListByStationIdAndTime(stationId, startTime, endTime); + if (CollectionUtils.isEmpty(orderBasicInfos)) { + log.info("站点{}没有查询到前一日的订单信息", stationId); + return null; + } + log.info("站点{}查询到{}条订单信息", stationId, orderBasicInfos.size()); + } catch (Exception e) { + log.error("查询站点{}订单信息失败", stationId, e); + return null; + } + + // 3. 统计站点充电数据 + BigDecimal stationTotalElectricity = BigDecimal.ZERO; + int stationTotalChargeTime = 0; + String startChargeTime = null; + String endChargeTime = null; + + for (SupStationStatsVO orderVO : orderBasicInfos) { + // 处理用电量 + BigDecimal power = orderVO.getTotalPower(); + if (power != null) { + stationTotalElectricity = stationTotalElectricity.add(power); + } + + // 处理充电时长 + String start = orderVO.getStartTime(); + String end = orderVO.getEndTime(); + if (start != null && end != null) { + try { + long chargeTime = DateUtils.intervalTime(start, end); + stationTotalChargeTime += (int) chargeTime; + + // 更新统计开始和结束时间 + if (startChargeTime == null || start.compareTo(startChargeTime) < 0) { + startChargeTime = start; + } + if (endChargeTime == null || end.compareTo(endChargeTime) > 0) { + endChargeTime = end; + } + } catch (Exception e) { + log.error("计算订单{}充电时长失败", orderVO.getOrderCode(), e); + } + } + } + + // 如果未获取到统计开始或结束时间,使用默认值 + if (startChargeTime == null) { + startChargeTime = startTime; + } + if (endChargeTime == null) { + endChargeTime = endTime; + } + + // 4. 按枪口分组统计 + Map> collect = orderBasicInfos.stream() + .filter(vo -> vo.getPileConnectorCode() != null) // 仅过滤枪号为空的订单 + .collect(Collectors.groupingBy(SupStationStatsVO::getPileConnectorCode)); + TreeMap> sortedMap = new TreeMap<>(collect); + + + List equipmentStatsInfoList = new ArrayList<>(); + String currentPileSn = ""; // 当前处理的桩编号 + BigDecimal currentPilePower = BigDecimal.ZERO; // 当前桩的总电量 + int currentPileChargeTime = 0; // 当前桩的总充电时长 + List currentConnectorList = new ArrayList<>(); + + // 遍历每个枪口分组 + for (Map.Entry> entry : sortedMap.entrySet()) { + String pileConnectorCode = entry.getKey(); + List connectorOrders = entry.getValue(); + + // 处理该枪号下的所有订单 + for (SupStationStatsVO order : connectorOrders) { + // 创建并初始化枪口统计信息 + SupStationStatsInfo.EquipmentStatsInfo.ConnectorStatsInfo connectorStatsInfo = + new SupStationStatsInfo.EquipmentStatsInfo.ConnectorStatsInfo(); + connectorStatsInfo.setConnectorId(pileConnectorCode); + connectorStatsInfo.setEquipmentClassification(1); + + // 设置枪口用电量(如果不为空) + BigDecimal power = order.getTotalPower(); + if (power != null) { + connectorStatsInfo.setConnectorElectricity(power.setScale(1, RoundingMode.HALF_UP)); + } + + // 获取当前订单的桩编号(处理可能为空的情况) + String pileSn = order.getPileSn() != null ? order.getPileSn() : "unknown_pile"; + + // 检查是否需要创建新的桩统计信息 + if (!pileSn.equals(currentPileSn)) { + // 如果不是第一个桩,保存之前的桩统计信息 + if (!currentPileSn.isEmpty()) { + saveCurrentPileStats( + currentPileSn, + currentPilePower, + currentPileChargeTime, + currentConnectorList, + equipmentStatsInfoList + ); + } + + // 初始化新桩的统计信息 + currentPileSn = pileSn; + currentPilePower = BigDecimal.ZERO; + currentPileChargeTime = 0; + currentConnectorList = new ArrayList<>(); + } + + // 累加当前桩的总电量和总充电时长 + if (power != null) { + currentPilePower = currentPilePower.add(power); + } + + String startTimeStr = order.getStartTime(); + String endTimeStr = order.getEndTime(); + int chargeTime = 0; + + if (startTimeStr != null && endTimeStr != null) { + try { + chargeTime = (int) DateUtils.intervalTime(startTimeStr, endTimeStr); + currentPileChargeTime += chargeTime; + } catch (Exception e) { + log.error("计算订单{}充电时长失败", order.getOrderCode(), e); + } + } + connectorStatsInfo.setConnectorTotalChargeTime(chargeTime); + connectorStatsInfo.setConnectorTotalChargeNum(connectorOrders.size()); + connectorStatsInfo.setConnectorTotalWarningNum(0); + + currentConnectorList.add(connectorStatsInfo); + } + } + if (!currentPileSn.isEmpty() && !currentConnectorList.isEmpty()) { + saveCurrentPileStats( + currentPileSn, + currentPilePower, + currentPileChargeTime, + currentConnectorList, + equipmentStatsInfoList + ); + log.info("站点{}最终统计到{}个充电桩数据", stationId, equipmentStatsInfoList.size()); + } else { + log.warn("站点{}未统计到任何充电桩数据!", stationId); + } + + SupStationStatsInfo supStationStatsInfo = SupStationStatsInfo.builder() + .stationId(stationId) + .startTime(startChargeTime) + .endTime(endChargeTime) + .stationElectricity(stationTotalElectricity.setScale(2, BigDecimal.ROUND_HALF_UP)) + .stationTotalChargeNum(orderBasicInfos.size()) + .stationTotalChargeTime(stationTotalChargeTime) + .stationTotalWarningNum(0) + .equipmentStatsInfos(equipmentStatsInfoList) + .supEquipmentStatsInfos(equipmentStatsInfoList) + .build(); + + // 7. 构建请求JSON + JSONObject json = new JSONObject(); + json.put("StationStatsInfos", Collections.singletonList(supStationStatsInfo)); + String jsonString = JSON.toJSONString(json); + + // 8. 发送推送请求 + ThirdPartySecretInfoVO thirdPartySecretInfoVO = getJiLinSecretInfo(); + String operatorId = Constants.OPERATORID_JIANG_SU; + String operatorSecret = thirdPartySecretInfoVO.getTheirOperatorSecret(); + String signSecret = thirdPartySecretInfoVO.getTheirSigSecret(); + String dataSecret = thirdPartySecretInfoVO.getTheirDataSecret(); + String dataSecretIv = thirdPartySecretInfoVO.getTheirDataSecretIv(); + String urlAddress = thirdPartySecretInfoVO.getTheirUrlPrefix(); + String url = urlAddress + "notification_operation_stats_info"; + + // 获取令牌 + String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); + + // 调用平台接口 + String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + log.info("站点{}推送结果: {}", stationId, result); + return result; + } + + + + /** + * 推送充电站实时功率信息 + * supervise_notification_realtime_power_info + */ + @Override + public String notificationPowerInfo(List stationIds) { + List list = new ArrayList<>(); + String dateTimeNow = DateUtils.dateTimeNow(DateUtils.YYYY_MM_DD_HH_MM_SS); + + for (String stationId : stationIds) { + BigDecimal stationPower = BigDecimal.ZERO; + SupStationPowerInfo supStationPowerInfo = new SupStationPowerInfo(); + + supStationPowerInfo.setStationId(stationId); + supStationPowerInfo.setDataTime(dateTimeNow); + supStationPowerInfo.setStationRealTimePower(stationPower); + + + // 根据站点id查询桩信息 + List pileList = pileBasicInfoService.getPileListByStationId(stationId); + if (CollectionUtils.isEmpty(pileList)) { + log.error("推送充换电站实时功率 error, 查询桩列表信息为空"); + throw new BusinessException(ReturnCodeEnum.CODE_SELECT_INFO_IS_NULL); + } + + // 将桩id筛选出来用于批量查询枪口数据 + List pileIds = pileList.stream() + .map(PileBasicInfo::getId) + .collect(Collectors.toList()); + QueryConnectorListDTO dto = new QueryConnectorListDTO(); + dto.setPileIds(pileIds); + dto.setRequestSource("thirdPartyPlatform"); + List connectorList = pileConnectorInfoService.getConnectorInfoListByParams(dto); + + if (CollectionUtils.isEmpty(connectorList)) { + log.error("推送充换电站实时功率 error, 查询枪口列表信息为空"); + throw new BusinessException(ReturnCodeEnum.CODE_SELECT_INFO_IS_NULL); + } + + List supPileInfoList = new ArrayList<>(); + for (PileBasicInfo pileBasicInfo : pileList) { + SupStationPowerInfo.EquipmentPowerInfo supPileInfo = new SupStationPowerInfo.EquipmentPowerInfo(); + supPileInfo.setEquipmentID(pileBasicInfo.getSn()); + supPileInfo.setEquipmentClassification(Constants.one); + supPileInfo.setDataTime(dateTimeNow); + supPileInfo.setEquipRealTimePower(BigDecimal.ZERO); + BigDecimal pileInstantPower = BigDecimal.ZERO; + List connectorPowerInfoList = new ArrayList<>(); + for (PileConnectorInfoVO pileConnectorInfoVO : connectorList) { + if (!StringUtils.equals(pileBasicInfo.getSn(), pileConnectorInfoVO.getPileSn())) { + continue; + } + BigDecimal instantPower = pileConnectorInfoVO.getInstantPower() == null ? BigDecimal.ZERO : pileConnectorInfoVO.getInstantPower(); + SupStationPowerInfo. + EquipmentPowerInfo. + ConnectorPowerInfo connectorPowerInfo = new SupStationPowerInfo.EquipmentPowerInfo.ConnectorPowerInfo(); + connectorPowerInfo.setConnectorID(pileConnectorInfoVO.getPileConnectorCode()); + connectorPowerInfo.setEquipmentClassification(Constants.one); + connectorPowerInfo.setDataTime(dateTimeNow); + BigDecimal InstantPower = instantPower.setScale(1, BigDecimal.ROUND_HALF_UP); + connectorPowerInfo.setConnectorRealTimePower(InstantPower); + // 计算桩此时实时功率 + pileInstantPower = pileInstantPower.add(InstantPower); + + connectorPowerInfoList.add(connectorPowerInfo); + } + supPileInfo.setConnectorPowerInfos(connectorPowerInfoList); + // 桩实时功率 + supPileInfo.setEquipRealTimePower(pileInstantPower.setScale(1, RoundingMode.HALF_UP)); + stationPower = stationPower.add(pileInstantPower); + supPileInfoList.add(supPileInfo); + } + supStationPowerInfo.setEquipmentPowerInfos(supPileInfoList); + supStationPowerInfo.setStationRealTimePower(stationPower.setScale(1, RoundingMode.HALF_UP)); + list.add(supStationPowerInfo); + } + + log.info("推送充电站实时功率信息:{}", JSON.toJSONString(list)); + + // 获取推送配置密钥信息 + ThirdPartySecretInfoVO guiZhouPlatformSecretInfo = getJiLinSecretInfo(); + + String operatorId = Constants.OPERATORID_JIANG_SU; + String operatorSecret = guiZhouPlatformSecretInfo.getTheirOperatorSecret(); + String signSecret = guiZhouPlatformSecretInfo.getTheirSigSecret(); + String dataSecret = guiZhouPlatformSecretInfo.getTheirDataSecret(); + String dataSecretIv = guiZhouPlatformSecretInfo.getTheirDataSecretIv(); + String urlAddress = guiZhouPlatformSecretInfo.getTheirUrlPrefix(); + + String url = urlAddress + "notification_realtime_power_info"; + // 获取令牌 + String token = getToken(urlAddress, operatorId, operatorSecret, dataSecretIv, signSecret, dataSecret); + if (StringUtils.isBlank(token)) { + return null; + } + JSONObject json = new JSONObject(); + json.put("StationPowerInfos", list); + String jsonString = JSON.toJSONString(json); + // 发送请求 + String result = HttpRequestUtil.sendPost(token, jsonString, url, dataSecret, dataSecretIv, operatorId, signSecret); + return result; + + } + + + + + + private void saveCurrentPileStats( + String pileSn, + BigDecimal pileTotalPower, + int pileTotalChargeTime, + List connectorList, + List resultList + ) { + SupStationStatsInfo.EquipmentStatsInfo equipmentStatsInfo = new SupStationStatsInfo.EquipmentStatsInfo(); + equipmentStatsInfo.setEquipmentId(pileSn); + equipmentStatsInfo.setEquipmentClassification(1); + equipmentStatsInfo.setEquipmentElectricity(pileTotalPower.setScale(2, RoundingMode.HALF_UP)); + equipmentStatsInfo.setEquipmentTotalChargeTime(pileTotalChargeTime); + equipmentStatsInfo.setEquipmentTotalChargeNum(connectorList.size()); // 改为每个桩的订单数 + equipmentStatsInfo.setEquipmentTotalWarningNum(0); + equipmentStatsInfo.setConnectorStatsInfos(connectorList); + equipmentStatsInfo.setSupconnectorStatsInfos(connectorList); + + resultList.add(equipmentStatsInfo); + log.debug("添加桩统计信息: 桩编号={}, 电量={}, 充电时长={}, 枪数量={}", + pileSn, pileTotalPower, pileTotalChargeTime, connectorList.size()); + } + /** @@ -870,41 +1625,34 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { * @param orderDetail * @return */ - private ChargeOrderInfo transformChargeOrderInfo(OrderBasicInfo orderBasicInfo , OrderDetail orderDetail) { + private ChargeOrderInfoDTO transformChargeOrderInfo(OrderBasicInfo orderBasicInfo , OrderDetail orderDetail) { PileStationVO stationInfo = pileStationInfoService.getStationInfo(orderBasicInfo.getStationId()); PileMerchantInfoVO pileMerchantInfoVO = pileMerchantInfoService.queryMerchantInfoByStationId(String.valueOf(stationInfo.getId())); String organizationCode = pileMerchantInfoVO.getOrganizationCode(); - ChargeOrderInfo chargeOrderInfo = ChargeOrderInfo.builder() - .operatorID(Constants.OPERATORID_JIANG_SU) - .equipmentOwnerID(ThirdPartyPlatformUtils.extractEquipmentOwnerID(organizationCode)) - .stationID(orderBasicInfo.getStationId()) - .equipmentID(orderBasicInfo.getPileSn()) - .orderNo(orderBasicInfo.getOrderCode()) - .connectorID(orderBasicInfo.getPileConnectorCode()) - .equipmentClassification(1) - .startTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeStartTime())) - .endTime(DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, orderBasicInfo.getChargeEndTime())) - .totalPower(orderDetail.getTotalUsedElectricity().setScale(4, RoundingMode.HALF_UP)) - .pushTimeStamp(DateUtils.getDateTime()) - .totalElecMoney(orderDetail.getTotalElectricityAmount().setScale(4, RoundingMode.HALF_UP)) - .totalServiceMoney(orderDetail.getTotalServiceAmount().setScale(4, RoundingMode.HALF_UP)) - .totalMoney(orderDetail.getTotalOrderAmount()) - .stopReason(2) - .stopDesc(orderBasicInfo.getReason()) - .build(); - if (orderBasicInfo.getPlateNumber() != null) { - chargeOrderInfo.setLicensePlate(orderBasicInfo.getPlateNumber()); - } - if (orderBasicInfo.getVinCode() != null) { - chargeOrderInfo.setVin(orderBasicInfo.getVinCode()); - } - if (orderBasicInfo.getStartSoc() != null) { - chargeOrderInfo.setStartSOC(orderBasicInfo.getStartSoc()); - } - if (orderBasicInfo.getEndSoc() != null) { - chargeOrderInfo.setEndSOC(orderBasicInfo.getEndSoc()); - } + ChargeOrderInfoDTO chargeOrderInfo = new ChargeOrderInfoDTO(); + BigDecimal totalElectricityAmount = orderDetail.getTotalElectricityAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalElectricityAmount(); + BigDecimal totalServiceAmount = orderDetail.getTotalServiceAmount() == null ? BigDecimal.ZERO : orderDetail.getTotalServiceAmount(); + BigDecimal totalMoney = orderBasicInfo.getOrderAmount() == null ? BigDecimal.ZERO : orderBasicInfo.getOrderAmount(); + BigDecimal startSoc = orderBasicInfo.getStartSoc() == null ? BigDecimal.ZERO : new BigDecimal(orderBasicInfo.getStartSoc()); + BigDecimal endSoc = orderBasicInfo.getEndSoc() == null ? BigDecimal.ZERO : new BigDecimal(orderBasicInfo.getEndSoc()); + + chargeOrderInfo.setStationID(stationInfo.getId()); + chargeOrderInfo.setEquipmentID(orderBasicInfo.getPileSn()); + chargeOrderInfo.setOrderNo(orderBasicInfo.getOrderCode()); + chargeOrderInfo.setConnectorID(orderBasicInfo.getPileConnectorCode()); + chargeOrderInfo.setStartSoc(startSoc.setScale(1, BigDecimal.ROUND_HALF_UP)); + chargeOrderInfo.setEndSoc(endSoc.setScale(1, BigDecimal.ROUND_HALF_UP)); + // 累计充电量 + chargeOrderInfo.setTotalPower(orderDetail.getTotalUsedElectricity().setScale(4, BigDecimal.ROUND_HALF_UP)); + chargeOrderInfo.setPushTimeStamp(DateUtils.getDateTime()); // 推送时间戳 + + chargeOrderInfo.setTotalElecMoney(totalElectricityAmount.setScale(2, BigDecimal.ROUND_HALF_UP));// 电费 + chargeOrderInfo.setTotalServiceMoney(totalServiceAmount.setScale(2, BigDecimal.ROUND_HALF_UP));// 服务费 + chargeOrderInfo.setTotalMoney(totalMoney);//累计总金额 + chargeOrderInfo.setStopReason(2); + chargeOrderInfo.setStopDesc(orderBasicInfo.getReason()); + return chargeOrderInfo; } @@ -1003,6 +1751,7 @@ public class JiLinPlatformServiceImpl implements ThirdPartyPlatformService { connectorInfo.setNationalStandard(2); connectorInfo.setAuxPower(3); connectorInfo.setOpreateStatus(Integer.valueOf(pileStationInfo.getStationStatus())); + connectorInfo.setOperateStatus(Integer.valueOf(pileStationInfo.getStationStatus())); String parkingLockFlag = pileStationInfo.getParkingLockFlag() == null ? "0" : pileStationInfo.getParkingLockFlag(); connectorInfo.setHasLock(Integer.valueOf(parkingLockFlag)); //有无地锁 0 无 1 有