Browse Source

光伏充电站接口

2025年1月1日14:01:49
qingyuan_dev_new
lishuai 1 year ago
parent
commit
9c9c0eabd3
  1. 2
      README.md
  2. 4
      application/pom.xml
  3. 15
      application/src/main/resources/application.yml
  4. 32
      common/core/src/main/java/com/thing/common/core/event/SimulateSocketEvent.java
  5. 2
      modules/pom.xml
  6. 103
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/controller/AlertController.java
  7. 70
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/dto/AlertDTO.java
  8. 113
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/entity/AlertEntity.java
  9. 64
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/excel/AlertExcel.java
  10. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/mapper/AlertMapper.java
  11. 19
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/service/AlertService.java
  12. 97
      modules/qingyuan/src/main/java/com/thing/qingyuan/alert/service/impl/AlertServiceImpl.java
  13. 108
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/controller/DeviceController.java
  14. 53
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/dto/DeviceDTO.java
  15. 82
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/entity/DeviceEntity.java
  16. 46
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/excel/DeviceExcel.java
  17. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/mapper/DeviceMapper.java
  18. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/service/IotDeviceService.java
  19. 36
      modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/service/impl/IotDeviceServiceImpl.java
  20. 41
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/config/StationProperties.java
  21. 65
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/ChargeOrderHeadController.java
  22. 44
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/ChargeStatisticController.java
  23. 91
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/StationInfoController.java
  24. 84
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeOrderDetailsDTO.java
  25. 83
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeOrderHeadDTO.java
  26. 84
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeStatisticReportResp.java
  27. 94
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeStatisticRequest.java
  28. 64
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ConnectorInfoDTO.java
  29. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ConnectorStatusInfo.java
  30. 64
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/EquipmentInfoDTO.java
  31. 11
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/IdNameDTO.java
  32. 17
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/SimpleThingRelationDTO.java
  33. 26
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationDeviceDetail.java
  34. 86
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationInfoDTO.java
  35. 81
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationOrderAgg.java
  36. 43
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationSimpleDTO.java
  37. 28
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationSimpleInfo.java
  38. 81
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ChargeOrderDetailsEntity.java
  39. 70
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ChargeOrderHeadEntity.java
  40. 66
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ConnectorInfoEntity.java
  41. 80
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/EquipmentInfoEntity.java
  42. 105
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/StationInfoEntity.java
  43. 106
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/excel/ChargeStatisticExcel.java
  44. 23
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ChargeOrderDetailsMapper.java
  45. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ChargeOrderHeadMapper.java
  46. 32
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ConnectorInfoMapper.java
  47. 24
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/EquipmentInfoMapper.java
  48. 22
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/StationInfoMapper.java
  49. 20
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeOrderDetailsService.java
  50. 21
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeOrderHeadService.java
  51. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeStatisticService.java
  52. 23
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ConnectorInfoService.java
  53. 22
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/EquipmentInfoService.java
  54. 55
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/StationInfoService.java
  55. 57
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeOrderDetailsServiceImpl.java
  56. 108
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeOrderHeadServiceImpl.java
  57. 135
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeStatisticServiceImpl.java
  58. 51
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ConnectorInfoServiceImpl.java
  59. 53
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/EquipmentInfoServiceImpl.java
  60. 389
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/StationInfoServiceImpl.java
  61. 272
      modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/task/StationTask.java
  62. 112
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/ManageBoardController.java
  63. 80
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/ManageChargeController.java
  64. 96
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/PlantController.java
  65. 20
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ChargeTotalInfo.java
  66. 22
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ChargingGunState.java
  67. 22
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/DataParam.java
  68. 28
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/DataReq.java
  69. 15
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/FindParam.java
  70. 20
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/GunDataParam.java
  71. 17
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/GunReportParam.java
  72. 16
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/MapParam.java
  73. 20
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PVParam.java
  74. 68
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PVReport.java
  75. 55
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantDTO.java
  76. 57
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantInfoReq.java
  77. 32
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantReq.java
  78. 36
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ReductionStatistics.java
  79. 30
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/SiteTypeInfo.java
  80. 61
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/StationInfoReq.java
  81. 27
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/TotalInfo.java
  82. 39
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/YOYDataReq.java
  83. 90
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/entity/PlantEntity.java
  84. 18
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/mapper/PlantMapper.java
  85. 29
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/ManageBoardService.java
  86. 25
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/ManageChargeService.java
  87. 25
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/PlantService.java
  88. 551
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/ManageBoardServiceImpl.java
  89. 557
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/ManageChargeServiceImpl.java
  90. 107
      modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/PlantServiceImpl.java
  91. 129
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/controller/PhotovoltaicController.java
  92. 33
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicConsumptionDTO.java
  93. 45
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicDTO.java
  94. 36
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicOverviewDTO.java
  95. 43
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicReportDTO.java
  96. 45
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/service/PhotovoltaicService.java
  97. 776
      modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/service/impl/PhotovoltaicServiceImpl.java
  98. 100
      modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/controller/IotEnergyConsumptionTargetController.java
  99. 101
      modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/controller/IotValueAddedController.java
  100. 26
      modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/dto/IotAddedDateDTO.java

2
README.md

@ -5,7 +5,7 @@
.pom文件,yml文件整合
.删除不需要的私有化定制代码
.本地队列驱动优化
.移除[changshu]模块
.移除[qingyuan]模块
.移除 老旧的[gateway]模块
.[publicorg]模块 有涉及设备管理相关代码,暂时保留

4
application/pom.xml

@ -137,6 +137,10 @@
<groupId>com.thing.modules</groupId>
<artifactId>filter-rule</artifactId>
</dependency>
<dependency>
<groupId>com.thing.modules</groupId>
<artifactId>qingyuan</artifactId>
</dependency>
<dependency>
<groupId>com.thing.modules</groupId>
<artifactId>cqc-service</artifactId>

15
application/src/main/resources/application.yml

@ -1,5 +1,5 @@
server:
port: 18080
port: 8080
servlet:
context-path: /thing
spring:
@ -62,7 +62,7 @@ database:
# 数据源及mybatis、mybatis-flex配置
mybatis-flex:
#是否开启审计日志打印
auditEnable: false
auditEnable: true
#mapper 包扫描路径
typeAliasesPackage: com.thing.**.mapper
#mapper 扫描路径
@ -82,14 +82,21 @@ mybatis-flex:
#物管理数据源
pg-thing:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:postgresql://127.0.0.1:25432/pub_guowang_v1
url: jdbc:postgresql://127.0.0.1:15432/thing
driver-class-name: org.postgresql.Driver
username: postgres
password: sddt8888
#遥测数据数据眼
pg-tskv:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:postgresql://127.0.0.1:25432/pub_guowang_v1
url: jdbc:postgresql://127.0.0.1:15432/thing
driver-class-name: org.postgresql.Driver
username: postgres
password: sddt8888
systemCollect:
# 指定为HikariDataSource
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:postgresql://192.168.188.184:5432/systemCollect
driver-class-name: org.postgresql.Driver
username: postgres
password: sddt8888

32
common/core/src/main/java/com/thing/common/core/event/SimulateSocketEvent.java

@ -0,0 +1,32 @@
package com.thing.common.core.event;
import com.thing.common.data.dto.QueueMsgDTO;
import com.thing.common.data.event.AbstractQueueEvent;
import java.io.Serial;
import java.util.List;
/**
* @author zhenghh. 2023-03-14
**/
public class SimulateSocketEvent extends AbstractQueueEvent<QueueMsgDTO> {
@Serial
private static final long serialVersionUID = -7524682936528507783L;
public SimulateSocketEvent(Object source, List<QueueMsgDTO> list) {
super(source, list);
}
// /**
// * 事件类型
// *
// * @return type
// */
// @Override
// public QueueEventType getEventType() {
// return QueueEventType.SOCKET;
// }
}

2
modules/pom.xml

@ -21,6 +21,8 @@
<module>calculation</module>
<module>mock</module>
<module>fix</module>
<module>qingyuan</module>
<!--<module>carbon</module>-->
<module>publicorg</module>
<module>alarm</module>
<module>filter-rule</module>

103
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/controller/AlertController.java

@ -0,0 +1,103 @@
package com.thing.qingyuan.alert.controller;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.alert.service.AlertService;
import com.thing.common.core.annotation.LogOperation;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.validator.AssertUtils;
import com.thing.common.core.validator.ValidatorUtils;
import com.thing.common.core.validator.group.AddGroup;
import com.thing.common.core.validator.group.DefaultGroup;
import com.thing.common.core.validator.group.UpdateGroup;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@RestController
@RequestMapping("alert")
@Tag(name="告警记录")
@RequiredArgsConstructor
public class AlertController {
private final AlertService alertService;
@GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始") ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数") ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
@Parameter(name = "name", description = "告警名称"),
@Parameter(name = "level", description = "告警等级"),
@Parameter(name = "status", description = "处理状态"),
@Parameter(name = "startTime", description = "告警开始时间窗口"),
@Parameter(name = "endTime", description = "告警结束时间窗口"),
@Parameter(name = "plantIds", description = "光伏场站id列表"),
})
public Result<PageData<AlertDTO>> page(@RequestParam Map<String, Object> params){
PageData<AlertDTO> page = alertService.handlePage(params);
return new Result<PageData<AlertDTO>>().ok(page);
}
@GetMapping("{id}")
@Operation(summary="信息")
public Result<AlertDTO> get(@PathVariable("id") Long id){
AlertDTO data = alertService.getByIdAs(id, AlertDTO.class);
return new Result<AlertDTO>().ok(data);
}
@PostMapping
@Operation(summary="保存")
@LogOperation("保存")
public Result<Void> save(@RequestBody AlertDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
alertService.saveDto(dto);
return new Result<>();
}
@PutMapping
@Operation(summary="修改")
@LogOperation("修改")
public Result<Void> update(@RequestBody AlertDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
alertService.updateDto(dto);
return new Result<>();
}
@DeleteMapping
@Operation(summary="删除")
@LogOperation("删除")
public Result<Void> delete(@RequestBody Long[] ids){
//效验数据
AssertUtils.isArrayEmpty(ids, "id");
alertService.batchDelete(ids);
return new Result<>();
}
@GetMapping("export")
@Operation(summary="导出")
@LogOperation("导出")
public void export( @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<AlertDTO> list = alertService.listAs(params, AlertDTO.class);
//ExcelUtils.exportExcelToTarget(response, null, "告警记录", list, AlertExcel.class);
}
}

70
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/dto/AlertDTO.java

@ -0,0 +1,70 @@
package com.thing.qingyuan.alert.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@Data
@Schema( name= "告警记录")
public class AlertDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "主键")
private Long plantAlertId;
@Schema(description = "电站id")
private Long plantId;
@Schema(description = "电站名称")
private String plantName;
@Schema(description = "设备id")
private Long deviceId;
@Schema(description = "设备名称")
private String deviceName;
@Schema(description = "状态id:1.未处理;2.已处理;3.已恢复")
private Integer status;
@Schema(description = "状态文本:1.未处理;2.已处理;3.已恢复")
private String statusLabel;
@Schema(description = "采集器sn")
private String collectorSn;
@Schema(description = "逆变器sn")
private String deviceSn;
@Schema(description = "报警等级id: 01.故障 02.警告 03.提示")
private Integer alertLevel;
@Schema(description = "报警等级文本: 01.故障 02.警告 03.提示")
private String alertLevelLabel;
@Schema(description = "报警名称")
private String alertName;
@Schema(description = "报警代码")
private String alertCode;
@Schema(description = "报警影响面")
private Integer alertEffect;
@Schema(description = "报警影响面文本")
private String alertEffectLabel;
@Schema(description = "报警发生时间")
private String startTimeOrigin;
@Schema(description = "报警发生时间")
private String startTime;
@Schema(description = "报警恢复时间")
private String endTimeOrigin;
@Schema(description = "报警恢复时间")
private String endTime;
@Schema(description = "报警发生时间")
private String startTimeForCharts;
@Schema(description = "报警恢复时间")
private String endTimeForCharts;
@Schema(description = "持续时间")
private String duration;
@Schema(description = "拟解决方案")
private String solution;
@Schema(description = "时区")
private Integer timeZoneOffset;
}

113
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/entity/AlertEntity.java

@ -0,0 +1,113 @@
package com.thing.qingyuan.alert.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Table("alert")
public class AlertEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@Id
private Long plantAlertId;
/**
* 电站id
*/
private Long plantId;
/**
* 设备id
*/
private Long deviceId;
/**
* 状态id1.未处理2.已处理3.已恢复
*/
private Integer status;
/**
* 状态文本1.未处理2.已处理3.已恢复
*/
private String statusLabel;
/**
* 采集器sn
*/
private String collectorSn;
/**
* 逆变器sn
*/
private String deviceSn;
/**
* 报警等级id: 01.故障 02.警告 03.提示
*/
private Integer alertLevel;
/**
* 报警等级文本: 01.故障 02.警告 03.提示
*/
private String alertLevelLabel;
/**
* 报警名称
*/
private String alertName;
/**
* 报警代码
*/
private String alertCode;
/**
* 报警影响面
*/
private Integer alertEffect;
/**
* 报警影响面文本
*/
private String alertEffectLabel;
/**
* 报警发生时间
*/
private String startTimeOrigin;
/**
* 报警发生时间
*/
private String startTime;
/**
* 报警恢复时间
*/
private String endTimeOrigin;
/**
* 报警恢复时间
*/
private String endTime;
/**
* 报警发生时间
*/
private String startTimeForCharts;
/**
* 报警恢复时间
*/
private String endTimeForCharts;
/**
* 持续时间
*/
private String duration;
/**
* 拟解决方案
*/
private String solution;
/**
* 时区
*/
private Integer timeZoneOffset;
}

64
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/excel/AlertExcel.java

@ -0,0 +1,64 @@
package com.thing.qingyuan.alert.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@Data
@ContentRowHeight(20)
@HeadRowHeight(20)
@ColumnWidth(25)
public class AlertExcel {
@ExcelProperty(value = "主键", index = 0)
private Long plantAlertId;
@ExcelProperty(value = "电站id", index = 1)
private Long plantId;
@ExcelProperty(value = "设备id", index = 2)
private Long deviceId;
@ExcelProperty(value = "状态id:1.未处理;2.已处理;3.已恢复", index = 3)
private Integer status;
@ExcelProperty(value = "状态文本:1.未处理;2.已处理;3.已恢复", index = 4)
private String statusLabel;
@ExcelProperty(value = "采集器sn", index = 5)
private String collectorSn;
@ExcelProperty(value = "逆变器sn", index = 6)
private String deviceSn;
@ExcelProperty(value = "报警等级id: 01.故障 02.警告 03.提示", index = 7)
private Integer alertLevel;
@ExcelProperty(value = "报警等级文本: 01.故障 02.警告 03.提示", index = 8)
private String alertLevelLabel;
@ExcelProperty(value = "报警名称", index = 9)
private String alertName;
@ExcelProperty(value = "报警代码", index = 10)
private String alertCode;
@ExcelProperty(value = "报警影响面", index = 11)
private Integer alertEffect;
@ExcelProperty(value = "报警影响面文本", index = 12)
private String alertEffectLabel;
@ExcelProperty(value = "报警发生时间", index = 13)
private String startTimeOrigin;
@ExcelProperty(value = "报警发生时间", index = 14)
private String startTime;
@ExcelProperty(value = "报警恢复时间", index = 15)
private String endTimeOrigin;
@ExcelProperty(value = "报警恢复时间", index = 16)
private String endTime;
@ExcelProperty(value = "报警发生时间", index = 17)
private String startTimeForCharts;
@ExcelProperty(value = "报警恢复时间", index = 18)
private String endTimeForCharts;
@ExcelProperty(value = "持续时间", index = 19)
private String duration;
@ExcelProperty(value = "拟解决方案", index = 20)
private String solution;
@ExcelProperty(value = "时区", index = 21)
private Integer timeZoneOffset;
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/mapper/AlertMapper.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.alert.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.alert.entity.AlertEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@Mapper
@UseDataSource("systemCollect")
public interface AlertMapper extends PowerBaseMapper<AlertEntity> {
}

19
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/service/AlertService.java

@ -0,0 +1,19 @@
package com.thing.qingyuan.alert.service;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.alert.entity.AlertEntity;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.IBaseService;
import java.util.Map;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
public interface AlertService extends IBaseService<AlertEntity> {
PageData<AlertDTO> handlePage(Map<String, Object> params);
}

97
modules/qingyuan/src/main/java/com/thing/qingyuan/alert/service/impl/AlertServiceImpl.java

@ -0,0 +1,97 @@
package com.thing.qingyuan.alert.service.impl;
import cn.hutool.core.map.MapUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.alert.entity.AlertEntity;
import com.thing.qingyuan.alert.mapper.AlertMapper;
import com.thing.qingyuan.alert.service.AlertService;
import com.thing.qingyuan.basedevice.entity.DeviceEntity;
import com.thing.qingyuan.basedevice.service.IotDeviceService;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.qingyuan.manageboard.service.PlantService;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import static com.thing.qingyuan.alert.entity.table.AlertEntityTableDef.ALERT_ENTITY;
/**
* 告警记录
*
* @author xc
* @since 3.0 2024-01-31
*/
@Service
@RequiredArgsConstructor
public class AlertServiceImpl extends BaseServiceImpl<AlertMapper, AlertEntity>
implements AlertService {
private final PlantService plantService;
private final IotDeviceService deviceService;
@Override
public QueryWrapper getWrapper(Map<String, Object> params) {
QueryWrapper wrapper = new QueryWrapper();
String alertName = MapUtil.getStr(params, "name");
Integer alertLevel = MapUtil.getInt(params, "level");
String statusLabel = MapUtil.getStr(params, "status");
String startTime = MapUtil.getStr(params, "startTime");
String endTime = MapUtil.getStr(params, "endTime");
String plantIds = MapUtil.getStr(params, "plantIds");
wrapper.eq(AlertEntity::getAlertName, alertName, StringUtils.isNotBlank(alertName))
.eq(AlertEntity::getAlertLevel, alertLevel, Objects.nonNull(alertLevel))
.eq(AlertEntity::getStatusLabel, statusLabel, StringUtils.isNotBlank(statusLabel));
if(StringUtils.isNotBlank(startTime) && StringUtils.isNotBlank(endTime)){
startTime += " UTC+08:00";
endTime += " UTC+08:00";
wrapper.and(ALERT_ENTITY.START_TIME.between(startTime, endTime)
.or(ALERT_ENTITY.END_TIME.between(startTime, endTime)));
}
if (StringUtils.isNotBlank(plantIds)) {
List<Long> plantIdList =
Arrays.stream(plantIds.split(","))
.map(Long::valueOf)
.toList();
wrapper.in(AlertEntity::getPlantId, plantIdList);
}
wrapper.isNotNull(AlertEntity::getStartTimeOrigin);
return wrapper;
}
@Override
public PageData<AlertDTO> handlePage(Map<String, Object> params) {
PageData<AlertDTO> pageData = getPageData(params, AlertDTO.class);
List<AlertDTO> list = pageData.getList();
if (list.isEmpty()) {
return pageData;
}
Set<Long> plantIds = list.stream().map(AlertDTO::getPlantId).collect(Collectors.toSet());
Set<Long> deviceIds = list.stream().map(AlertDTO::getDeviceId).collect(Collectors.toSet());
Map<Long, String> plantMap =
plantService.getMapper().selectListByIds(plantIds).stream()
.collect(
Collectors.toMap(
PlantEntity::getPlantId, PlantEntity::getPlantName));
Map<Long, String> deviceMap =
deviceService.getMapper().selectListByIds(deviceIds).stream()
.filter(e -> Objects.nonNull(e.getAlias()))
.collect(
Collectors.toMap(
DeviceEntity::getDeviceId, DeviceEntity::getAlias));
list.forEach(
item -> {
item.setPlantName(plantMap.get(item.getPlantId()));
item.setDeviceName(deviceMap.get(item.getDeviceId()));
});
return pageData;
}
}

108
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/controller/DeviceController.java

@ -0,0 +1,108 @@
//package com.thing.qingyuan.basedevice.controller;
//
//import com.thing.qingyuan.basedevice.dto.DeviceDTO;
//import com.thing.qingyuan.basedevice.service.IotDeviceService;
//import com.thing.common.core.annotation.LogOperation;
//import com.thing.common.core.constants.Constant;
//import com.thing.common.core.validator.AssertUtils;
//import com.thing.common.core.validator.ValidatorUtils;
//import com.thing.common.core.validator.group.AddGroup;
//import com.thing.common.core.validator.group.DefaultGroup;
//import com.thing.common.core.validator.group.UpdateGroup;
//import com.thing.common.core.web.response.PageData;
//import com.thing.common.core.web.response.Result;
//import io.swagger.v3.oas.annotations.Operation;
//import io.swagger.v3.oas.annotations.Parameter;
//import io.swagger.v3.oas.annotations.Parameters;
//import io.swagger.v3.oas.annotations.tags.Tag;
//import jakarta.servlet.http.HttpServletResponse;
//import lombok.RequiredArgsConstructor;
//import org.springframework.web.bind.annotation.*;
//
//import java.util.List;
//import java.util.Map;
//
///**
// * 设备信息表
// *
// * @author xc
// * @since 3.0 2024-01-30
// */
//@RestController
//@RequestMapping("v1/device/info")
//@Tag(name = "设备信息表")
//@RequiredArgsConstructor
//public class DeviceController {
//
// private final IotDeviceService iotDeviceService;
//
// @GetMapping("page")
// @Operation(summary = "分页")
// @Parameters({
// @Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
// @Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
// @Parameter(name = Constant.ORDER_FIELD, description = "排序字段"),
// @Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)")
// })
// public Result<PageData<DeviceDTO>> page(@RequestParam Map<String, Object> params) {
// PageData<DeviceDTO> page = iotDeviceService.getPageData(params, DeviceDTO.class);
// return new Result<PageData<DeviceDTO>>().ok(page);
// }
//
// @GetMapping("{id}")
// @Operation(summary = "信息")
// public Result<DeviceDTO> get(@PathVariable("id") Long id) {
// DeviceDTO data = iotDeviceService.getByIdAs(id, DeviceDTO.class);
// return new Result<DeviceDTO>().ok(data);
// }
//
// @PostMapping
// @Operation(summary = "保存")
// @LogOperation("保存")
// public Result<Void> save(@RequestBody DeviceDTO dto) {
// //效验数据
// ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
// iotDeviceService.saveDto(dto);
// return new Result<>();
// }
//
// @PutMapping
// @Operation(summary = "修改")
// @LogOperation("修改")
// public Result<Void> update(@RequestBody DeviceDTO dto) {
// //效验数据
// ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
// iotDeviceService.updateDto(dto);
// return new Result<>();
// }
//
// @DeleteMapping
// @Operation(summary = "删除")
// @LogOperation("删除")
// public Result<Void> delete(@RequestBody Long[] ids) {
// //效验数据
// AssertUtils.isArrayEmpty(ids, "id");
// iotDeviceService.batchDelete(ids);
// return new Result<>();
// }
//
// @GetMapping("export")
// @Operation(summary = "导出")
// @LogOperation("导出")
// public void export(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
// List<DeviceDTO> list = iotDeviceService.listAs(params, DeviceDTO.class);
// //ExcelUtils.exportExcelToTarget(response, null, "设备信息表", list, DeviceExcel.class);
// }
//
// @GetMapping("{plantId}/{type}")
// @Operation(summary = "根据电站id和类型查询 1.采集器\n" +
// "2.逆变器\n" +
// "3.电表\n" +
// "4.EPM\n" +
// "5.气象仪")
// public Result<List<DeviceDTO>> getDeviceByType(@PathVariable("plantId") Long plantId,@PathVariable("type") Integer type) {
// List<DeviceDTO> deviceDTOS = iotDeviceService.findByPlantId(plantId, type);
// return new Result<List<DeviceDTO>>().ok(deviceDTOS);
// }
//
//}

53
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/dto/DeviceDTO.java

@ -0,0 +1,53 @@
package com.thing.qingyuan.basedevice.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
@Data
@Schema(name = "设备信息表")
public class DeviceDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "设备ID")
private Long deviceId;
@Schema(description = "设备类型: 1.采集器 2.逆变器 3.电表 4.EPM 5.气象仪")
private Integer deviceType;
@Schema(description = "设备类型2: 与 productKey及deviceType2 关联")
private Integer deviceType2;
@Schema(description = "设备SN 逆变器sn")
private String deviceSn;
@Schema(description = "设备首次上电日期")
private String firstReportTime;
@Schema(description = "设备状态: 01.正常 02.离线 3.报警 4.故障 5.自定义报警 逆变器状态")
private Integer status;
@Schema(description = "产品代码 ")
private String productKey;
@Schema(description = "设备当前实时关联的电站ID")
private Long plantId;
@Schema(description = "设备最后上电日期")
private String lastReportTime;
@Schema(description = "设备上级连接父设备")
private Long upDeviceId;
@Schema(description = "记录创建时间")
private String createTime;
@Schema(description = "父设备sn 采集器sn")
private String upDeviceSn;
@Schema(description = "01.正常 02.离线 3.报警 4.故障 5.自定义报警 采集器状态 ")
private Integer upStatus;
@Schema(description = "01.正常 02.离线 3.报警 4.故障 5.自定义报警 采集器状态 ")
private String upAlias;
@Schema(description = "设备别名")
private String alias;
@Schema(description = "网络状态")
private String netWorkType="4G";
}

82
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/entity/DeviceEntity.java

@ -0,0 +1,82 @@
package com.thing.qingyuan.basedevice.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Table(value = "device",dataSource = "systemCollect")
public class DeviceEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 设备ID
*/
@Id
private Long deviceId;
/**
* 设备类型:
* 1.采集器
* 2.逆变器
* 3.电表
* 4.EPM
* 5.气象仪
*/
private Integer deviceType;
/**
* 设备类型2: productKey及deviceType2 关联
*/
private Integer deviceType2;
/**
* 设备SN
*/
private String deviceSn;
/**
* 设备首次上电日期
*/
private String firstReportTime;
/**
* 设备状态: 01.正常 02.离线 3.报警 4.故障 5.自定义报警
*/
private Integer status;
/**
* 产品代码
*/
private String productKey;
/**
* 设备当前实时关联的电站ID
*/
private Long plantId;
/**
* 设备最后上电日期
*/
private String lastReportTime;
/**
* 设备上级连接父设备
*/
private Long upDeviceId;
/**
* 记录创建时间
*/
private String createTime;
/**
* 父设备sn
*/
private String upDeviceSn;
/**
* 设备别名
*/
private String alias;
}

46
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/excel/DeviceExcel.java

@ -0,0 +1,46 @@
package com.thing.qingyuan.basedevice.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
@Data
@ContentRowHeight(20)
@HeadRowHeight(20)
@ColumnWidth(25)
public class DeviceExcel {
@ExcelProperty(value = "设备ID", index = 0)
private Long deviceId;
@ExcelProperty(value = "设备类型:1.采集器2.逆变器3.电表4.EPM5.气象仪", index = 1)
private Integer deviceType;
@ExcelProperty(value = "设备类型2: 与 productKey及deviceType2 关联", index = 2)
private Integer deviceType2;
@ExcelProperty(value = "设备SN", index = 3)
private String deviceSn;
@ExcelProperty(value = "设备首次上电日期", index = 4)
private String firstReportTime;
@ExcelProperty(value = "设备状态: 01.正常 02.离线 3.报警 4.故障 5.自定义报警", index = 5)
private Integer status;
@ExcelProperty(value = "产品代码 ", index = 6)
private String productKey;
@ExcelProperty(value = "设备当前实时关联的电站ID", index = 7)
private Long plantId;
@ExcelProperty(value = "设备最后上电日期", index = 8)
private String lastReportTime;
@ExcelProperty(value = "设备上级连接父设备", index = 9)
private Long upDeviceId;
@ExcelProperty(value = "记录创建时间", index = 10)
private String createTime;
@ExcelProperty(value = "父设备sn", index = 11)
private String upDeviceSn;
@ExcelProperty(value = "设备别名", index = 12)
private String alias;
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/mapper/DeviceMapper.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.basedevice.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.basedevice.entity.DeviceEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
@Mapper
@UseDataSource("systemCollect")
public interface DeviceMapper extends PowerBaseMapper<DeviceEntity> {
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/service/IotDeviceService.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.basedevice.service;
import com.thing.qingyuan.basedevice.dto.DeviceDTO;
import com.thing.qingyuan.basedevice.entity.DeviceEntity;
import com.thing.common.orm.service.IBaseService;
import java.util.List;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
public interface IotDeviceService extends IBaseService<DeviceEntity> {
List<DeviceDTO> findByPlantId(Long plantId,Integer type);
}

36
modules/qingyuan/src/main/java/com/thing/qingyuan/basedevice/service/impl/IotDeviceServiceImpl.java

@ -0,0 +1,36 @@
package com.thing.qingyuan.basedevice.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.basedevice.dto.DeviceDTO;
import com.thing.qingyuan.basedevice.entity.DeviceEntity;
import com.thing.qingyuan.basedevice.mapper.DeviceMapper;
import com.thing.qingyuan.basedevice.service.IotDeviceService;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
/**
* 设备信息表
*
* @author xc
* @since 3.0 2024-01-30
*/
@Service("IotDeviceServiceImpl")
public class IotDeviceServiceImpl extends BaseServiceImpl<DeviceMapper, DeviceEntity> implements IotDeviceService {
@Override
public QueryWrapper getWrapper(Map<String, Object> params) {
QueryWrapper wrapper = new QueryWrapper();
return wrapper;
}
@Override
public List<DeviceDTO> findByPlantId(Long plantId,Integer type) {
QueryWrapper queryWrapper = QueryWrapper.create().eq(DeviceEntity::getPlantId, plantId).eq(DeviceEntity::getDeviceType,type, ObjectUtil::isNotNull);
return mapper.selectListByQueryAs(queryWrapper,DeviceDTO.class);
}
}

41
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/config/StationProperties.java

@ -0,0 +1,41 @@
package com.thing.qingyuan.chargeStation.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Objects;
/**
* @author SiYang
* @date 2024/01/29 14:17
* @description 充电站配置属性
*/
@Data
@Component
@ConfigurationProperties(prefix = "qingyuan.charge-station")
public class StationProperties {
private Long relationId;
private List<Operator> operators;
@Data
public static class Operator {
private String id;
private String name;
}
public String getOperatorNameById(String id) {
Operator operator = getOperatorById(id);
return Objects.isNull(operator) ? null : operator.getName();
}
private Operator getOperatorById(String id) {
return operators.stream()
.filter(e -> Objects.equals(id, e.getId()))
.findFirst()
.orElse(null);
}
}

65
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/ChargeOrderHeadController.java

@ -0,0 +1,65 @@
package com.thing.qingyuan.chargeStation.controller;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderHeadDTO;
import com.thing.qingyuan.chargeStation.service.ChargeOrderHeadService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@RestController
@RequestMapping("chargeStation/order/head")
@Tag(name="充电桩订单头")
@RequiredArgsConstructor
public class ChargeOrderHeadController {
private final ChargeOrderHeadService chargeOrderHeadService;
@GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true) ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true) ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
@Parameter(name = Constant.BEGIN_TIME, description = "开始时间"),
@Parameter(name = Constant.END_TIME, description = "结束时间"),
@Parameter(name = "startChargeSeq", description = "订单号"),
@Parameter(name = "stationId", description = "充电站编码"),
@Parameter(name = "equipmentId", description = "充电桩编码"),
@Parameter(name = "connectorId", description = "充电枪编码"),
})
public Result<PageData<ChargeOrderHeadDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){
String order = StringUtils.isBlank((String) params.get(Constant.ORDER)) ? "desc" : (String) params.get(Constant.ORDER);
String orderField = StringUtils.isBlank((String) params.get(Constant.ORDER_FIELD)) ? "start_time" : (String) params.get(Constant.ORDER_FIELD);
params.put(Constant.ORDER, order);
params.put(Constant.ORDER_FIELD, orderField);
PageData<ChargeOrderHeadDTO> page = chargeOrderHeadService.handlePage(params);
return new Result<PageData<ChargeOrderHeadDTO>>().ok(page);
}
@GetMapping("{startChargeSeq}")
@Operation(summary="充电详情")
@Parameters({
@Parameter(name = "startChargeSeq", description = "订单号"),
})
public Result<ChargeOrderHeadDTO> get(@PathVariable("startChargeSeq") String startChargeSeq){
ChargeOrderHeadDTO data = chargeOrderHeadService.getDetails(startChargeSeq);
return new Result<ChargeOrderHeadDTO>().ok(data);
}
}

44
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/ChargeStatisticController.java

@ -0,0 +1,44 @@
package com.thing.qingyuan.chargeStation.controller;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticReportResp;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import com.thing.qingyuan.chargeStation.service.ChargeStatisticService;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 充电统计
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@RestController
@RequestMapping("chargeStation/statistic")
@Tag(name = "充电统计")
@RequiredArgsConstructor
public class ChargeStatisticController {
private final ChargeStatisticService service;
@PostMapping("report")
@Operation(summary = "充电统计报表")
public Result<List<ChargeStatisticReportResp>> page(@RequestBody ChargeStatisticRequest request) {
List<ChargeStatisticReportResp> data = service.getReport(request);
return new Result<List<ChargeStatisticReportResp>>().ok(data);
}
@PostMapping("report/export")
@Operation(summary="充电统计报表导出")
public void export(@RequestBody ChargeStatisticRequest request, HttpServletResponse response) {
service.export(request, response);
}
}

91
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/controller/StationInfoController.java

@ -0,0 +1,91 @@
package com.thing.qingyuan.chargeStation.controller;
import cn.hutool.core.map.MapUtil;
import com.thing.qingyuan.chargeStation.dto.IdNameDTO;
import com.thing.qingyuan.chargeStation.dto.StationDeviceDetail;
import com.thing.qingyuan.chargeStation.dto.StationInfoDTO;
import com.thing.qingyuan.chargeStation.dto.StationSimpleInfo;
import com.thing.qingyuan.chargeStation.service.StationInfoService;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@RestController
@RequestMapping("chargeStation/station")
@Tag(name = "充电站信息")
@RequiredArgsConstructor
public class StationInfoController {
private final StationInfoService stationInfoService;
@GetMapping("page")
@Operation(summary = "分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始", required = true),
@Parameter(name = Constant.LIMIT, description = "每页显示记录数", required = true),
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段"),
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
@Parameter(name = "areaCode", description = "区域编码"),
@Parameter(name = "operatorId", description = "运营商id"),
@Parameter(name = "keyword", description = "充电站名称关键字"),
})
public Result<PageData<StationInfoDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
params.putIfAbsent(Constant.ORDER_FIELD, "station_id");
PageData<StationInfoDTO> page = stationInfoService.handlePage(params);
return new Result<PageData<StationInfoDTO>>().ok(page);
}
@GetMapping("simple/list")
@Operation(summary="简要信息列表")
public Result<List<StationSimpleInfo>> simpleList(){
List<StationSimpleInfo> list = stationInfoService.simpleList();
return new Result<List<StationSimpleInfo>>().ok(list);
}
@GetMapping("pile/or/gun/idName")
@Operation(summary="充电桩或充电枪的id-name列表")
@Parameters({
@Parameter(name = "type", description = "pile:充电桩, gun:充电枪"),
@Parameter(name = "pid", description = "上级id"),
})
public Result<List<IdNameDTO>> getIdNameList(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
List<IdNameDTO> list = stationInfoService.getIdNameList(params);
return new Result<List<IdNameDTO>>().ok(list);
}
@GetMapping("details")
@Operation(summary = "信息")
@Parameters({
@Parameter(name = "stationId", description = "充电站编码(id)"),
})
public Result<StationDeviceDetail> getDetails(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
String stationId = MapUtil.getStr(params, "stationId");
StationDeviceDetail data = stationInfoService.getDetails(stationId);
return new Result<StationDeviceDetail>().ok(data);
}
@GetMapping("generate/thing/config")
@Operation(summary = "一键生成物模型、物实体、物指标、物关系、数据源配置")
public Result<Void> get() {
stationInfoService.generateThingConfig();
return new Result<>();
}
}

84
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeOrderDetailsDTO.java

@ -0,0 +1,84 @@
package com.thing.qingyuan.chargeStation.dto;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.data.proto.QueueProto;
import com.thing.common.data.proto.QueueProto.DataProto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 充电桩订单明细
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Data
@Schema(description = "充电桩订单明细")
public class ChargeOrderDetailsDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Long id;
@Schema(description = "充电订单号;运营商ID+唯一编号")
private String startChargeSeq;
@Schema(description = "充电设备接口编码")
private String connectorId;
@Schema(description = "结束时间;格式,yyyy-MM-dd HH: mm: ss")
private String endTime;
@Schema(description = "开始时间")
private String startTime;
@Schema(description = "A相电流")
private BigDecimal currentA;
@Schema(description = "B相电流")
private BigDecimal currentB;
@Schema(description = "C相电流")
private BigDecimal currentC;
@Schema(description = "A相电压")
private BigDecimal voltageA;
@Schema(description = "B相电压")
private BigDecimal voltageB;
@Schema(description = "C相电压")
private BigDecimal voltageC;
@Schema(description = "电池剩余电量,单位:%")
private BigDecimal soc;
@Schema(description = "时段充电量,单位:度(kwh)")
private BigDecimal totalPower;
public List<DataProto> toProtoDataList() {
List<DataProto> dataProtoList = new ArrayList<>();
Long ts = DateTimeUtils.convertTimeToLong(endTime);
dataProtoList.add(toProtoData(connectorId, "A8", currentA, ts));
dataProtoList.add(toProtoData(connectorId, "A9", currentB, ts));
dataProtoList.add(toProtoData(connectorId, "A10", currentC, ts));
dataProtoList.add(toProtoData(connectorId, "A1", voltageA, ts));
dataProtoList.add(toProtoData(connectorId, "A2", voltageB, ts));
dataProtoList.add(toProtoData(connectorId, "A3", voltageC, ts));
dataProtoList.add(toProtoData(connectorId, "A203", soc, ts));
dataProtoList.add(toProtoData(connectorId, "A229", totalPower, ts));
return dataProtoList.stream().filter(Objects::nonNull).collect(Collectors.toList());
}
private DataProto toProtoData(String thingCode, String key, BigDecimal val, Long ts) {
if(Objects.isNull(val)){
return null;
}
return DataProto.newBuilder()
.setTskvProto(
QueueProto.TsKvProto.newBuilder()
.setThingCode(thingCode)
.setKey(key)
.setVal(val.toPlainString())
.setTs(ts)
.build())
.build();
}
}

83
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeOrderHeadDTO.java

@ -0,0 +1,83 @@
package com.thing.qingyuan.chargeStation.dto;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderDetailsEntity;
import com.thing.common.core.utils.DateTimeUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Data
@Accessors(chain = true)
@Schema(description = "充电桩订单头")
public class ChargeOrderHeadDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "充电订单号;运营商ID+唯一编号")
private String startChargeSeq;
@Schema(description = "充电站id")
private String stationId;
@Schema(description = "充电站名称")
private String stationName;
@Schema(description = "充电桩id")
private String equipmentId;
@Schema(description = "充电桩名称")
private String equipmentName;
@Schema(description = "充电枪id")
private String connectorId;
@Schema(description = "充电枪名称")
private String connectorName;
@Schema(description = "开始充电时间;格式,yyyy-MM-dd HH: mm: ss")
private String startTime;
@Schema(description = "结束充电时间;格式,yyyy-MM-dd HH: mm: ss")
private String endTime;
@Schema(description = "累计充电量;单位:度, 小数点后2位")
private BigDecimal totalPower;
@Schema(description = "总电费;单位:元, 小数点后2位")
private BigDecimal elecMoney;
@Schema(description = "总服务费;单位:元, 小数点后2位")
private BigDecimal seviceMoney;
@Schema(description = "累计总金额;单位:元, 小数点后2位")
private BigDecimal totalMoney;
@Schema(description = "充电结束原因;0: 用户手动停止充电; 1:客户归属地运营商平台停止充电; 2: BMS停止充电; 3: 充电机设备故障; 4:连接器断开; 5~99: 自定义")
private Integer stopReason;
@Schema(description = "时段数N;范围:0~32")
private Integer sumPeriod;
@Schema(description = "充电订单状态;1:启动中; 2:充电中; 3:停止中; 4:已结束; 5:未知")
private Integer startChargeSeqStat;
@Schema(description = "订单详情: 电池电量(%)、A相电流、B相电流、C相电流 ...")
private List<ChargeOrderDetailsEntity> details;
public Long getDuration(){
return Objects.isNull(endTime)
? System.currentTimeMillis() - getStartTs()
: getEndTs() - getStartTs();
}
public Long getStartTs(){
return DateTimeUtils.convertTimeToLong(startTime);
}
public Long getEndTs(){
return DateTimeUtils.convertTimeToLong(endTime);
}
}

84
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeStatisticReportResp.java

@ -0,0 +1,84 @@
package com.thing.qingyuan.chargeStation.dto;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.data.tskv.TsKvDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
/**
* @author SiYang
* @date 2024/01/31 17:31
* @description 充电统计报表数据
*/
@Data
@Accessors(chain = true)
public class ChargeStatisticReportResp {
@Schema(description = "物id")
private Long thingId;
@Schema(description = "物名称")
private String thingName;
@Schema(description = "物编码")
private String thingCode;
@Schema(description = "属性名称")
private String attrName;
@Schema(description = "属性编码")
private String attrCode;
@Schema(description = "属性单位")
private String unit;
@Schema(description = "时间类型")
private String timeType;
@Schema(description = "合计数据")
private BigDecimal total;
@Schema(description = "数据")
private Map<Long, String> data;
public ChargeStatisticReportResp initData(List<LocalDateTime> timeList) {
if (Objects.isNull(data)) {
data = new TreeMap<>();
}
timeList.forEach(t -> data.put(DateTimeUtils.parse(t), null));
return this;
}
public ChargeStatisticReportResp fillData(List<TsKvDTO> tskvList) {
if(CollectionUtils.isEmpty(tskvList)){
return this;
}
if (Objects.isNull(data)) {
data = new TreeMap<>();
}
tskvList.forEach(tskv -> data.put(tskv.getTs(), tskv.getVal()));
return this;
}
public ChargeStatisticReportResp calculateTotal() {
BigDecimal total =
data.values().stream()
.filter(Objects::nonNull)
.map(
dataStr ->
BigDecimal.valueOf(Double.parseDouble(dataStr))
.setScale(2, RoundingMode.HALF_UP))
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
return this.setTotal(total);
}
}

94
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ChargeStatisticRequest.java

@ -0,0 +1,94 @@
package com.thing.qingyuan.chargeStation.dto;
import com.thing.common.core.exception.SysException;
import com.thing.common.core.utils.DateTimeUtils;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* @author SiYang
* @date 2024/01/31 17:16
* @description 充电统计请求
*/
@Data
@Schema(description = "充电统计请求参数")
public class ChargeStatisticRequest {
@Schema(description = "关系id")
private Long rootId;
@Schema(description = "顶级物id列表")
private List<String> rootThingIds;
@Schema(description = "物id列表")
private List<Long> thingIds;
@Schema(description = "报表类型=> 充电量: 1; 充电时长: 2; 充电次数: 3")
private Integer reportType;
@Schema(description = "时间类型:day ,month, year, any")
private String timeType;
@Schema(description = "开始时间")
private String beginTime;
@Schema(description = "结束时间")
private String endTime;
public String getAttrType() {
return switch (timeType) {
case "day" -> "hh";
case "month", "any" -> "dd";
case "year" -> "mm";
default -> throw new SysException(
"unSupport timeType, pls choose from [month, year, any]");
};
}
/** 充电量: A29; 充电时长: A201; 充电次数: A202 */
public String getBaseAttrCode(){
return switch (reportType) {
case 1 -> "A29";
case 2 -> "A201";
case 3 -> "A202";
default -> throw new SysException(
"unSupport reportType, pls choose from [1, 2, 3]");
};
}
public String getAttrCode() {
return getBaseAttrCode() + getAttrType();
}
public Long getStartTs() {
return DateTimeUtils.convertTimeToLong(beginTime);
}
public Long getEndTs() {
return DateTimeUtils.convertTimeToLong(endTime);
}
public List<LocalDateTime> generateAllDateTime() {
List<LocalDateTime> dateTimeList = new ArrayList<>();
LocalDateTime begin = getBeginDateTime().withHour(0).withMinute(0).withSecond(0).withNano(0);
LocalDateTime end = getEndDateTime();
while (begin.isBefore(end) || begin.isEqual(end)) {
dateTimeList.add(begin);
begin = "year".equals(timeType) ? begin.plusMonths(1) : begin.plusDays(1);
}
return dateTimeList;
}
private LocalDateTime getBeginDateTime() {
return DateTimeUtils.parseDateTime(beginTime);
}
private LocalDateTime getEndDateTime() {
LocalDateTime dateTime = DateTimeUtils.parseDateTime(endTime);
LocalDateTime currentDateTime = LocalDateTime.now();
return dateTime.isBefore(currentDateTime) ? dateTime : currentDateTime;
}
}

64
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ConnectorInfoDTO.java

@ -0,0 +1,64 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电枪
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Data
@Schema(description = "充电枪")
public class ConnectorInfoDTO implements Serializable {
@Serial private static final long serialVersionUID = 1L;
@Schema(description = "充电设备接口编码")
private String connectorId;
private String couplerType;
@Schema(description = "额定电压下限")
private Integer voltageLowerLimits;
private String qrCode;
@Schema(
description =
"充电设备接口类型内唯 1:家用插座(模式2);2: 交流接口插座(模式3, 连接方式B);3:交流接口插头(带枪线,模式3,连接方式C);4:直流5: 无线充电座; 6:其他")
private Integer connectorType;
@Schema(description = "额定电压上限")
private Integer voltageUpperLimits;
@Schema(description = "家标准1: 2011: 2: 2015")
private Integer nationalStandard;
@Schema(description = "充电设备接口名称")
private String connectorName;
private Integer ratedCurrent;
@Schema(description = "额定电流")
private BigDecimal current;
@Schema(description = "额定功率")
private BigDecimal power;
@Schema(description = "充电桩Id")
private String equipmentId;
@Schema(description = "充电设备接口状态 0:离网;1:空闲;2:占用(未充电);3:占用(充电中); 4:占用(预约锁定); 255:故障")
private Integer status;
@Schema(description = "地锁状态 0: 未知;10: 已解锁;50: 已上锁")
private Integer lockStatus;
@Schema(description = "车位状态 0:未知;10:空闲;50:占用")
private Integer parkStatus;
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/ConnectorStatusInfo.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "充电枪统计信息")
public class ConnectorStatusInfo {
@Schema(description = "状态")
private String status;
@Schema(description = "数量")
private Integer num;
}

64
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/EquipmentInfoDTO.java

@ -0,0 +1,64 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Objects;
/**
* 充电桩
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Data
@Accessors(chain = true)
@Schema(description = "充电桩")
public class EquipmentInfoDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String equipmentApplication;
private Integer equipmentStatus;
@Schema(description = "设备生产商名称")
private String manufacturerName;
private String openDate;
private BigDecimal equipmentPower;
@Schema(description = "设备编码")
private String equipmentId;
@Schema(description = "设备生产商组织机 构代码")
private String manufacturerId;
private Integer nationalStandard;
@Schema(description = "充电设备经度")
private BigDecimal equipmentLng;
private String openForBusinessDate;
@Schema(description = "充电枪数量")
private Integer gunNum;
@Schema(description = "设备类型1:直流设备; 2:交流设备;3:交直流一体设备;4:无线设备;5:其他")
private Integer equipmentType;
@Schema(description = "充电设备纬度")
private BigDecimal equipmentLat;
private BigDecimal voltage;
private Integer newNationalStandard;
@Schema(description = "充电设备名称")
private String equipmentName;
@Schema(description = "设备生产日期")
private String productionDate;
@Schema(description = "设备型号")
private String equipmentModel;
private BigDecimal current;
@Schema(description = "充电设备总功率单位:kW")
private BigDecimal power;
private String stationId;
public EquipmentInfoDTO add(EquipmentInfoDTO another) {
if (Objects.isNull(another)) return this;
return setGunNum(gunNum + another.getGunNum())
.setEquipmentPower(equipmentPower.add(another.getEquipmentPower()))
.setPower(power.add(another.getPower()));
}
}

11
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/IdNameDTO.java

@ -0,0 +1,11 @@
package com.thing.qingyuan.chargeStation.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
@Data
@AllArgsConstructor
public class IdNameDTO {
private String id;
private String name;
}

17
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/SimpleThingRelationDTO.java

@ -0,0 +1,17 @@
package com.thing.qingyuan.chargeStation.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author SiYang
* @date 2024/01/30 16:14
* @description 极简物关系
*/
@Data
@AllArgsConstructor
public class SimpleThingRelationDTO {
private String fromCode;
private String toCode;
private String toName;
}

26
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationDeviceDetail.java

@ -0,0 +1,26 @@
package com.thing.qingyuan.chargeStation.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author SiYang
* @date 2024/01/29 13:29
* @description 充电站的设备详情包含充电桩充电枪
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class StationDeviceDetail {
/** 充电站id */
private String stationId;
/** 充电桩列表 */
private List<EquipmentInfoDTO> pileList;
/** 充电枪列表 */
private List<ConnectorInfoDTO> gunList;
}

86
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationInfoDTO.java

@ -0,0 +1,86 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@Data
@Schema(description = "充电站信息")
public class StationInfoDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "填写内容为参照GB/T2260 2007 ")
private String areaCode;
@Schema(description = "详细地址 ")
private String address;
@Schema(description = "能够联系场站工作人员进行协助的联系电话")
private String stationTel;
@Schema(description = "平台服务电话, 例如400的电话")
private String serviceTel;
@Schema(description = "1:公共; 50:个人;100:公交(专用);101:环卫(专用);102:物流(专用);103:出租车(专用);255:其他")
private Integer stationType;
@Schema(description = ":未知; 1:建设中:5:关闭下线;6:维护中;50:正常使用")
private Integer stationStatus;
@Schema(description = "可停放进行充电的车位总数,默认: 0未知")
private Integer parkNums;
@Schema(description = "GCJ-02坐标系")
private BigDecimal stationLng;
@Schema(description = "GCJ-02坐标系")
private BigDecimal stationLat;
@Schema(description = "描述性文字, 用千引导车主找到充电车位")
private String siteGuide;
@Schema(description = "1:居民区; 2:公共机构;3:企事业单位;4:写字楼;5:工业园区;6:交通枢纽;7:大型文体设施;8:城市绿地;9:大型建筑配建停车场;10:路边停车位;11:城际高速服务区;255:其他")
private Integer construction;
@Schema(description = "描述该站点接受的车大小以及类型, 如大巳、 物流车、 私家乘用车、 出租车等")
private String matchCars;
@Schema(description = "车位楼层以及数擢信息")
private String parkInfo;
@Schema(description = "营业时间描述")
private String busineHours;
@Schema(description = "充电费描述")
private String electricityFee;
@Schema(description = "服务费率描述")
private String serviceFee;
@Schema(description = "停车费率描述")
private String parkFee;
@Schema(description = "支付方式:刷卡、线上、现金。其中电子钱包类卡为刷卡,身份鉴权卡、微信/支付宝、APP为线上 ")
private String payment;
@Schema(description = "充电设备是否需要提前预约后才能使用。0为不支持预约; 1 为支持预约。不填默认为0")
private Integer supportOrder;
@Schema(description = "其他备注信息")
private String remark;
@Schema(description = "充电站Id 接口文档没有但是接口有")
private String stationId;
@Schema(description = "运营商id")
private String operatorId;
@Schema(description = "运营商名称")
private String operatorName;
@Schema(description = "设备所有者id")
private String equipmentOwnerId;
@Schema(description = "充电站名称")
private String stationName;
@Schema(description = "国家")
private String countryCode;
@Schema(description = "省")
private String province;
@Schema(description = "市")
private String city;
@Schema(description = "区")
private String area;
@Schema(description = "装机功率: sum(充电桩功率)")
private Double totalPilePower;
@Schema(description = "调节功率")
private Double regulatingPower;
}

81
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationOrderAgg.java

@ -0,0 +1,81 @@
package com.thing.qingyuan.chargeStation.dto;
import com.thing.common.data.proto.QueueProto;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* @author SiYang
* @date 2024/01/23 15:54
* @description 充电站订单汇总数据
* 充电量: A29 totalPower
* 充电时长: A201 endTime - startTime
* 充电次数: A202 count(order)
* 充电金额: A204 totalMoney
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
public class StationOrderAgg {
/** 设备编号: 站(stationId), 桩(equipmentId), 枪(connectorId) */
private String deviceCode;
/** 汇总充电金额:A204xx */
private BigDecimal fee = BigDecimal.ZERO;
/** 汇总充电电量:A29xx */
private BigDecimal energy = BigDecimal.ZERO;
/** 汇总充电次数:A202xx */
private Integer count = 0;
/** 汇总充电时长:A201xx */
private Long duration = 0L;
public StationOrderAgg(String deviceCode) {
this.deviceCode = deviceCode;
}
public StationOrderAgg add(ChargeOrderHeadDTO order) {
if (Objects.isNull(order)) return this;
return setFee(fee.add(order.getTotalMoney()))
.setEnergy(energy.add(order.getTotalPower()))
.setCount(count + 1)
.setDuration(duration + order.getDuration());
}
public StationOrderAgg add(StationOrderAgg another) {
if (Objects.isNull(another)) return this;
return setFee(fee.add(another.getFee()))
.setEnergy(energy.add(another.getEnergy()))
.setCount(count + another.getCount())
.setDuration(duration + another.getDuration());
}
public List<QueueProto.DataProto> toProtoData(Long ts, String suffix) {
List<QueueProto.DataProto> list = new ArrayList<>();
list.add(toProtoData("A204" + suffix, fee.toPlainString(), ts));
list.add(toProtoData("A29" + suffix, energy.toPlainString(), ts));
list.add(toProtoData("A202" + suffix, count.toString(), ts));
list.add(toProtoData("A201" + suffix, duration.toString(), ts));
return list;
}
private QueueProto.DataProto toProtoData(String key, String val, Long ts) {
return QueueProto.DataProto.newBuilder()
.setTskvProto(
QueueProto.TsKvProto.newBuilder()
.setThingCode(deviceCode)
.setKey(key)
.setVal(val)
.setTs(ts)
.build())
.build();
}
}

43
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationSimpleDTO.java

@ -0,0 +1,43 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@Data
@Schema(description = "充电站简要信息")
public class StationSimpleDTO {
@Schema(description = "充电站id")
private String stationId;
@Schema(description = "充电站名称")
private String stationName;
@Schema(description = "经度")
private BigDecimal stationLng;
@Schema(description = "纬度")
private BigDecimal stationLat;
@Schema(description = "充电枪总数")
private Integer totalGunCount;
@Schema(description = "离线枪数量")
private Integer offLineCount;
@Schema(description = "空闲枪数量")
private Integer freeCount;
@Schema(description = "正在充电的枪数量")
private Integer inChargingCount;
@Schema(description = "故障枪数量")
private Integer errorCount;
}

28
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/dto/StationSimpleInfo.java

@ -0,0 +1,28 @@
package com.thing.qingyuan.chargeStation.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* @author SiYang
* @date 2024/01/29 13:54
* @description 充电站简化信息用于下拉查询
*/
@Data
@Accessors(chain = true)
@Schema(description = "充电站简化信息")
public class StationSimpleInfo {
@Schema(description = "充电站id ")
private String stationId;
@Schema(description = "充电站名称 ")
private String stationName;
@Schema(description = "地区编码 ")
private String areaCode;
@Schema(description = "地区名称 ")
private String areaName;
@Schema(description = "运营商id ")
private String operatorId;
@Schema(description = "运营商名称 ")
private String operatorName;
}

81
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ChargeOrderDetailsEntity.java

@ -0,0 +1,81 @@
package com.thing.qingyuan.chargeStation.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电桩订单明细
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Table("charge_details")
public class ChargeOrderDetailsEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 主键
*/
@Id
private Long id;
/**
* 充电订单号;运营商ID唯一编号
* @see ChargeOrderHeadEntity#startChargeSeq
*/
private String startChargeSeq;
/**
* 充电设备接口编码
*/
private String connectorId;
/**
* 结束时间;格式,yyyy-MM-dd HH: mm: ss
*/
private String endTime;
/**
* 开始时间
*/
private String startTime;
/**
* A相电流
*/
private BigDecimal currentA;
/**
* B相电流
*/
private BigDecimal currentB;
/**
* C相电流
*/
private BigDecimal currentC;
/**
* A相电压
*/
private BigDecimal voltageA;
/**
* B相电压
*/
private BigDecimal voltageB;
/**
* C相电压
*/
private BigDecimal voltageC;
/**
* 电池剩余电量,单位%
*/
private BigDecimal soc;
/**
* 时段充电量,单位kwh
*/
private BigDecimal totalPower;
}

70
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ChargeOrderHeadEntity.java

@ -0,0 +1,70 @@
package com.thing.qingyuan.chargeStation.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Table("notification_charge_order_info")
public class ChargeOrderHeadEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 充电订单号;运营商ID唯一编号
*/
@Id
private String startChargeSeq;
/**
* 充电设备接口编码
*/
private String connectorId;
/**
* 开始充电时间;格式,yyyy-MM-dd HH: mm: ss
*/
private String startTime;
/**
* 结束充电时间;格式,yyyy-MM-dd HH: mm: ss
*/
private String endTime;
/**
* 累计充电量;单位 小数点后2位
*/
private BigDecimal totalPower;
/**
* 总电费;单位 小数点后2位
*/
private BigDecimal elecMoney;
/**
* 总服务费;单位 小数点后2位
*/
private BigDecimal seviceMoney;
/**
* 累计总金额;单位 小数点后2位
*/
private BigDecimal totalMoney;
/**
* 充电结束原因;0: 用户手动停止充电 1:客户归属地运营商平台停止充电 2: BMS停止充电 3: 充电机设备故障 4:连接器断开 5~99: 自定义
*/
private Integer stopReason;
/**
* 时段数N;范围0~32
*/
private Integer sumPeriod;
/**
* 充电订单状态;1:启动中 2:充电中 3:停止中 4:已结束 5:未知
*/
private Integer startChargeSeqStat;
}

66
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/ConnectorInfoEntity.java

@ -0,0 +1,66 @@
package com.thing.qingyuan.chargeStation.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电枪
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@Table("connector_info")
public class ConnectorInfoEntity implements Serializable {
@Serial private static final long serialVersionUID = 1L;
/** 充电设备接口编码 */
@Id private String connectorId;
private String couplerType;
/** 额定电压下限 */
private Integer voltageLowerLimits;
private String qrCode;
/** 充电设备接口类型内唯 1:家用插座(模式2);2: 交流接口插座(模式3, 连接方式B);3:交流接口插头(带枪线,模式3,连接方式C);4:直流5: 无线充电座; 6:其他 */
private Integer connectorType;
/** 额定电压上限 */
private Integer voltageUpperLimits;
/** 家标准1: 2011: 2: 2015 */
private Integer nationalStandard;
/** 充电设备接口名称 */
private String connectorName;
private Integer ratedCurrent;
/** 额定电流 */
private BigDecimal current;
/** 额定功率 */
private BigDecimal power;
private String equipmentId;
/** 充电设备接口状态 0:离网;1:空闲;2:占用(未充电);3:占用(充电中); 4:占用(预约锁定); 255:故障 */
private Integer status;
/** 地锁状态 0: 未知;10: 已解锁;50: 已上锁 */
private Integer lockStatus;
/** 车位状态 0:未知;10:空闲;50:占用 */
private Integer parkStatus;
}

80
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/EquipmentInfoEntity.java

@ -0,0 +1,80 @@
package com.thing.qingyuan.chargeStation.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电桩
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Table("equipment_info")
public class EquipmentInfoEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 设备编码
*/
@Id
private String equipmentId;
private String equipmentApplication;
private Integer equipmentStatus;
/**
* 设备生产商名称
*/
private String manufacturerName;
private String openDate;
private BigDecimal equipmentPower;
/**
* 设备生产商组织机 构代码
*/
private String manufacturerId;
private Integer nationalStandard;
/**
* 充电设备经度
*/
private BigDecimal equipmentLng;
private String openForBusinessDate;
/**
* 充电枪数量
*/
private Integer gunNum;
/**
* 设备类型1:直流设备2:交流设备3:交直流一体设备4:无线设备5:其他
*/
private Integer equipmentType;
/**
* 充电设备纬度
*/
private BigDecimal equipmentLat;
private BigDecimal voltage;
private Integer newNationalStandard;
/**
* 充电设备名称
*/
private String equipmentName;
/**
* 设备生产日期
*/
private String productionDate;
/**
* 设备型号
*/
private String equipmentModel;
private BigDecimal current;
/**
* 充电设备总功率单位kW
*/
private BigDecimal power;
private String stationId;
}

105
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/entity/StationInfoEntity.java

@ -0,0 +1,105 @@
package com.thing.qingyuan.chargeStation.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Table("station_info")
public class StationInfoEntity implements Serializable {
@Serial private static final long serialVersionUID = 1L;
/** 填写内容为参照GB/T2260 2007 */
private String areaCode;
/** 详细地址 */
private String address;
/** 能够联系场站工作人员进行协助的联系电话 */
private String stationTel;
/** 平台服务电话, 例如400的电话 */
private String serviceTel;
/** 1:公共;50:个人;100:公交(专用);101:环卫(专用);102:物流(专用);103:出租车(专用);255:其他 */
private Integer stationType;
/** :未知;1:建设中:5:关闭下线;6:维护中;50:正常使用 */
private Integer stationStatus;
/** 可停放进行充电的车位总数,默认: 0未知 */
private Integer parkNums;
/** GCJ-02坐标系 */
private BigDecimal stationLng;
/** GCJ-02坐标系 */
private BigDecimal stationLat;
/** 描述性文字, 用千引导车主找到充电车位 */
private String siteGuide;
/**
* 1:居民区2:公共机构3:企事业单位4:写字楼5:工业园区6:交通枢纽7:大型文体设施8:城市绿地9:大型建筑配建停车场10:路边停车位11:城际高速服务区255:其他
*/
private Integer construction;
/** 描述该站点接受的车大小以及类型, 如大巳、 物流车、 私家乘用车、 出租车等 */
private String matchCars;
/** 车位楼层以及数擢信息 */
private String parkInfo;
/** 营业时间描述 */
private String busineHours;
/** 充电费描述 */
private String electricityFee;
/** 服务费率描述 */
private String serviceFee;
/** 停车费率描述 */
private String parkFee;
/** 支付方式:刷卡、线上、现金。其中电子钱包类卡为刷卡,身份鉴权卡、微信/支付宝、APP为线上 */
private String payment;
/** 充电设备是否需要提前预约后才能使用。0为不支持预约; 1 为支持预约。不填默认为0 */
private Integer supportOrder;
/** 其他备注信息 */
private String remark;
/** 充电站Id 接口文档没有但是接口有 */
@Id
private String stationId;
/** 运营商id */
private String operatorId;
/** 设备所属方id */
private String equipmentOwnerId;
/** 充电站名称 */
private String stationName;
/** 充电站国家代码 */
private String countryCode;
/** 省 */
private String province;
/** 市 */
private String city;
/** 区 */
private String area;
}

106
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/excel/ChargeStatisticExcel.java

@ -0,0 +1,106 @@
package com.thing.qingyuan.chargeStation.excel;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticReportResp;
import com.thing.common.core.annotation.CustomExcel;
import com.thing.common.core.annotation.CustomExcelCollection;
import com.thing.common.core.utils.DateTimeUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.util.CollectionUtils;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author SiYang
* @date 2024/02/01 14:17
* @description 充电统计
*/
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ChargeStatisticExcel {
@CustomExcel(name = "结构", width = 25)
private String thingName;
private String attrName;
private String attrUnit;
@CustomExcel(columnNameGenerator = "dataColNameGenerator", width = 15, orderNum = 1)
private String total;
@CustomExcelCollection
private List<TsVal> data;
@SuppressWarnings("unused")
private String dataColNameGenerator() {
return attrName + "(" + attrUnit + ")";
}
public static List<ChargeStatisticExcel> convert(List<ChargeStatisticReportResp> sources) {
if (CollectionUtils.isEmpty(sources)) {
return Collections.emptyList();
}
return sources.stream()
.map(
source -> {
Map<Long, String> dataMap = source.getData();
List<TsVal> dataList = new ArrayList<>();
dataMap.forEach(
(k, v) ->
dataList.add(
new TsVal()
.setTs(DateTimeUtils.parseDateTime(k))
.setTimeType(source.getTimeType())
.setVal(Optional.ofNullable(v).orElse("--"))));
return new ChargeStatisticExcel()
.setThingName(source.getThingName() + source.getAttrCode())
.setAttrName(source.getAttrName())
.setAttrUnit(source.getUnit())
.setTotal(source.getTotal().toString())
.setData(dataList);
})
.collect(Collectors.toList());
}
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public static class TsVal {
private String timeType;
private LocalDateTime ts;
@CustomExcel(columnNameGenerator = "dataColNameGenerator", width = 12, orderGenerator = "colOrderGenerator")
private String val;
@SuppressWarnings("unused")
private String dataColNameGenerator() {
return switch (timeType) {
case "month" -> ts.getDayOfMonth() + "日";
case "year" -> ts.getMonthValue() + "月";
default -> null;
};
}
@SuppressWarnings("unused")
private int colOrderGenerator(){
int orderNum = 2;
switch (timeType) {
case "month" -> orderNum += (31 - ts.getDayOfMonth());
case "year" -> orderNum += (12 - ts.getMonthValue());
default -> {
}
}
return orderNum;
}
}
}

23
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ChargeOrderDetailsMapper.java

@ -0,0 +1,23 @@
package com.thing.qingyuan.chargeStation.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderDetailsDTO;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderDetailsEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 充电桩订单明细
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Mapper
@UseDataSource("systemCollect")
public interface ChargeOrderDetailsMapper extends PowerBaseMapper<ChargeOrderDetailsEntity> {
List<ChargeOrderDetailsDTO> getLatestDetails(@Param("start") String start, @Param("end") String end);
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ChargeOrderHeadMapper.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.chargeStation.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderHeadEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Mapper
@UseDataSource("systemCollect")
public interface ChargeOrderHeadMapper extends PowerBaseMapper<ChargeOrderHeadEntity> {
}

32
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/ConnectorInfoMapper.java

@ -0,0 +1,32 @@
package com.thing.qingyuan.chargeStation.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.chargeStation.dto.ConnectorStatusInfo;
import com.thing.qingyuan.chargeStation.entity.ConnectorInfoEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 充电枪
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Mapper
@UseDataSource("systemCollect")
public interface ConnectorInfoMapper extends PowerBaseMapper<ConnectorInfoEntity> {
List<ConnectorStatusInfo> getStatusByStationId(String stationId);
Integer getCountByStationIds(List<String> stationIds);
List<ConnectorStatusInfo> getStatusByStationIds(List<String> stationIds);
List<ConnectorInfoEntity> simpleList(@Param("stationId") String stationId);
}

24
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/EquipmentInfoMapper.java

@ -0,0 +1,24 @@
package com.thing.qingyuan.chargeStation.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 充电桩
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Mapper
@UseDataSource("systemCollect")
public interface EquipmentInfoMapper extends PowerBaseMapper<EquipmentInfoEntity> {
List<Map<String, Object>> sumPower(@Param("stationIds") Collection<String> stationIds);
}

22
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/mapper/StationInfoMapper.java

@ -0,0 +1,22 @@
package com.thing.qingyuan.chargeStation.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.chargeStation.dto.StationSimpleDTO;
import com.thing.qingyuan.chargeStation.entity.StationInfoEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@Mapper
@UseDataSource("systemCollect")
public interface StationInfoMapper extends PowerBaseMapper<StationInfoEntity> {
List<StationSimpleDTO> getSimpleListWithGunStatus();
}

20
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeOrderDetailsService.java

@ -0,0 +1,20 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderDetailsDTO;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderDetailsEntity;
import com.thing.common.orm.service.IBaseService;
import java.util.List;
/**
* 充电桩订单明细
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
public interface ChargeOrderDetailsService extends IBaseService<ChargeOrderDetailsEntity> {
List<ChargeOrderDetailsEntity> findByHeadId(String startChargeSeq);
List<ChargeOrderDetailsDTO> getLatestDetails(String start, String end);
}

21
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeOrderHeadService.java

@ -0,0 +1,21 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderHeadDTO;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderHeadEntity;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.IBaseService;
import java.util.Map;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
public interface ChargeOrderHeadService extends IBaseService<ChargeOrderHeadEntity> {
PageData<ChargeOrderHeadDTO> handlePage(Map<String, Object> params);
ChargeOrderHeadDTO getDetails(String startChargeSeq);
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ChargeStatisticService.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticReportResp;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
/**
* @author SiYang
* @date 2024/01/31 17:33
* @description 充电统计服务
*/
public interface ChargeStatisticService {
List<ChargeStatisticReportResp> getReport(ChargeStatisticRequest request);
void export(ChargeStatisticRequest request, HttpServletResponse response);
}

23
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/ConnectorInfoService.java

@ -0,0 +1,23 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.ConnectorInfoDTO;
import com.thing.qingyuan.chargeStation.entity.ConnectorInfoEntity;
import com.thing.common.orm.service.IBaseService;
import java.util.Collection;
import java.util.List;
/**
* 充电枪
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
public interface ConnectorInfoService extends IBaseService<ConnectorInfoEntity> {
List<ConnectorInfoDTO> getByEquipmentIds(Collection<String> equipmentIds);
List<ConnectorInfoEntity> simpleList(String stationId);
Integer getCountByStationIds(List<String> stationIds);
}

22
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/EquipmentInfoService.java

@ -0,0 +1,22 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.EquipmentInfoDTO;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.common.orm.service.IBaseService;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 充电桩
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
public interface EquipmentInfoService extends IBaseService<EquipmentInfoEntity> {
List<EquipmentInfoDTO> getByStationId(String stationId);
Map<String, Double> sumPower(Collection<String> stationIds);
}

55
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/StationInfoService.java

@ -0,0 +1,55 @@
package com.thing.qingyuan.chargeStation.service;
import com.thing.qingyuan.chargeStation.dto.*;
import com.thing.qingyuan.chargeStation.entity.StationInfoEntity;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.IBaseService;
import com.thing.qingyuan.manageboard.dto.MapParam;
import java.util.List;
import java.util.Map;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
public interface StationInfoService extends IBaseService<StationInfoEntity> {
PageData<StationInfoDTO> handlePage(Map<String, Object> params);
/**
* 查询充电站的简要信息列表
*/
List<StationSimpleInfo> simpleList();
/**
* 获取充电站下的充电桩列表和充电枪列表
*
* @param stationId 充电站id
* @return 充电站设备详情
*/
StationDeviceDetail getDetails(String stationId);
/**
* 在当前租户下生成充电站配置
* 1. 物模型
* 2. 物实体
* 3. 物指标
* 4. 物关系
* 5. 数据源配置
*/
void generateThingConfig();
Map<String, List<StationInfoDTO>> findByParam(MapParam mapParam);
List<StationInfoDTO> findByName(String plantName, String area);
List<StationInfoEntity> getSimpleList();
List<StationSimpleDTO> getSimpleListWithGunStatus();
List<IdNameDTO> getIdNameList(Map<String, Object> params);
}

57
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeOrderDetailsServiceImpl.java

@ -0,0 +1,57 @@
package com.thing.qingyuan.chargeStation.service.impl;
import cn.hutool.core.map.MapUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderDetailsDTO;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderDetailsEntity;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderHeadEntity;
import com.thing.qingyuan.chargeStation.mapper.ChargeOrderDetailsMapper;
import com.thing.qingyuan.chargeStation.service.ChargeOrderDetailsService;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* 充电桩订单明细
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Service
@RequiredArgsConstructor
public class ChargeOrderDetailsServiceImpl extends BaseServiceImpl<ChargeOrderDetailsMapper, ChargeOrderDetailsEntity> implements ChargeOrderDetailsService {
@Override
public QueryWrapper getWrapper(Map<String, Object> params) {
QueryWrapper wrapper = new QueryWrapper();
String orderNo = MapUtil.getStr(params, "orderNo");
String beginTime = MapUtil.getStr(params, "beginTime");
String endTime = MapUtil.getStr(params, "endTime");
wrapper.eq(ChargeOrderHeadEntity::getStartChargeSeq, orderNo);
if (Objects.nonNull(beginTime) && Objects.nonNull(endTime)) {
wrapper.between(ChargeOrderHeadEntity::getStartTime, beginTime, endTime)
.between(ChargeOrderHeadEntity::getEndTime, beginTime, endTime);
}
return wrapper;
}
@Override
public List<ChargeOrderDetailsEntity> findByHeadId(String startChargeSeq) {
return list(
QueryWrapper.create()
.eq(ChargeOrderDetailsEntity::getStartChargeSeq, startChargeSeq)
.orderBy(ChargeOrderDetailsEntity::getEndTime)
.asc());
}
@Override
public List<ChargeOrderDetailsDTO> getLatestDetails(String start, String end) {
return mapper.getLatestDetails(start, end);
}
}

108
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeOrderHeadServiceImpl.java

@ -0,0 +1,108 @@
package com.thing.qingyuan.chargeStation.service.impl;
import cn.hutool.core.map.MapUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderHeadDTO;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderDetailsEntity;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderHeadEntity;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.qingyuan.chargeStation.entity.StationInfoEntity;
import com.thing.qingyuan.chargeStation.mapper.ChargeOrderHeadMapper;
import com.thing.qingyuan.chargeStation.service.*;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import static com.thing.qingyuan.chargeStation.entity.table.ChargeOrderHeadEntityTableDef.CHARGE_ORDER_HEAD_ENTITY;
import static com.thing.qingyuan.chargeStation.entity.table.ConnectorInfoEntityTableDef.CONNECTOR_INFO_ENTITY;
import static com.thing.qingyuan.chargeStation.entity.table.EquipmentInfoEntityTableDef.EQUIPMENT_INFO_ENTITY;
import static com.thing.qingyuan.chargeStation.entity.table.StationInfoEntityTableDef.STATION_INFO_ENTITY;
/**
* 充电桩订单头
*
* @author system system@lrd.com
* @since 5.1 2024-01-23
*/
@Service
@RequiredArgsConstructor
public class ChargeOrderHeadServiceImpl extends BaseServiceImpl<ChargeOrderHeadMapper, ChargeOrderHeadEntity> implements ChargeOrderHeadService {
private final ChargeOrderDetailsService chargeOrderDetailsService;
@Override
public QueryWrapper getWrapper(Map<String, Object> params){
return new QueryWrapper();
}
@Override
public PageData<ChargeOrderHeadDTO> handlePage(Map<String, Object> params) {
Page<ChargeOrderHeadDTO> page = getPage(params, ChargeOrderHeadDTO.class);
return selectPage(page, params);
}
@Override
public ChargeOrderHeadDTO getDetails(String startChargeSeq) {
ChargeOrderHeadDTO orderHead = getByIdAs(startChargeSeq, ChargeOrderHeadDTO.class);
fillDetail(orderHead);
return orderHead;
}
private PageData<ChargeOrderHeadDTO> selectPage(Page<ChargeOrderHeadDTO> page, Map<String, Object> params) {
String startChargeSeq = MapUtil.getStr(params, "startChargeSeq");
String stationId = MapUtil.getStr(params, "stationId");
String equipmentId = MapUtil.getStr(params, "equipmentId");
String connectorId = MapUtil.getStr(params, "connectorId");
String beginTime = MapUtil.getStr(params, "beginTime");
String endTime = MapUtil.getStr(params, "endTime");
String order = MapUtil.getStr(params, Constant.ORDER);
String orderField = MapUtil.getStr(params, Constant.ORDER_FIELD);
QueryWrapper queryWrapper =
QueryWrapper.create()
.select(
CHARGE_ORDER_HEAD_ENTITY.ALL_COLUMNS,
CONNECTOR_INFO_ENTITY.CONNECTOR_NAME,
EQUIPMENT_INFO_ENTITY.EQUIPMENT_ID,
EQUIPMENT_INFO_ENTITY.EQUIPMENT_NAME,
STATION_INFO_ENTITY.STATION_ID,
STATION_INFO_ENTITY.STATION_NAME)
.from(CHARGE_ORDER_HEAD_ENTITY)
.innerJoin(CONNECTOR_INFO_ENTITY).on(CHARGE_ORDER_HEAD_ENTITY.CONNECTOR_ID.eq(CONNECTOR_INFO_ENTITY.CONNECTOR_ID))
.innerJoin(EQUIPMENT_INFO_ENTITY).on(CONNECTOR_INFO_ENTITY.EQUIPMENT_ID.eq(EQUIPMENT_INFO_ENTITY.EQUIPMENT_ID))
.innerJoin(STATION_INFO_ENTITY).on(EQUIPMENT_INFO_ENTITY.STATION_ID.eq(STATION_INFO_ENTITY.STATION_ID))
.eq(ChargeOrderHeadEntity::getStartChargeSeq, startChargeSeq, StringUtils.isNotBlank(startChargeSeq))
.eq(ChargeOrderHeadEntity::getConnectorId, connectorId, StringUtils.isNotBlank(connectorId))
.eq(StationInfoEntity::getStationId, stationId, StringUtils.isNotBlank(stationId))
.eq(EquipmentInfoEntity::getEquipmentId, equipmentId, StringUtils.isNotBlank(equipmentId));
if (StringUtils.isNotBlank(beginTime) && StringUtils.isNotBlank(endTime)) {
queryWrapper.and(CHARGE_ORDER_HEAD_ENTITY.START_TIME.between(beginTime, endTime)
.or(CHARGE_ORDER_HEAD_ENTITY.END_TIME.between(beginTime, endTime)));
}
queryWrapper.orderBy(orderField, "asc".equals(order));
Page<ChargeOrderHeadDTO> paginate =
mapper.paginateAs(page, queryWrapper, ChargeOrderHeadDTO.class);
return new PageData<>(paginate.getRecords(), paginate.getTotalRow());
}
/**
* 补充属性和值, 属性说明CurrentA~C: 电流A VoltageA~C: 电压V
*
* @param orderHead 充电枪订单头
*/
private void fillDetail(ChargeOrderHeadDTO orderHead) {
List<ChargeOrderDetailsEntity> details =
chargeOrderDetailsService.findByHeadId(orderHead.getStartChargeSeq());
orderHead.setDetails(details);
}
}

135
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ChargeStatisticServiceImpl.java

@ -0,0 +1,135 @@
package com.thing.qingyuan.chargeStation.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticReportResp;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import com.thing.qingyuan.chargeStation.excel.ChargeStatisticExcel;
import com.thing.qingyuan.chargeStation.service.ChargeStatisticService;
import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.core.utils.export.ExcelEntityGenerator;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.thing.dict.dto.IotThingDictDTO;
import com.thing.thing.dict.entity.IotThingDictEntity;
import com.thing.thing.dict.service.IotThingDictService;
import com.thing.thing.dictRelation.service.IotThingDictRelationService;
import com.thing.thing.entity.dto.IotThingViewDTO;
import com.thing.thing.entity.entity.IotThingEntity;
import com.thing.thing.entity.service.IotThingEntityService;
import com.thing.thing.relation.root.service.IotThingRelationRootService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author SiYang
* @date 2024/01/31 17:34
* @description 充电统计服务实现
*/
@Service
@RequiredArgsConstructor
public class ChargeStatisticServiceImpl implements ChargeStatisticService {
private final TsKvService tsKvService;
private final IotThingDictService thingDictService;
private final IotThingDictRelationService thingDictRelationService;
private final IotThingEntityService thingEntityService;
private final IotThingRelationRootService relationRootService;
@Override
public List<ChargeStatisticReportResp> getReport(ChargeStatisticRequest request) {
// 物信息
List<Long> thingIds = request.getThingIds();
List<IotThingViewDTO> things = thingEntityService.findByIds(thingIds);
Set<String> thingCodes = things.stream().map(IotThingViewDTO::getEntityCode).collect(Collectors.toSet());
// 属性信息
IotThingDictDTO dict = thingDictService.findDictByCode(request.getBaseAttrCode());
// 查询tskv
List<TsKvDTO> tskvList =
tsKvService.findTsKvByCodesAndAttrs(
thingCodes,
Collections.singletonList(request.getAttrCode()),
request.getStartTs(),
request.getEndTs(),
false);
Map<String, List<TsKvDTO>> thingTskvListMap =
tskvList.stream().collect(Collectors.groupingBy(TsKvDTO::getThingCode));
// 数据组装
List<ChargeStatisticReportResp> unsortedResult = assemble(things, dict, request, thingTskvListMap);
// 按深度优先排序
return relationRootService.sortInDiffRootThingIds(
request.getRootId(),
request.getRootThingIds(),
new HashSet<>(thingIds),
unsortedResult,
res -> res.stream().collect(Collectors.groupingBy(ChargeStatisticReportResp::getThingId)));
}
@Override
public void export(ChargeStatisticRequest request, HttpServletResponse response) {
// 报表原始数据
List<ChargeStatisticReportResp> report = getReport(request);
// 数据类型转换
List<ChargeStatisticExcel> excelDataList = ChargeStatisticExcel.convert(report);
// 生成表头 & 生成数据集合
List<ExcelExportEntity> excelExportEntities = ExcelEntityGenerator.generateExportEntity(new ArrayList<>(excelDataList));
List<Map<String, Object>> dataCollection = ExcelEntityGenerator.generateDataCollection(new ArrayList<>(excelDataList));
// 导出
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(null, "充电统计报表"), excelExportEntities, dataCollection);
ExcelUtils.downLoadExcel("充电统计报表.xls", response, workbook);
}
private List<ChargeStatisticReportResp> assemble(
List<IotThingViewDTO> things,
IotThingDictDTO dict,
ChargeStatisticRequest request,
Map<String, List<TsKvDTO>> thingTskvListMap) {
return things.stream()
.map(
t -> {
List<TsKvDTO> tskvList = thingTskvListMap.get(t.getEntityCode());
if (CollectionUtils.isNotEmpty(tskvList) && request.getReportType().equals(2)) {
tskvList.forEach(
e -> {
String msVal = e.getVal();
if (StringUtils.isNotBlank(msVal)) {
BigDecimal hourVal =
new BigDecimal(msVal)
.divide(BigDecimal.valueOf(60 * 60 * 1000), 2, RoundingMode.HALF_UP);
e.setVal(hourVal.toPlainString());
}
});
}
return new ChargeStatisticReportResp()
.setThingId(t.getEntityId())
.setThingName(t.getEntityName())
.setThingCode(t.getEntityCode())
.setAttrName(dict.getName())
.setAttrCode(dict.getCode())
.setUnit(dict.getUnit())
.setTimeType(request.getTimeType())
.initData(request.generateAllDateTime())
.fillData(tskvList)
.calculateTotal();
})
.toList();
}
}

51
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/ConnectorInfoServiceImpl.java

@ -0,0 +1,51 @@
package com.thing.qingyuan.chargeStation.service.impl;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.dto.ConnectorInfoDTO;
import com.thing.qingyuan.chargeStation.entity.ConnectorInfoEntity;
import com.thing.qingyuan.chargeStation.mapper.ConnectorInfoMapper;
import com.thing.qingyuan.chargeStation.service.ConnectorInfoService;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* 充电枪
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Service
@RequiredArgsConstructor
public class ConnectorInfoServiceImpl extends BaseServiceImpl<ConnectorInfoMapper, ConnectorInfoEntity> implements ConnectorInfoService {
@Override
public QueryWrapper getWrapper(Map<String, Object> params){
QueryWrapper wrapper = new QueryWrapper();
return wrapper;
}
@Override
public List<ConnectorInfoDTO> getByEquipmentIds(Collection<String> equipmentIds) {
return mapper.selectListByQueryAs(
QueryWrapper.create()
.in(ConnectorInfoEntity::getEquipmentId, equipmentIds)
.orderBy(ConnectorInfoEntity::getEquipmentId)
.asc(),
ConnectorInfoDTO.class);
}
@Override
public List<ConnectorInfoEntity> simpleList(String stationId) {
return mapper.simpleList(stationId);
}
@Override
public Integer getCountByStationIds(List<String> stationIds) {
return mapper.getCountByStationIds(stationIds);
}
}

53
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/EquipmentInfoServiceImpl.java

@ -0,0 +1,53 @@
package com.thing.qingyuan.chargeStation.service.impl;
import cn.hutool.core.map.MapUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.dto.EquipmentInfoDTO;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.qingyuan.chargeStation.mapper.EquipmentInfoMapper;
import com.thing.qingyuan.chargeStation.service.EquipmentInfoService;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 充电桩
*
* @author system system@lrd.com
* @since 5.1 2024-01-29
*/
@Service
public class EquipmentInfoServiceImpl extends BaseServiceImpl<EquipmentInfoMapper, EquipmentInfoEntity> implements EquipmentInfoService {
@Override
public QueryWrapper getWrapper(Map<String, Object> params) {
QueryWrapper wrapper = new QueryWrapper();
String stationId = MapUtil.getStr(params, "stationId");
wrapper.eq(EquipmentInfoEntity::getStationId, stationId, StringUtils.isNotBlank(stationId));
return wrapper;
}
@Override
public List<EquipmentInfoDTO> getByStationId(String stationId) {
return mapper.selectListByQueryAs(
QueryWrapper.create().eq(EquipmentInfoEntity::getStationId, stationId),
EquipmentInfoDTO.class);
}
@Override
public Map<String, Double> sumPower(Collection<String> stationIds) {
List<Map<String, Object>> stationPowerMapList = mapper.sumPower(stationIds);
Map<String, Double> res = new HashMap<>();
for (Map<String, Object> map : stationPowerMapList) {
String stationId = (String) map.get("stationId");
Double totalPower = Double.valueOf("" + map.get("totalPower"));
res.put(stationId, totalPower);
}
return res;
}
}

389
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/service/impl/StationInfoServiceImpl.java

@ -0,0 +1,389 @@
package com.thing.qingyuan.chargeStation.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.config.StationProperties;
import com.thing.qingyuan.chargeStation.dto.*;
import com.thing.qingyuan.chargeStation.entity.ConnectorInfoEntity;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.qingyuan.chargeStation.entity.StationInfoEntity;
import com.thing.qingyuan.chargeStation.mapper.StationInfoMapper;
import com.thing.qingyuan.chargeStation.service.ConnectorInfoService;
import com.thing.qingyuan.chargeStation.service.EquipmentInfoService;
import com.thing.qingyuan.chargeStation.service.StationInfoService;
import com.thing.common.core.enumeration.TemplateMark;
import com.thing.common.core.utils.ConvertUtils;
import com.thing.common.core.validator.AssertUtils;
import com.thing.common.core.web.response.PageData;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import com.thing.event.ThingRelationDetailSaveEvent;
import com.thing.qingyuan.manageboard.dto.MapParam;
import com.thing.sys.security.context.UserContext;
import com.thing.thing.dictRelation.service.IotThingDictRelationService;
import com.thing.thing.entity.entity.IotThingEntity;
import com.thing.thing.entity.service.IotThingEntityService;
import com.thing.thing.model.service.IotThingModelService;
import com.thing.thing.model.thread.ThingModelExecutor;
import com.thing.thing.relation.detail.service.IotThingRelationDetailService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
import static com.thing.qingyuan.chargeStation.entity.table.StationInfoEntityTableDef.STATION_INFO_ENTITY;
/**
* 充电站信息
*
* @author ssy 2337720667@qq.com
* @since 3.0 2024-01-23
*/
@Service
@RequiredArgsConstructor
public class StationInfoServiceImpl extends BaseServiceImpl<StationInfoMapper, StationInfoEntity> implements StationInfoService {
private final StationProperties stationProperties;
private final ThingModelExecutor thingModelExecutor;
private final EquipmentInfoService equipmentInfoService;
private final ConnectorInfoService connectorInfoService;
private final IotThingModelService iotThingModelService;
private final IotThingEntityService iotThingEntityService;
private final ApplicationEventPublisher applicationEventPublisher;
private final IotThingDictRelationService iotThingDictRelationService;
private final IotThingRelationDetailService iotThingRelationDetailService;
private static final String STATION_TEMPLATE_TYPE = "Station";
private static final String PILE_TEMPLATE_TYPE = "Pile";
private static final String GUN_TEMPLATE_TYPE = "Gun";
@Override
public QueryWrapper getWrapper(Map<String, Object> params) {
QueryWrapper wrapper = new QueryWrapper();
String areaCode = MapUtil.getStr(params, "areaCode");
String operatorId = MapUtil.getStr(params, "operatorId");
String keyword = MapUtil.getStr(params, "keyword");
wrapper.eq(StationInfoEntity::getAreaCode, areaCode, StringUtils.isNotBlank(areaCode))
.eq(StationInfoEntity::getOperatorId, operatorId, StringUtils.isNotBlank(operatorId))
.like(StationInfoEntity::getStationName, keyword, StringUtils.isNotBlank(keyword));
return wrapper;
}
@Override
public PageData<StationInfoDTO> handlePage(Map<String, Object> params) {
PageData<StationInfoDTO> page = getPageData(params, StationInfoDTO.class);
List<StationInfoDTO> list = page.getList();
fillExtendData(list);
return page;
}
private void fillExtendData(List<StationInfoDTO> list) {
Set<String> stationIds = list.stream().map(StationInfoDTO::getStationId).collect(Collectors.toSet());
Map<String, Double> stationPowerMap = equipmentInfoService.sumPower(stationIds);
list.forEach(
e -> {
e.setOperatorName(stationProperties.getOperatorNameById(e.getOperatorId()));
e.setTotalPilePower(stationPowerMap.get(e.getStationId()));
});
}
@Override
public List<StationSimpleInfo> simpleList() {
List<StationInfoEntity> list = list();
return list.stream()
.map(
e ->
new StationSimpleInfo()
.setStationId(e.getStationId())
.setStationName(e.getStationName())
.setAreaCode(e.getAreaCode())
.setAreaName(e.getArea())
.setOperatorId(e.getOperatorId())
.setOperatorName(
stationProperties.getOperatorNameById(e.getOperatorId())))
.collect(Collectors.toList());
}
@Override
public StationDeviceDetail getDetails(String stationId) {
List<EquipmentInfoDTO> pileList = equipmentInfoService.getByStationId(stationId);
Set<String> equipmentIds = pileList.stream().map(EquipmentInfoDTO::getEquipmentId).collect(Collectors.toSet());
List<ConnectorInfoDTO> gunList = connectorInfoService.getByEquipmentIds(equipmentIds);
return new StationDeviceDetail(stationId, pileList, gunList);
}
/**
* 在当前租户下生成充电站配置
* 1. 物模型
* 2. 物实体
* 3. 物指标
* 4. 物关系
* 5. 数据源配置
*/
@Override
public void generateThingConfig() {
Long tenantCode = UserContext.getTenantCode();
//
List<StationInfoEntity> stationList = list();
List<SimpleThingRelationDTO> stationSimpleRelations = stationConvert2SimpleRelation(stationList);
doGenerate(stationSimpleRelations, STATION_TEMPLATE_TYPE, tenantCode);
//
List<EquipmentInfoEntity> pileList = equipmentInfoService.list();
List<SimpleThingRelationDTO> pileSimpleRelations = pileConvert2SimpleRelation(pileList);
doGenerate(pileSimpleRelations, PILE_TEMPLATE_TYPE, tenantCode);
//
List<ConnectorInfoEntity> gunList = connectorInfoService.list();
List<SimpleThingRelationDTO> gunSimpleRelations = gunConvert2SimpleRelation(gunList);
doGenerate(gunSimpleRelations, GUN_TEMPLATE_TYPE, tenantCode);
}
@Override
public Map<String, List<StationInfoDTO>> findByParam(MapParam mapParam) {
QueryWrapper wrapper = new QueryWrapper();
if(mapParam.getType().equals("2")){
wrapper.eq(StationInfoEntity::getProvince,mapParam.getCityName());
List<StationInfoDTO> dtos = ConvertUtils.sourceToTarget(this.list(wrapper),StationInfoDTO.class);
return dtos.stream()
.collect(Collectors.groupingBy(StationInfoDTO::getCity));
}else if(mapParam.getType().equals("3")){
wrapper.eq(StationInfoEntity::getCity,mapParam.getCityName());
List<StationInfoDTO> dtos = ConvertUtils.sourceToTarget(this.list(wrapper),StationInfoDTO.class);
return dtos.stream()
.collect(Collectors.groupingBy(StationInfoDTO::getCity));
}else if(mapParam.getType().equals("4")){
wrapper.eq(StationInfoEntity::getArea,mapParam.getCityName());
List<StationInfoDTO> dtos = ConvertUtils.sourceToTarget(this.list(wrapper),StationInfoDTO.class);
return dtos.stream()
.collect(Collectors.groupingBy(StationInfoDTO::getCity));
}else {
List<StationInfoDTO> dtos = ConvertUtils.sourceToTarget(this.list(wrapper),StationInfoDTO.class);
return dtos.stream()
.collect(Collectors.groupingBy(StationInfoDTO::getProvince));
}
}
@Override
public List<StationInfoDTO> findByName(String plantName, String area) {
QueryWrapper wrapper = new QueryWrapper();
wrapper.like(StationInfoEntity::getStationName,plantName,StringUtils.isNotEmpty(plantName));
wrapper.like(StationInfoEntity::getArea,area,StringUtils.isNotEmpty(area));
return ConvertUtils.sourceToTarget(this.list(wrapper),StationInfoDTO.class);
}
@Override
public List<StationInfoEntity> getSimpleList() {
QueryWrapper queryWrapper =
QueryWrapper.create()
.select(STATION_INFO_ENTITY.STATION_ID, STATION_INFO_ENTITY.STATION_NAME)
.from(STATION_INFO_ENTITY);
return list(queryWrapper);
}
@Override
public List<StationSimpleDTO> getSimpleListWithGunStatus() {
return mapper.getSimpleListWithGunStatus();
}
@Override
public List<IdNameDTO> getIdNameList(Map<String, Object> params) {
String type = MapUtil.getStr(params, "type");
String pid = MapUtil.getStr(params, "pid");
boolean pidValid = StringUtils.isNotBlank(pid);
if ("pile".equals(type)) {
List<EquipmentInfoEntity> piles =
equipmentInfoService.list(
QueryWrapper.create()
.eq(EquipmentInfoEntity::getStationId, pid, pidValid));
return piles.stream()
.map(p -> new IdNameDTO(p.getEquipmentId(), p.getEquipmentName()))
.toList();
} else {
List<ConnectorInfoEntity> guns =
connectorInfoService.list(
QueryWrapper.create()
.eq(ConnectorInfoEntity::getEquipmentId, pid, pidValid));
return guns.stream()
.map(g -> new IdNameDTO(g.getConnectorId(), g.getConnectorName()))
.toList();
}
}
private void doGenerate(List<SimpleThingRelationDTO> simpleRelations, String templateType, Long tenantCode){
Map<String, String> thingMap =
simpleRelations.stream().collect(Collectors.toMap(SimpleThingRelationDTO::getToCode, SimpleThingRelationDTO::getToName));
Set<String> thingCodes = thingMap.keySet();
// 新增物模型异步
// thingModelExecutor.execute(() -> iotThingModelService.batchSaveWithCodes(thingCodes));
// 新增物实体同步
// iotThingEntityService.batchSaveWithThingMap(thingMap, templateType, tenantCode);
AssertUtils.isBlank(templateType, "物模板不存在,请配置物模板");
// 同步物指标异步
// thingModelExecutor.execute(() -> syncDict(templateType, tenantCode));
// 生成物关系同步
// 查询出当前租户下类型为${templateType}且不在任何物关系中的物实体
// List<IotThingEntity> nonRelationThings = iotThingEntityService.selectNonRelationThings(tenantCode, templateType);
/*if (!CollectionUtil.isEmpty(nonRelationThings)) {
// 需要新增的物关系
if (STATION_TEMPLATE_TYPE.equals(templateType)) {
createTopRelationDetails(nonRelationThings, tenantCode);
} else {
createSubRelationDetails(nonRelationThings, simpleRelations, tenantCode);
}
}*/
// 生成数据源异步
List<IotThingEntity> things =
iotThingEntityService.list(
QueryWrapper.create().eq(IotThingEntity::getTenantCode, tenantCode));
generateThingSource(things, tenantCode);
}
/* private void createTopRelationDetails(List<IotThingEntity> things, Long tenantCode){
Long maxSort = iotThingRelationDetailService.getMaxSort(stationProperties.getRelationId());
List<IotThingRelationDetailEntity> details = new ArrayList<>();
for (IotThingEntity thing : things) {
IotThingRelationDetailEntity detail =
new IotThingRelationDetailEntity()
.setSort(++maxSort)
.setFromId(stationProperties.getRelationId())
.setToId(thing.getId())
.setToCode(thing.getCode())
.setToName(thing.getName())
.setRootId(stationProperties.getRelationId())
.setRootThingId(thing.getId());
details.add(detail);
}
iotThingRelationDetailService.saveBatch(details);
}*/
/**
* 创建物关系详情
*
* @param things 本次新创建的物模板
* @param simpleRelations 携带所有物的父级id
* @param tenantCode 租户编码
*/
/* private void createSubRelationDetails(List<IotThingEntity> things, List<SimpleThingRelationDTO> simpleRelations, Long tenantCode) {
Set<String> toCodes = things.stream().map(IotThingEntity::getCode).collect(Collectors.toSet());
List<SimpleThingRelationDTO> validSimpleRelations =
simpleRelations.stream().filter(e -> toCodes.contains(e.getToCode())).toList();
Map<String, String> codeMap =
validSimpleRelations.stream()
.collect(
Collectors.toMap(
SimpleThingRelationDTO::getToCode,
SimpleThingRelationDTO::getFromCode));
Set<String> fromCodes =
validSimpleRelations.stream()
.map(SimpleThingRelationDTO::getFromCode)
.collect(Collectors.toSet());
List<IotThingEntity> fromThings = findUnTemplateThings(fromCodes, tenantCode);
Map<String, Long> fromtCodeIdMap =
fromThings.stream()
.collect(
Collectors.toMap(
IotThingEntity::getCode,
IotThingEntity::getId,
(v1, v2) -> v1));
Map<Long, Long> fromIdMaxSortMap = iotThingRelationDetailService.getMaxSortMap(fromtCodeIdMap.values());
Map<Long, Long> fromIdRootThingIdMap = iotThingRelationDetailService.getRootThingIds(fromtCodeIdMap.values());
List<IotThingRelationDetailEntity> details = new ArrayList<>();
for (IotThingEntity thing : things) {
String fromCode = codeMap.get(thing.getCode());
Long fromId = fromtCodeIdMap.get(fromCode);
Long maxSort = Optional.ofNullable(fromIdMaxSortMap.get(fromId)).orElse(0L);
long newMaxSort = maxSort + 1;
fromIdMaxSortMap.put(fromId, newMaxSort);
IotThingRelationDetailEntity detail =
new IotThingRelationDetailEntity()
.setSort(newMaxSort)
.setFromId(fromId)
.setToId(thing.getId())
.setToCode(thing.getCode())
.setToName(thing.getName())
.setRootId(stationProperties.getRelationId())
.setRootThingId(fromIdRootThingIdMap.get(fromId));
details.add(detail);
}
iotThingRelationDetailService.saveBatch(details);
}*/
/**
* 基于物模板同步物实体的属性,只有新创建的物才会进行属性同步
* @param templateType 物模板类型
* @param tenantCode 租户编码
*/
/* private void syncDict(String templateType, Long tenantCode){
// 查询当前租户下类型为${templateType}且没有任何属性的物实体
List<IotThingEntity> things = iotThingEntityService.selectNonAttrThings(tenantCode, templateType);
if (CollectionUtil.isEmpty(things)) return;
List<IotThingDictRelationEntity> templateDictRelations = iotThingDictRelationService.findByTemplate(templateType);
List<IotThingDictRelationEntity> targetDictList =
things.stream()
.map(t -> templateDictRelations.stream()
.map(d -> {
IotThingDictRelationEntity targetDict = new IotThingDictRelationEntity();
BeanUtils.copyProperties(d, targetDict);
targetDict.setId(null);
targetDict.setFromId(t.getId());
return targetDict;
})
.collect(Collectors.toList()))
.flatMap(Collection::stream)
.toList();
iotThingDictRelationService.saveBatch(targetDictList);
}*/
private List<SimpleThingRelationDTO> stationConvert2SimpleRelation(List<StationInfoEntity> stationList) {
return stationList.stream()
.map(e -> new SimpleThingRelationDTO(null, e.getStationId(), e.getStationName()))
.toList();
}
private List<SimpleThingRelationDTO> pileConvert2SimpleRelation(List<EquipmentInfoEntity> pileList) {
return pileList.stream()
.map(e -> new SimpleThingRelationDTO(e.getStationId(), e.getEquipmentId(), e.getEquipmentName()))
.toList();
}
private List<SimpleThingRelationDTO> gunConvert2SimpleRelation(List<ConnectorInfoEntity> gunList) {
return gunList.stream()
.map(e -> new SimpleThingRelationDTO(e.getEquipmentId(), e.getConnectorId(), e.getConnectorName()))
.toList();
}
private void generateThingSource(List<IotThingEntity> things, Long tenantCode){
List<Long> thingIds =
things.stream().map(IotThingEntity::getId).collect(Collectors.toList());
applicationEventPublisher.publishEvent(
new ThingRelationDetailSaveEvent(
this,
stationProperties.getRelationId(),
thingIds,
tenantCode));
}
private List<IotThingEntity> findUnTemplateThings(Collection<String> codes, Long tenantCode) {
return iotThingEntityService
.getMapper()
.selectListByQuery(
QueryWrapper.create()
.in(IotThingEntity::getCode, codes)
.eq(IotThingEntity::getTenantCode, tenantCode)
.eq(IotThingEntity::getTemplateMark, TemplateMark.NO.getValue()));
}
}

272
modules/qingyuan/src/main/java/com/thing/qingyuan/chargeStation/task/StationTask.java

@ -0,0 +1,272 @@
package com.thing.qingyuan.chargeStation.task;
import com.alibaba.fastjson.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderDetailsDTO;
import com.thing.qingyuan.chargeStation.dto.ChargeOrderHeadDTO;
import com.thing.qingyuan.chargeStation.dto.StationOrderAgg;
import com.thing.qingyuan.chargeStation.entity.ChargeOrderHeadEntity;
import com.thing.qingyuan.chargeStation.entity.ConnectorInfoEntity;
import com.thing.qingyuan.chargeStation.entity.EquipmentInfoEntity;
import com.thing.qingyuan.chargeStation.service.ChargeOrderDetailsService;
import com.thing.qingyuan.chargeStation.service.ChargeOrderHeadService;
import com.thing.qingyuan.chargeStation.service.ConnectorInfoService;
import com.thing.qingyuan.chargeStation.service.EquipmentInfoService;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.data.event.QueueConsumerEvent;
import com.thing.common.data.proto.QueueProto.DataProto;
import com.thing.quartz.timetask.task.ITask;
import com.thing.queue.util.Topics;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author SiYang
* @date 2024/02/01 16:59
* @description 每日订单数据汇总
*/
@Slf4j
@RequiredArgsConstructor
@Component("StationTask")
public class StationTask implements ITask {
private final ConnectorInfoService gunService;
private final EquipmentInfoService pileService;
private final ChargeOrderHeadService orderHeadService;
private final ApplicationEventPublisher eventPublisher;
private final ChargeOrderDetailsService orderDetailsService;
/**
* 1. 查询完成时间在昨日的订单数据
* 2. 按枪的维度汇总数据
* 3. 按桩的维度再次汇总
* 4. 按站的维度再次汇总
* 5. 推送数据
* @param params json格式支持字段如下
* - startTime: 订单结束时间的起始时间窗口 (yyyy-MM-dd HH:mm:ss)
* - endTime: 订单结束时间的结束时间窗口 (yyyy-MM-dd HH:mm:ss)
*/
@Override
public void run(String params) {
getDayList(params).forEach(timePair -> {
handleSequence(timePair);
handleAgg(timePair);
});
}
/**
* 时序数据推送电流电压剩余电量充电量
* @param timePair 某天的开始时间和结束时间
*/
private void handleSequence(Pair<String, String> timePair) {
Pair<String, String> latestTimePair = convert2LatestTime(timePair.getLeft());
List<ChargeOrderDetailsDTO> orderDetails = getOrderDetails(latestTimePair);
List<DataProto> dataProtoList =
orderDetails.stream()
.map(ChargeOrderDetailsDTO::toProtoDataList)
.flatMap(List::stream)
.toList();
if (!dataProtoList.isEmpty()) {
eventPublisher.publishEvent(
new QueueConsumerEvent(Topics.V1_TSKV_HISTORY.getValue(), dataProtoList));
}
}
/**
* 按指定时间聚合数据
* @param timePair 某天的开始时间和结束时间
*/
private void handleAgg(Pair<String, String> timePair){
// 计算本次汇总数据所在的时间戳
Long ts = DateTimeUtils.convertTimeToLong(timePair.getLeft());
// 查询本次汇总数据所需使用的订单列表
List<ChargeOrderHeadDTO> orders = getOrders(timePair);
// 汇总枪
Map<String, List<ChargeOrderHeadDTO>> gunOrderMap =
orders.stream().collect(Collectors.groupingBy(ChargeOrderHeadDTO::getConnectorId));
Map<String, StationOrderAgg> gunDailyAggMap = aggGunOrders(gunOrderMap, ts);
// 汇总桩
Map<String, List<String>> pileGunIdMap = getPileGunIdMap(gunOrderMap.keySet());
Map<String, StationOrderAgg> pileDailyAggMap = aggSubDeviceData(pileGunIdMap, gunDailyAggMap, ts);
// 汇总站
Map<String, List<String>> stationPileIdMap = getStationPileIdMap(pileGunIdMap.keySet());
aggSubDeviceData(stationPileIdMap, pileDailyAggMap, ts);
}
/**
* 跨天任务支持
*
* @param params 任务参数
* @return 每天的起始和结束时间列表
*/
private List<Pair<String, String>> getDayList(String params) {
List<Pair<String, String>> dayList = new ArrayList<>();
// 默认计算: 当前时间在00:05分前那么计算昨日数据 否则计算今日数据目的防止遗漏临界情况下的订单
if (StringUtils.isBlank(params)) {
LocalDateTime currentTime = LocalDateTime.now();
LocalDate today = currentTime.toLocalDate();
boolean calculateYesterday = currentTime.getHour() == 0 && currentTime.getMinute() <= 5;
String start = getDayStart(calculateYesterday ? today.minusDays(1) : today);
String end = getDayStart(calculateYesterday ? today : today.plusDays(1));
dayList.add(Pair.of(start, end));
return dayList;
}
// 按参数解析出多天的起始和结束时间
JSONObject jsonObject = JSONObject.parseObject(params);
LocalDateTime startTime = getDayStart(jsonObject.getString("startTime"));
LocalDateTime endTime = DateTimeUtils.parseDateTime(jsonObject.getString("endTime"));
while (!startTime.isAfter(endTime)) {
String start = startTime.format(DateTimeUtils.DATE_TIME_PATTERN);
String end = getDayStart(startTime.toLocalDate().plusDays(1));
dayList.add(Pair.of(start, end));
startTime = startTime.plusDays(1);
}
return dayList;
}
private Pair<String, String> convert2LatestTime(String dateTime) {
LocalDateTime localDateTime = DateTimeUtils.parseDateTime(dateTime);
LocalDateTime now = LocalDateTime.now();
LocalDateTime formatTime =
localDateTime
.withHour(now.getHour())
.withMinute(now.getMinute())
.withSecond(now.getSecond());
String start;
if (formatTime.getHour() == 0 && formatTime.getMinute() <= 10) {
start = getDayStart(formatTime.toLocalDate());
} else {
start = formatTime.minusMinutes(10).format(DateTimeUtils.DATE_TIME_PATTERN);
}
String end = formatTime.format(DateTimeUtils.DATE_TIME_PATTERN);
return Pair.of(start, end);
}
private List<ChargeOrderHeadDTO> getOrders(Pair<String, String> timePair) {
return orderHeadService.listAs(
QueryWrapper.create()
.between(
ChargeOrderHeadEntity::getEndTime,
timePair.getLeft(),
timePair.getRight()),
ChargeOrderHeadDTO.class);
}
private List<ChargeOrderDetailsDTO> getOrderDetails(Pair<String, String> timePair) {
return orderDetailsService.getLatestDetails(timePair.getLeft(), timePair.getRight());
}
private Map<String, List<String>> getPileGunIdMap(Collection<String> gunIds) {
if (gunIds.isEmpty()) return new HashMap<>(1);
List<ConnectorInfoEntity> gunList = gunService.listByIds(gunIds);
return gunList.stream()
.collect(
Collectors.groupingBy(
ConnectorInfoEntity::getEquipmentId,
Collectors.mapping(
ConnectorInfoEntity::getConnectorId, Collectors.toList())));
}
private Map<String, List<String>> getStationPileIdMap(Collection<String> pileIds) {
if(pileIds.isEmpty()) return new HashMap<>(1);
List<EquipmentInfoEntity> pileList = pileService.listByIds(pileIds);
return pileList.stream()
.collect(
Collectors.groupingBy(
EquipmentInfoEntity::getStationId,
Collectors.mapping(
EquipmentInfoEntity::getEquipmentId, Collectors.toList())));
}
/**
* 仅针对充电枪的聚合
*
* @param orderMap 订单按充电枪id分组后的map
* @param ts 汇总数据所在时间戳
* @return 充电枪的汇总数据
*/
private Map<String, StationOrderAgg> aggGunOrders(
Map<String, List<ChargeOrderHeadDTO>> orderMap, Long ts) {
Map<String, StationOrderAgg> orderAggMap = new HashMap<>();
orderMap.forEach(
(gunId, orderList) -> {
StationOrderAgg orderAgg =
orderList.stream()
.reduce(
new StationOrderAgg(gunId),
StationOrderAgg::add,
(x, y) -> null);
orderAggMap.put(gunId, orderAgg);
});
List<StationOrderAgg> orderAggList = new ArrayList<>(orderAggMap.values());
publish(orderAggList, ts);
return orderAggMap;
}
/**
* 将子设备的聚合数据进一步聚合成为父设备的聚合数据
*
* @param deviceCodeMap 父设备id, 子设备id列表组成的map
* @param subDeviceAggMap 子设备的聚合数据map
* @param ts 数据所在时间戳
* @return 父设备的聚合数据
*/
private Map<String, StationOrderAgg> aggSubDeviceData(
Map<String, List<String>> deviceCodeMap,
Map<String, StationOrderAgg> subDeviceAggMap,
Long ts) {
Map<String, StationOrderAgg> parentDeviceAggMap = new HashMap<>();
deviceCodeMap.forEach(
(parentDeviceId, subDeviceIdList) -> {
List<StationOrderAgg> subDeviceAggList =
subDeviceIdList.stream().map(subDeviceAggMap::get).toList();
StationOrderAgg parentDeviceAgg =
subDeviceAggList.stream()
.reduce(StationOrderAgg::add)
.orElse(new StationOrderAgg());
parentDeviceAgg.setDeviceCode(parentDeviceId);
parentDeviceAggMap.put(parentDeviceId, parentDeviceAgg);
});
List<StationOrderAgg> orderAggList = new ArrayList<>(parentDeviceAggMap.values());
publish(orderAggList, ts);
return parentDeviceAggMap;
}
private void publish(List<StationOrderAgg> orderAggList, Long ts) {
if (CollectionUtils.isEmpty(orderAggList)) return;
List<DataProto> protoList =
orderAggList.stream()
.map(orderAgg -> orderAgg.toProtoData(ts, "am"))
.flatMap(Collection::stream)
.toList();
if (!protoList.isEmpty()) {
eventPublisher.publishEvent(
new QueueConsumerEvent(Topics.V1_TSKV_HISTORY.getValue(), protoList));
}
}
private String getDayStart(LocalDate date) {
return LocalDateTime.of(date, LocalTime.MIN).format(DateTimeUtils.DATE_TIME_PATTERN);
}
private LocalDateTime getDayStart(String date) {
return DateTimeUtils.parseDateTime(date).toLocalDate().atStartOfDay();
}
}

112
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/ManageBoardController.java

@ -0,0 +1,112 @@
package com.thing.qingyuan.manageboard.controller;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.basedevice.dto.DeviceDTO;
import com.thing.qingyuan.basedevice.entity.DeviceEntity;
import com.thing.qingyuan.basedevice.mapper.DeviceMapper;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.manageboard.service.ManageBoardService;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 管理端主平台
*/
@RestController
@RequestMapping("manage/board")
@Tag(name="管理端主平台")
@RequiredArgsConstructor
public class ManageBoardController {
private final ManageBoardService boardService;
private final DeviceMapper deviceMapper;
@PostMapping ("map")
@Operation(summary="管理端主平台-光伏地图")
private Result<List<ScreenData>> mapInfoByNameAndType(@RequestBody MapParam mapParam){
return boardService.mapInfoByNameAndType(mapParam);
}
@GetMapping ("plantList")
@Operation(summary="管理端主平台-光伏项目下拉列表")
private Result<List<PlantReq>> plantList(){
return boardService.plantList();
}
@PostMapping ("plantInfoList")
@Operation(summary="管理端主平台,光伏子平台-光伏项目发电量,上网量,减排量等信息,可按名称模糊过滤")
private Result<List<PlantInfoReq>> plantInfoList(@RequestBody FindParam param){
return boardService.plantInfoList(param);
}
@GetMapping ("totalInfo")
@Operation(summary="管理端主平台-光伏项目数量,总装机容量,发电量,收益等统计信息")
private Result<TotalInfo> totalInfo(){
return boardService.totalInfo();
}
@PostMapping ("reduction")
@Operation(summary="管理端主平台-光伏节能减排信息")
private Result<ReductionStatistics> reduction(){
return boardService.reduction();
}
@GetMapping ("alertList")
@Operation(summary="管理端主平台,光伏子平台-光伏项目告警记录列表")
private Result<List<AlertDTO>> alertList(){
return boardService.alertList();
}
@PostMapping ("findListByAttrCodeAndType")
@Operation(summary="管理端主平台,月/年得电量用量查询")
private Result<DataReq> findListByAttrCodeAndType(@RequestBody DataParam dataParam){
return boardService.findListByAttrCodeAndType(dataParam);
}
@PostMapping ("findYOYList")
@Operation(summary="管理端主平台,年发电量同比分析")
private Result<List<YOYDataReq>> findYOYList(@RequestBody DataParam dataParam){
return boardService.findYOYList(dataParam);
}
@PostMapping ("pVReport")
@Operation(summary="管理端主平台,光伏数据报表")
private Result<List<PVReport>> pVReport(@RequestBody PVParam param){
return boardService.pVReport(param);
}
@PostMapping ("pVReportExport")
@Operation(summary="管理端主平台,光伏数据报表导出")
private void pVReportExport(@RequestBody PVParam param, HttpServletResponse response) {
ExcelUtils.exportExcel(boardService.pVReport(param).getData(), "光伏数据报表", null, PVReport.class, "光伏报表.xls", response);
}
@GetMapping("deviceInfoByPlantId/{id}")
@Operation(summary="逆变器列表查询")
private Result<List<DeviceDTO>> deviceInfoByPlantId(@PathVariable("id") Long id){
QueryWrapper queryWrapper = QueryWrapper.create().eq(DeviceEntity::getPlantId, id).eq(DeviceEntity::getDeviceType,2);
List<DeviceDTO> result = deviceMapper.selectListByQueryAs(queryWrapper,DeviceDTO.class);
result.forEach(temp->{
DeviceDTO dto = deviceMapper.selectOneByQueryAs(QueryWrapper.create().eq(DeviceEntity::getDeviceId, temp.getUpDeviceId()),DeviceDTO.class);
try {
temp.setUpStatus(dto.getStatus());
temp.setUpAlias(dto.getAlias());
} catch (Exception e) {
temp.setUpStatus(1);
}
});
return new Result<List<DeviceDTO>>().ok(result);
}
}

80
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/ManageChargeController.java

@ -0,0 +1,80 @@
package com.thing.qingyuan.manageboard.controller;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.manageboard.service.ManageChargeService;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("charge/board")
@Tag(name="管理端主平台,充电站")
@RequiredArgsConstructor
public class ManageChargeController {
private final ManageChargeService manageChargeService;
@PostMapping("map")
@Operation(summary="管理端主平台-充电站地图")
private Result<List<ScreenData>> mapInfoByNameAndType(@RequestBody MapParam mapParam){
return manageChargeService.mapInfoByNameAndType(mapParam);
}
@GetMapping("totalInfo")
@Operation(summary="管理端主平台-充电站数量,充电枪数量,年度充电量,年度充电金额等信息")
private Result<ChargeTotalInfo> totalInfo(){
return manageChargeService.totalInfo();
}
@GetMapping("siteTypeInfo")
@Operation(summary="管理端主平台-年度站点类型分析")
private Result<List<SiteTypeInfo>> siteTypeInfo(){
return manageChargeService.siteTypeInfo();
}
@GetMapping("chargingGunState")
@Operation(summary="管理端主平台-充电枪实时状态")
private Result<List<ChargingGunState>> chargingGunState(){
return manageChargeService.chargingGunState();
}
@PostMapping("stationInfo")
@Operation(summary="管理端主平台-充电站详情")
private Result<List<StationInfoReq>> stationInfo(@RequestBody FindParam param){
return manageChargeService.stationInfo(param);
}
@PostMapping ("findListByAttrCodeAndType")
@Operation(summary="管理端主平台,月充电分析/年度充电时常趋势")
private Result<DataReq> findListByAttrCode(@RequestBody GunDataParam dataParam){
return manageChargeService.findListByAttrCode(dataParam);
}
@PostMapping ("findYOYList")
@Operation(summary="管理端主平台,年发电量同比分析")
private Result<List<YOYDataReq>> findYOYList(@RequestBody GunDataParam dataParam){
return manageChargeService.findYOYList(dataParam);
}
@PostMapping ("gunReport")
@Operation(summary="管理端主平台,光伏数据报表")
private Result<List<StationInfoReq>> gunReport(@RequestBody PVParam param){
return manageChargeService.gunReport(param);
}
@PostMapping ("gunReportExport")
@Operation(summary="管理端主平台,充电站数据报表导出")
private void gunReportExport(@RequestBody PVParam param, HttpServletResponse response) {
ExcelUtils.exportExcel(manageChargeService.gunReport(param).getData(), "充电站数据报表", null, StationInfoReq.class, "充电站报表.xls", response);
}
}

96
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/controller/PlantController.java

@ -0,0 +1,96 @@
package com.thing.qingyuan.manageboard.controller;
import com.thing.qingyuan.manageboard.dto.PlantDTO;
import com.thing.qingyuan.manageboard.service.PlantService;
import com.thing.common.core.annotation.LogOperation;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@RestController
@RequestMapping("plant")
@Tag(name="光伏项目基础信息")
@RequiredArgsConstructor
public class PlantController {
private final PlantService plantService;
@GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始") ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数") ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
@Parameter(name = "buildDate", description = "建站日期"),
@Parameter(name = "area", description = "区域"),
@Parameter(name = "key", description = "站点idor名称")
})
public Result<PageData<PlantDTO>> page(@RequestParam Map<String, Object> params){
PageData<PlantDTO> page = plantService.getPageData(params, PlantDTO.class);
return new Result<PageData<PlantDTO>>().ok(page);
}
@GetMapping("{id}")
@Operation(summary="信息")
public Result<PlantDTO> get(@PathVariable("id") Long id){
PlantDTO data = plantService.getByIdAs(id, PlantDTO.class);
return new Result<PlantDTO>().ok(data);
}
@GetMapping("list")
@Operation(summary="电站列表信息")
public Result<List<PlantDTO>> list(@RequestParam Map<String, Object> params){
List<PlantDTO> plantDTOS = plantService.listAs(params, PlantDTO.class);
return new Result<List<PlantDTO>>().ok(plantDTOS);
}
@PostMapping
@Operation(summary="保存")
@LogOperation("保存")
public Result<Void> save(@RequestBody PlantDTO dto){
plantService.saveDto(dto);
return new Result<>();
}
@PutMapping
@Operation(summary="修改")
@LogOperation("修改")
public Result<Void> update(@RequestBody PlantDTO dto){
plantService.updateDto(dto);
return new Result<>();
}
@DeleteMapping
@Operation(summary="删除")
@LogOperation("删除")
public Result<Void> delete(@RequestBody Long[] ids){
plantService.batchDelete(ids);
return new Result<>();
}
@GetMapping("export")
@Operation(summary="导出")
@LogOperation("导出")
public void export( @RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
List<PlantDTO> list = plantService.listAs(params, PlantDTO.class);
//ExcelUtils.exportExcelToTarget(response, null, "光伏项目点位信息", list, PlantExcel.class);
}
}

20
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ChargeTotalInfo.java

@ -0,0 +1,20 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema( description= "充电站统计信息")
public class ChargeTotalInfo {
@Schema( description= "充电站数量")
private Integer stationCount;
@Schema( description= "充电枪数量")
private Integer connectorCount;
@Schema( description= "年度充电量")
private BigDecimal yearCharge;
@Schema( description= "年充电金额")
private BigDecimal yearMoney;
}

22
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ChargingGunState.java

@ -0,0 +1,22 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@Schema(description = "充电枪实时状态")
@AllArgsConstructor
@NoArgsConstructor
public class ChargingGunState {
@Schema(description = "充电枪状态名称")
private String stateName;
@Schema(description = "充电桩状态编码")
private String stateCode;
@Schema(description = "数量")
private Integer num;
}

22
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/DataParam.java

@ -0,0 +1,22 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "查询入参")
public class DataParam {
@Schema(description = "物编码")
private String thingCode;
@Schema(description = "属性编码 月 传A29dd,年传A29mm")
private String attrCode;
@Schema(description = "属性类型,dd 月,mm年")
private String attrType;
private Long startTime;
private Long endTime;
}

28
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/DataReq.java

@ -0,0 +1,28 @@
package com.thing.qingyuan.manageboard.dto;
import com.thing.common.data.tskv.TsKvDTO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "用量查询,响应结果")
public class DataReq {
@Schema(description = "用量结果集合")
private List<TsKvDTO> tskvs;
@Schema(description = "属性信息")
private AttrInfo attrInfo;
@Schema(description = "属性信息")
@Data
public static class AttrInfo{
@Schema(description = "属性编码")
private String attrCode;
@Schema(description = "属性名称")
private String attrName;
@Schema(description = "属性单位")
private String attrUint;
}
}

15
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/FindParam.java

@ -0,0 +1,15 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "模糊查找入参")
public class FindParam {
@Schema(description = "项目名称/站点名称")
private String plantName;
}

20
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/GunDataParam.java

@ -0,0 +1,20 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "查询入参")
public class GunDataParam {
@Schema(description = "属性编码 充电电量: 月A29dd,年A29mm,充电时长月A201dd,年A201mm,充电次数 A202dd")
private String attrCode;
@Schema(description = "属性类型,dd 月,mm年")
private String attrType;
private Long startTime;
private Long endTime;
}

17
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/GunReportParam.java

@ -0,0 +1,17 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "充电站报表查询入参")
public class GunReportParam {
@Schema(description = "区域")
private String area;
@Schema(description = "站点名称")
private String stationName;
@Schema(description = "时间 月 入参 yyyy-MM 年入参 yyyy")
private String date;
@Schema(description = "时间类型 dd月,mm年")
private String dateType;
}

16
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/MapParam.java

@ -0,0 +1,16 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "地图统计信息请求入参")
public class MapParam {
@Schema(description = "城市名称,全国的时候不传")
private String cityName;
@Schema(description = "类型,1全国,2全省,3全市")
private String type;
}

20
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PVParam.java

@ -0,0 +1,20 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "光伏报表查询入参")
public class PVParam {
@Schema(description = "区域")
private String area;
@Schema(description = "项目名称")
private String plantName;
@Schema(description = "时间 月 入参 yyyy-MM 年入参 yyyy")
private String date;
@Schema(description = "时间类型 dd月,mm年")
private String dateType;
}

68
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PVReport.java

@ -0,0 +1,68 @@
package com.thing.qingyuan.manageboard.dto;
import cn.afterturn.easypoi.excel.annotation.Excel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "光伏项目报表")
public class PVReport {
@Schema(description = "电站Id")
private Long plantId;
@Excel(name = "序号")
private String sortStr;
@Schema(description = "电站名称")
@Excel(name = "项目名称")
private String plantName;
@Schema(description = "所属区县")
@Excel(name = "区域")
private String area;
@Schema(description = "电站装机容量 (单位:MWp)")
@Excel(name = "装机容量(MWp)")
private BigDecimal capacity = BigDecimal.ZERO;
@Schema(description = "理论发电量")
@Excel(name = "理论发电量(kWh)")
private BigDecimal theoryEnergyPhotovoltaic = BigDecimal.ZERO;
@Schema(description = "发电量")
@Excel(name = "发电量(kWh)")
private BigDecimal energyPhotovoltaic = BigDecimal.ZERO;
@Schema(description = "综合效率")
@Excel(name = "综合效率(%)")
private BigDecimal oee = BigDecimal.ZERO;
@Schema(description = "消纳量")
@Excel(name = "消纳量(kWh)")
private BigDecimal consumption = BigDecimal.ZERO;
@Schema(description = "上网电量")
@Excel(name = "上网电量(kWh)")
private BigDecimal internetUsage= BigDecimal.ZERO;
@Schema(description = "减排量")
@Excel(name = "减排量(kgCO₂)")
private BigDecimal co2 = BigDecimal.ZERO;
@Schema(description = "建站日期")
private String buildDate;
@Schema(description = "所属国家")
private String country;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "电站所在具体地址")
private String address;
@Schema(description = "电站状态(1 正常 2 离线 3报警)")
private Integer status;
@Schema(description = "衰减率")
private BigDecimal attenuation = BigDecimal.ZERO;
@Schema(description = "日照时常")
private BigDecimal sunshine = BigDecimal.ZERO;
private Integer sort;
public String getSortStr() {
if(sort==-1){
return "--";
}
return sort.toString();
}
}

55
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantDTO.java

@ -0,0 +1,55 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏项目点位信息")
public class PlantDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "电站Id")
private Long plantId;
@Schema(description = "电站名称")
private String plantName;
@Schema(description = "建站日期(yyyy-MM-dd)")
private String buildDate;
@Schema(description = "所属国家")
private String country;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "所属区县")
private String area;
@Schema(description = "电站所在具体地址")
private String address;
@Schema(description = "电站状态(1 正常 2 离线 3报警)")
private Integer status;
@Schema(description = "电站装机容量 (单位:kWp)")
private BigDecimal capacity;
@Schema(description = "电站最后同步数据时间")
private String lastReportTime;
@Schema(description = "经度")
private BigDecimal longitude;
@Schema(description = "纬度")
private BigDecimal latitude;
@Schema(description = "并网日期(yyyy-MM-dd)")
private String gridDate;
@Schema(description = "衰减率")
private BigDecimal attenuation;
@Schema(description = "日照时常")
private BigDecimal sunshine;
}

57
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantInfoReq.java

@ -0,0 +1,57 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏项目发电量,上网量,减排量等信息")
@AllArgsConstructor
@NoArgsConstructor
public class PlantInfoReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "电站Id")
private Long plantId;
@Schema(description = "电站名称")
private String plantName;
@Schema(description = "建站日期")
private String buildDate;
@Schema(description = "装机容量 (单位:kWp)")
private BigDecimal capacity;
@Schema(description = "年发电量(单位:万kWh)")
private BigDecimal powerGeneration;
@Schema(description = "年上网量 (单位:万kWh)")
private BigDecimal internetUsage;
@Schema(description = "年减排量 (单位:tCO₂)")
private BigDecimal minusTCO2;
@Schema(description = "所属国家")
private String country;
@Schema(description = "所属省份")
private String province;
@Schema(description = "所属城市")
private String city;
@Schema(description = "所属区县")
private String area;
@Schema(description = "电站所在具体地址")
private String address;
@Schema(description = "电站状态(1 正常 2 离线 3报警)")
private Integer status;
@Schema(description = "衰减率")
private BigDecimal attenuation;
@Schema(description = "日照时常")
private BigDecimal sunshine;
}

32
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/PlantReq.java

@ -0,0 +1,32 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serial;
import java.io.Serializable;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏项目点位信息")
@AllArgsConstructor
@NoArgsConstructor
public class PlantReq implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "电站Id")
private Long plantId;
@Schema(description = "电站名称")
private String plantName;
@Schema(description = "序号")
private Integer sort = 0;
}

36
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/ReductionStatistics.java

@ -0,0 +1,36 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@Schema( description= "节能减排统计")
@NoArgsConstructor
@AllArgsConstructor
public class ReductionStatistics {
@Schema(description = "年度信息")
private ReductionInfo nowYearInfo;
@Schema(description = "总信息")
private ReductionInfo totalInfo;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class ReductionInfo {
@Schema(description = "属性主键")
private BigDecimal tce;
@Schema(description = "属性名称")
private BigDecimal co2;
@Schema(description = "属性值")
private BigDecimal tree;
}
}

30
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/SiteTypeInfo.java

@ -0,0 +1,30 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@Schema(description = "站点类型分析结果")
@NoArgsConstructor
@AllArgsConstructor
public class SiteTypeInfo {
@Schema( description= "站点类型名称")
private String siteTypeName;
@Schema( description= "站点类型编码")
private String siteTypeCode;
@Schema( description= "年度充电量")
private BigDecimal yearCharge;
@Schema( description= "占比")
private BigDecimal proportion;
}

61
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/StationInfoReq.java

@ -0,0 +1,61 @@
package com.thing.qingyuan.manageboard.dto;
import cn.afterturn.easypoi.excel.annotation.Excel;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
@Schema(description = "充电站详情")
public class StationInfoReq {
@Schema(description = "充电站名称")
private String stationId;
@Excel(name = "序号")
private String sortStr;
@Schema(description = "充电站名称")
@Excel(name = "站点名称")
private String stationName;
@Schema(description = "运营商id")
private String operatorId;
@Schema(description = "区")
@Excel(name = "区域")
private String area;
@Schema(description = "运营商名称")
@Excel(name = "运营商")
private String operatorName;
@Schema( description= "充电枪数量")
@Excel(name = "充电枪数量")
private Integer gunCount = 0;
@Schema( description= "日充电量")
private BigDecimal dayCharge;
@Schema( description= "年度充电量/充电电量")
@Excel(name = "充电电量(kWh)")
private BigDecimal yearCharge = BigDecimal.ZERO;
@Schema( description= "枪均充电量")
@Excel(name = "枪均充电量(kWh/个)")
private BigDecimal gunCharge = BigDecimal.ZERO;
@Schema( description= "年度充电时常/充电时常")
@Excel(name = "充电时常(h)")
private BigDecimal yearOften = BigDecimal.ZERO;
@Schema( description= "枪均充电时常")
@Excel(name = "枪均充电时常(h/个)")
private BigDecimal gunChargeCount = BigDecimal.ZERO;
@Schema( description= "年度充电次数/充电次数")
@Excel(name = "充电次数(次)")
private BigDecimal yearChargeCount = BigDecimal.ZERO;
@Schema( description= "枪均充电次数")
@Excel(name = "枪均充电次数(次/个)")
private BigDecimal gunOften;
@Schema( description= "序号")
private Integer sort=0;
public String getSortStr() {
if(sort==-1){
return "--";
}
return sort.toString();
}
}

27
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/TotalInfo.java

@ -0,0 +1,27 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.math.BigDecimal;
@Data
@Schema( description= "光伏项目统计信息")
public class TotalInfo {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "光伏数量")
private Integer num =0;
@Schema(description = "电站装机容量 (单位:MWp)")
private BigDecimal capacity = BigDecimal.ZERO;
@Schema(description = "年发电量(单位:万kWh)")
private BigDecimal electricityUsage = BigDecimal.ZERO;
@Schema(description = "年度收益(单位:万元)")
private BigDecimal income = BigDecimal.ZERO;
}

39
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/dto/YOYDataReq.java

@ -0,0 +1,39 @@
package com.thing.qingyuan.manageboard.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.math.RoundingMode;
@Data
@Schema(description = "年发电量同比")
public class YOYDataReq {
@Schema(description = "时间")
private Long ts;
@Schema(description = "今年发/冲电量")
private BigDecimal nowYearVal;
@Schema(description = "去年发/冲电量")
private BigDecimal lastYearVal;
@Schema(description = "同比")
private String yoy;
@Schema(description = "属性单位")
private String unit;
@Schema(description = "属性名称")
private String attrName;
@Schema(description = "属性编码")
private String attrCode;
public String getYoy() {
if(nowYearVal.compareTo(BigDecimal.ZERO)==0){
return "--";
}
BigDecimal difference = nowYearVal.subtract(lastYearVal);
try {
return difference.divide(lastYearVal, 4, RoundingMode.HALF_UP).toString();
} catch (Exception e) {
return "--";
}
}
}

90
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/entity/PlantEntity.java

@ -0,0 +1,90 @@
package com.thing.qingyuan.manageboard.entity;
import com.mybatisflex.annotation.Id;
import com.mybatisflex.annotation.Table;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@EqualsAndHashCode(callSuper=false)
@Table(value = "plant",dataSource = "systemCollect")
public class PlantEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 电站Id
*/
@Id
private Long plantId;
/**
* 电站名称
*/
private String plantName;
/**
* 建站日期yyyy-MM-dd
*/
private String buildDate;
/**
* 所属国家
*/
private String country;
/**
* 所属省份
*/
private String province;
/**
* 所属城市
*/
private String city;
/**
* 所属区县
*/
private String area;
/**
* 电站所在具体地址
*/
private String address;
/**
* 电站状态1 正常 2 离线 3报警
*/
private Integer status;
/**
* 电站装机容量 单位kWp
*/
private BigDecimal capacity;
/**
* 电站最后同步数据时间
*/
private String lastReportTime;
/**
* 经度
*/
private BigDecimal longitude;
/**
* 纬度
*/
private BigDecimal latitude;
/**
* 并网日期yyyy-MM-dd
*/
private String gridDate;
/**
* 衰减率
*/
private BigDecimal attenuation;
/**
* 日照时常
*/
private BigDecimal sunshine;
}

18
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/mapper/PlantMapper.java

@ -0,0 +1,18 @@
package com.thing.qingyuan.manageboard.mapper;
import com.mybatisflex.annotation.UseDataSource;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.common.orm.mapper.PowerBaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Mapper
@UseDataSource("systemCollect")
public interface PlantMapper extends PowerBaseMapper<PlantEntity> {
}

29
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/ManageBoardService.java

@ -0,0 +1,29 @@
package com.thing.qingyuan.manageboard.service;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.common.core.web.response.Result;
import java.util.List;
public interface ManageBoardService {
Result<List<ScreenData>> mapInfoByNameAndType(MapParam mapParam);
Result<List<PlantReq>> plantList();
Result<List<PlantInfoReq>> plantInfoList(FindParam param);
Result<TotalInfo> totalInfo();
Result<ReductionStatistics> reduction();
Result<List<AlertDTO>> alertList();
Result<DataReq> findListByAttrCodeAndType(DataParam dataParam);
Result<List<YOYDataReq>> findYOYList(DataParam dataParam);
Result<List<PVReport>> pVReport(PVParam param);
}

25
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/ManageChargeService.java

@ -0,0 +1,25 @@
package com.thing.qingyuan.manageboard.service;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.common.core.web.response.Result;
import java.util.List;
public interface ManageChargeService {
Result<List<ScreenData>> mapInfoByNameAndType(MapParam mapParam);
Result<ChargeTotalInfo> totalInfo();
Result<List<SiteTypeInfo>> siteTypeInfo();
Result<List<ChargingGunState>> chargingGunState();
Result<List<StationInfoReq>> stationInfo(FindParam param);
Result<DataReq> findListByAttrCode(GunDataParam dataParam);
Result<List<YOYDataReq>> findYOYList(GunDataParam dataParam);
Result<List<StationInfoReq>> gunReport(PVParam param);
}

25
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/PlantService.java

@ -0,0 +1,25 @@
package com.thing.qingyuan.manageboard.service;
import com.thing.qingyuan.manageboard.dto.MapParam;
import com.thing.qingyuan.manageboard.dto.PlantDTO;
import com.thing.qingyuan.manageboard.dto.PlantInfoReq;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.common.orm.service.IBaseService;
import java.util.List;
import java.util.Map;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
public interface PlantService extends IBaseService<PlantEntity> {
Map<String,List<PlantDTO>> findByParam(MapParam mapParam);
List<PlantInfoReq> findByName(String plantName,String area);
}

551
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/ManageBoardServiceImpl.java

@ -0,0 +1,551 @@
package com.thing.qingyuan.manageboard.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.thing.carbon.energyrepory.dto.EnergyTimeLabelData;
import com.thing.qingyuan.alert.dto.AlertDTO;
import com.thing.qingyuan.alert.service.AlertService;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.qingyuan.manageboard.service.ManageBoardService;
import com.thing.qingyuan.manageboard.service.PlantService;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.qingyuan.util.CalculationUtil;
import com.thing.common.core.enumeration.AttributeTypeEnum;
import com.thing.common.core.utils.ConvertUtils;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.core.web.response.Result;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.thing.dict.dto.IotThingDictDTO;
import com.thing.thing.dict.service.IotThingDictService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ManageBoardServiceImpl implements ManageBoardService {
private final PlantService plantService;
private final TsKvService tskvService;
private final AlertService alertService;
private final IotThingDictService iotThingDictService;
@Override
public Result<List<ScreenData>> mapInfoByNameAndType(MapParam mapParam) {
List<ScreenData> result = new ArrayList<>();
Map<String,List<PlantDTO>> infoList = plantService.findByParam(mapParam);
if(mapParam.getType().equals("3")||mapParam.getType().equals("4")){
//全市的话按个统计
List<PlantDTO> dtos =infoList.values().stream()
.flatMap(List::stream)
.toList();
this.getAttrDataWithArea(dtos,result);
}else {
infoList.forEach((key, value) -> {
ScreenData screenData = new ScreenData();
screenData.setName(key);
this.getAttrDataWithCity(value,screenData);
result.add(screenData);
});
}
return new Result<List<ScreenData>>().ok(result);
}
@Override
public Result<List<PlantReq>> plantList() {
List<PlantReq> reqs = new ArrayList<>();
PlantReq req = new PlantReq(1000l,"总发电量",999);
reqs.add(req);
reqs.addAll(ConvertUtils.sourceToTarget(plantService.list(),PlantReq.class));
return new Result<List<PlantReq>>().ok(reqs);
}
@Override
public Result<List<PlantInfoReq>> plantInfoList(FindParam param) {
List<PlantInfoReq> reqs = plantService.findByName(param.getPlantName(),null);
reqs.forEach(temp->{
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodeAndAttrs(temp.getPlantId().toString(),List.of("A29yy","A30yy"),false);
Map<String,List<TsKvDTO>> map = tsKvDTOS.stream()
.collect(Collectors.groupingBy(TsKvDTO::getAttrKey));
BigDecimal a29yy = BigDecimal.ZERO; // 初始化a29yy
BigDecimal a30yy = BigDecimal.ZERO; // 初始化a30yy
BigDecimal co2 = BigDecimal.ZERO; // 初始化a30yy
for (Map.Entry<String, List<TsKvDTO>> entry : map.entrySet()) {
String key = entry.getKey();
List<TsKvDTO> val = entry.getValue();
if (key.equals("A29yy")) {
a29yy = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
try {
co2 = a29yy.multiply(BigDecimal.valueOf(0.000475)).setScale(4, RoundingMode.HALF_UP);
a29yy = a29yy.divide(BigDecimal.valueOf(10000),4,RoundingMode.HALF_UP);
} catch (Exception e) {
a29yy=BigDecimal.ZERO;
co2=BigDecimal.ZERO;
}
} else if (key.equals("A30yy")) {
a30yy = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
try {
a30yy = a30yy.divide(BigDecimal.valueOf(10000L), 4,RoundingMode.UP);
} catch (Exception e) {
a30yy= BigDecimal.ZERO;
}
}
}
temp.setInternetUsage(a30yy);
temp.setPowerGeneration(a29yy);
temp.setMinusTCO2(co2);
});
reqs.sort((p1, p2) -> p2.getPowerGeneration().compareTo(p1.getPowerGeneration()));
return new Result<List<PlantInfoReq>>().ok(reqs);
}
@Override
public Result<TotalInfo> totalInfo() {
TotalInfo result = new TotalInfo();
List<PlantEntity> list = plantService.list();
BigDecimal sumA29yy = nowTotalA29yy();
BigDecimal totalCapacity = list.stream()
.map(PlantEntity::getCapacity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
result.setNum(list.size());
result.setElectricityUsage(sumA29yy.setScale(4,RoundingMode.UP));
result.setCapacity(totalCapacity);
//todo 这里先写死为光伏租户得物编码后续再调整
List<TsKvDTO> kvDTOS = tskvService.findLatestByCodeAndAttrs("CO_1751771289957244928",List.of("A301"),false);
if(!kvDTOS.isEmpty()){
result.setIncome(BigDecimal.valueOf(Long.parseLong(kvDTOS.stream().findFirst().get().getVal())));
}
return new Result<TotalInfo>().ok(result);
}
@Override
public Result<ReductionStatistics> reduction() {
BigDecimal nowTotalA29yy = this.nowTotalA29yy();
BigDecimal allTotalA29yy = this.AllTotalA29yy();
BigDecimal tceRatio = BigDecimal.valueOf(0.0004);
BigDecimal co2Ratio = BigDecimal.valueOf(0.000475);
BigDecimal treeRatio = BigDecimal.valueOf(18.3).divide(BigDecimal.valueOf(40),8,RoundingMode.UP).multiply(BigDecimal.valueOf(1000));
ReductionStatistics.ReductionInfo nowYearInfo = new ReductionStatistics.ReductionInfo();
nowYearInfo.setTce(nowTotalA29yy.multiply(tceRatio).setScale(4,RoundingMode.UP));
nowYearInfo.setCo2(nowTotalA29yy.multiply(co2Ratio).setScale(4,RoundingMode.UP));
nowYearInfo.setTree(nowYearInfo.getCo2().multiply(treeRatio).setScale(4,RoundingMode.UP));
ReductionStatistics.ReductionInfo allInfo = new ReductionStatistics.ReductionInfo();
allInfo.setTce(allTotalA29yy.multiply(tceRatio).setScale(4,RoundingMode.UP));
allInfo.setCo2(allTotalA29yy.multiply(co2Ratio).setScale(4,RoundingMode.UP));
allInfo.setTree(allInfo.getCo2().multiply(treeRatio).setScale(4,RoundingMode.UP));
ReductionStatistics result = new ReductionStatistics(nowYearInfo,allInfo);
return new Result<ReductionStatistics>().ok(result);
}
@Override
public Result<List<AlertDTO>> alertList() {
List<AlertDTO> alertDTOS = alertService.listAs(new HashMap<>(),AlertDTO.class);
alertDTOS.sort((p1, p2) -> p2.getStartTime().compareTo(p1.getStartTime()));
return new Result<List<AlertDTO>>().ok(alertDTOS);
}
@Override
public Result<DataReq> findListByAttrCodeAndType(DataParam dataParam) {
DataReq req = new DataReq();
Long startTime;
Long endTime;
if(ObjectUtil.isNotEmpty(dataParam.getStartTime())&&ObjectUtil.isNotEmpty(dataParam.getEndTime())&&dataParam.getStartTime()!=0){
startTime = dataParam.getStartTime();
endTime = dataParam.getEndTime();
}else {
if(dataParam.getAttrType().equals("dd")){
startTime= DateTimeUtils.getMonthBeginTimestamp(System.currentTimeMillis());
}else {
startTime = DateTimeUtils.getYearBeginTimestamp(System.currentTimeMillis());
}
endTime = DateTimeUtils.getMonthEndTimestamp(System.currentTimeMillis());
}
AttributeTypeEnum attributeTypeEnum = AttributeTypeEnum.match(dataParam.getAttrType());
Instant instant = Instant.ofEpochMilli(startTime);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
List<LocalDateTime> timeRange = attributeTypeEnum.getTimeRange(dateTime);
List<EnergyTimeLabelData> energyTimeLabelData = this.generateEmptyData(timeRange, dataParam.getAttrType());
List<TsKvDTO> tskvs = new ArrayList<>();
if (dataParam.getThingCode().equals("1000")) {
List<PlantEntity> list = plantService.list();
List<String> entityCodes = list.stream().map(PlantEntity::getPlantId).map(String::valueOf).toList();
tskvs = tskvService.findTsKvByCodesAndAttrs(entityCodes,List.of(dataParam.getAttrCode()),startTime,endTime,false);
}else {
tskvs = tskvService.findTsKvByCodeAndAttr(dataParam.getThingCode(),dataParam.getAttrCode(),startTime,endTime,false);
}
Map<Long,List<TsKvDTO>> tsMap = tskvs.stream()
.collect(Collectors.groupingBy(TsKvDTO::getTs));
List<TsKvDTO> allInfo = new ArrayList<>();
energyTimeLabelData.forEach(temp->{
if(ObjectUtil.isNotEmpty(tsMap.get(temp.getTs()))){
BigDecimal val = tsMap.get(temp.getTs()).stream().map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
TsKvDTO tskv = new TsKvDTO(dataParam.getThingCode(),dataParam.getAttrCode(),temp.getTs(),val.setScale(4,RoundingMode.UP).toString());
allInfo.add(tskv);
}else {
TsKvDTO tskv = new TsKvDTO(dataParam.getThingCode(),dataParam.getAttrCode(),temp.getTs(),BigDecimal.ZERO.toString());
allInfo.add(tskv);
}
});
req.setTskvs(allInfo);
DataReq.AttrInfo attrInfo = new DataReq.AttrInfo();
IotThingDictDTO dictDTO = iotThingDictService.findDictByCode(dataParam.getAttrCode());
attrInfo.setAttrCode(dictDTO.getCode());
attrInfo.setAttrName(dictDTO.getName());
attrInfo.setAttrUint(dictDTO.getUnit());
req.setAttrInfo(attrInfo);
return new Result<DataReq>().ok(req);
}
@Override
public Result<List<YOYDataReq>> findYOYList(DataParam dataParam) {
List<YOYDataReq> result = new ArrayList<>();
DataReq nowYearList = this.findListByAttrCodeAndType(dataParam).getData();
dataParam.setStartTime(DateTimeUtils.fistDayOfLastYear());
dataParam.setEndTime(DateTimeUtils.lastDayOfLastYear());
DataReq lastYearList = this.findListByAttrCodeAndType(dataParam).getData();
List<TsKvDTO> last = lastYearList.getTskvs();
Map<Integer, List<TsKvDTO>> groupedMap = last.stream()
.collect(Collectors.groupingBy(dto -> Instant.ofEpochMilli(dto.getTs())
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.getMonth().getValue()));
nowYearList.getTskvs().forEach(temp->{
YOYDataReq req = new YOYDataReq();
LocalDate date = LocalDate.ofEpochDay(temp.getTs() / 86400000); // 将毫秒时间戳转换为 LocalDate 对象
Integer month = date.getMonthValue();
req.setTs(temp.getTs());
req.setAttrName(nowYearList.getAttrInfo().getAttrName());
req.setAttrCode(nowYearList.getAttrInfo().getAttrCode());
req.setUnit(nowYearList.getAttrInfo().getAttrUint());
List<TsKvDTO> tsKvDTOS = groupedMap.get(month);
if(ObjectUtil.isNotEmpty(tsKvDTOS)){
req.setLastYearVal(new BigDecimal(tsKvDTOS.stream().findFirst().get().getVal()));
}
req.setNowYearVal(new BigDecimal(temp.getVal()));
result.add(req);
});
return new Result<List<YOYDataReq>>().ok(result);
}
@Override
public Result<List<PVReport>> pVReport(PVParam param) {
List<PlantInfoReq> reqs = plantService.findByName(param.getPlantName(),param.getArea());
List<PVReport> result = ConvertUtils.sourceToTarget(reqs,PVReport.class);
LocalDateTime startTime = getBeginTime(param.getDateType(),param.getDate());
Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
long startTs = instant.toEpochMilli();
long endTs = startTs+1000L;
PVReport total = new PVReport();
total.setPlantName("合计");
total.setArea("--");
total.setSort(-1);
int sort = 1;
for (PVReport report : result) {
if(param.getDateType().equals("dd")){
getDataWithMonth(report,startTs,endTs,total);
}else {
getDataWithYear(report,startTs,endTs,total);
}
report.setSort(sort++);
}
total.setOee(total.getOee().divide(BigDecimal.valueOf(result.size()),4,RoundingMode.UP));
result.add(total);
result.sort(Comparator.comparing(PVReport::getSort));
return new Result<List<PVReport>>().ok(result);
}
/**
* 按月份统计报表
* @param report
*/
private void getDataWithYear(PVReport report,Long startTs,Long endTs,PVReport total){
//间隔年份
Integer yearsPassed = DateTimeUtils.yearsPassed(report.getBuildDate());
//日照时常
BigDecimal hour = report.getSunshine();
BigDecimal theoryPowerGeneration = CalculationUtil.theoryPowerGeneration(report.getCapacity(),hour,report.getAttenuation(),yearsPassed);
report.setTheoryEnergyPhotovoltaic(theoryPowerGeneration);
List<TsKvDTO> tsKvDTOS = tskvService.findTsKvByCodeAndAttrs(report.getPlantId().toString(),List.of("A29yy","A30yy"),startTs,endTs,false);
Map<String,List<TsKvDTO>> map = tsKvDTOS.stream()
.collect(Collectors.groupingBy(TsKvDTO::getAttrKey));
BigDecimal a29yy = BigDecimal.ZERO;
BigDecimal a30yy = BigDecimal.ZERO;
for (Map.Entry<String, List<TsKvDTO>> entry : map.entrySet()) {
String key = entry.getKey();
List<TsKvDTO> val = entry.getValue();
if (key.equals("A29yy")) {
a29yy = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
} else if (key.equals("A30yy")) {
a30yy = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
}
}
report.setInternetUsage(a30yy.setScale(4,RoundingMode.UP));
report.setEnergyPhotovoltaic(a29yy.setScale(4,RoundingMode.UP));
report.setConsumption(a29yy.subtract(a30yy).setScale(4,RoundingMode.UP));
try {
report.setOee(a29yy.divide(report.getTheoryEnergyPhotovoltaic(),4,RoundingMode.UP).multiply(new BigDecimal(100)));
} catch (Exception e) {
report.setOee(BigDecimal.ZERO);
}
report.setCo2(a29yy.multiply(BigDecimal.valueOf(0.475)).setScale(4,RoundingMode.UP));
total.setEnergyPhotovoltaic(total.getEnergyPhotovoltaic().add(report.getEnergyPhotovoltaic()).setScale(4,RoundingMode.UP));
total.setCapacity(total.getCapacity().add(report.getCapacity()).setScale(4,RoundingMode.UP));
total.setOee(total.getOee().add(report.getOee()).setScale(4,RoundingMode.UP));
total.setConsumption(total.getConsumption().add(report.getConsumption()).setScale(4,RoundingMode.UP));
total.setInternetUsage(total.getInternetUsage().add(report.getInternetUsage()).setScale( 4,RoundingMode.UP));
total.setCo2(total.getCo2().add(report.getCo2()).setScale(4,RoundingMode.UP));
total.setTheoryEnergyPhotovoltaic(total.getTheoryEnergyPhotovoltaic().add(report.getTheoryEnergyPhotovoltaic()).setScale(4,RoundingMode.UP));
}
/**
* 按月份统计报表
* @param report
*/
private void getDataWithMonth(PVReport report,Long startTs,Long endTs,PVReport total){
//间隔年份
Integer yearsPassed = DateTimeUtils.yearsPassed(report.getBuildDate());
//日照时常
BigDecimal hour = report.getSunshine().divide(BigDecimal.valueOf(12),4,RoundingMode.UP);
BigDecimal theoryPowerGeneration = CalculationUtil.theoryPowerGeneration(report.getCapacity(),hour,report.getAttenuation(),yearsPassed);
report.setTheoryEnergyPhotovoltaic(theoryPowerGeneration);
List<TsKvDTO> tsKvDTOS = tskvService.findTsKvByCodeAndAttrs(report.getPlantId().toString(),List.of("A29mm","A30mm"),startTs,endTs,false);
Map<String,List<TsKvDTO>> map = tsKvDTOS.stream()
.collect(Collectors.groupingBy(TsKvDTO::getAttrKey));
BigDecimal a29mm = BigDecimal.ZERO; // 初始化a29yy
BigDecimal a30mm = BigDecimal.ZERO; // 初始化a16
for (Map.Entry<String, List<TsKvDTO>> entry : map.entrySet()) {
String key = entry.getKey();
List<TsKvDTO> val = entry.getValue();
if (key.equals("A29mm")) {
a29mm = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
} else if (key.equals("A30mm")) {
a30mm = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
}
}
report.setInternetUsage(a30mm.setScale(4,RoundingMode.UP));
report.setEnergyPhotovoltaic(a29mm.setScale(4,RoundingMode.UP));
report.setConsumption(a29mm.subtract(a30mm).setScale(4,RoundingMode.UP));
try {
report.setOee(a29mm.divide(report.getTheoryEnergyPhotovoltaic(),4,RoundingMode.UP).multiply(new BigDecimal(100)));
} catch (Exception e) {
report.setOee(BigDecimal.ZERO);
}
report.setCo2(a29mm.multiply(BigDecimal.valueOf(0.475)).setScale(4,RoundingMode.UP));
total.setEnergyPhotovoltaic(total.getEnergyPhotovoltaic().add(report.getEnergyPhotovoltaic()).setScale(4,RoundingMode.UP));
total.setCapacity(total.getCapacity().add(report.getCapacity()).setScale(4,RoundingMode.UP));
total.setOee(total.getOee().add(report.getOee()).setScale(4,RoundingMode.UP));
total.setConsumption(total.getConsumption().add(report.getConsumption()).setScale(4,RoundingMode.UP));
total.setInternetUsage(total.getInternetUsage().add(report.getInternetUsage()).setScale(4,RoundingMode.UP));
total.setCo2(total.getCo2().add(report.getCo2()).setScale(4,RoundingMode.UP));
total.setTheoryEnergyPhotovoltaic(total.getTheoryEnergyPhotovoltaic().add(report.getTheoryEnergyPhotovoltaic()).setScale(4,RoundingMode.UP));
}
/**
* 本年所有光伏项目总发电量
* @return
*/
private BigDecimal nowTotalA29yy(){
List<PlantEntity> list = plantService.list();
List<String> entityCodes = list.stream().map(PlantEntity::getPlantId).map(String::valueOf).toList();
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodesAndAttrs(entityCodes,List.of("A29yy"),false);
return tsKvDTOS.stream()
.map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 光伏项目所有历史发电量总合
* @return
*/
private BigDecimal AllTotalA29yy(){
List<PlantEntity> list = plantService.list();
List<String> entityCodes = list.stream().map(PlantEntity::getPlantId).map(String::valueOf).toList();
List<TsKvDTO> tsKvDTOS = tskvService.findTsKvByCodesAndAttrs(entityCodes,List.of("A29yy"),1701360000000L,System.currentTimeMillis(),false);
return tsKvDTOS.stream()
.map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* 区统计
* @param dtos
*/
private void getAttrDataWithArea(List<PlantDTO> dtos,List<ScreenData> result){
dtos.forEach(temp->{
ScreenData screenData = new ScreenData();
List<ScreenData.AttrData> data = new ArrayList<>();
screenData.setName(temp.getPlantName());
screenData.setLon(temp.getLongitude());
screenData.setLat(temp.getLatitude());
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodeAndAttrs(temp.getPlantId().toString(),List.of("A29yy","A16"),false);
Map<String,List<TsKvDTO>> map = tsKvDTOS.stream()
.collect(Collectors.groupingBy(TsKvDTO::getAttrKey));
BigDecimal a29yy = BigDecimal.ZERO; // 初始化a29yy
BigDecimal a16 = BigDecimal.ZERO; // 初始化a16
for (Map.Entry<String, List<TsKvDTO>> entry : map.entrySet()) {
String key = entry.getKey();
List<TsKvDTO> val = entry.getValue();
if (key.equals("A29yy")) {
a29yy = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
try {
a29yy = a29yy.divide(BigDecimal.valueOf(10000), 4,RoundingMode.UP);
} catch (Exception e) {
a29yy=BigDecimal.ZERO;
}
} else if (key.equals("A16")) {
a16 = val.stream().findFirst().map(dto -> new BigDecimal(dto.getVal())).orElse(BigDecimal.ZERO);
try {
a16 = a16.divide(BigDecimal.valueOf(1000L), 4,RoundingMode.UP);
} catch (Exception e) {
a16= BigDecimal.ZERO;
}
}
}
//装机容量
BigDecimal capacity = temp.getCapacity();
ScreenData.AttrData capacityData = new ScreenData.AttrData();
capacityData.setAttrName("装机容量");
capacityData.setAttrValue(String.valueOf(capacity));
capacityData.setAttrUnit("kWp");
data.add(capacityData);
ScreenData.AttrData a29yyData = new ScreenData.AttrData();
a29yyData.setAttrName("年发电量");
a29yyData.setAttrValue(a29yy.toString());
a29yyData.setAttrUnit("万kWh");
data.add(a29yyData);
ScreenData.AttrData a16Data = new ScreenData.AttrData();
a16Data.setAttrName("发电功率");
a16Data.setAttrValue(a16.toString());
a16Data.setAttrUnit("KW");
data.add(a16Data);
ScreenData.AttrData cop = new ScreenData.AttrData();
cop.setAttrName("性能比");
try {
cop.setAttrValue(String.valueOf(a16.divide(capacity,RoundingMode.UP).multiply(BigDecimal.valueOf(100))));
} catch (Exception e) {
cop.setAttrValue(BigDecimal.ZERO.toString());
}
cop.setAttrUnit("%");
data.add(cop);
screenData.setData(data);
result.add(screenData);
});
}
/**
* 统计
* @param dtos
* @param screenData
*/
private void getAttrDataWithCity(List<PlantDTO> dtos,ScreenData screenData){
List<ScreenData.AttrData> data = new ArrayList<>();
BigDecimal totalCapacity = dtos.stream()
.map(PlantDTO::getCapacity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
List<String> thingCodes = dtos.stream()
.map(dto -> String.valueOf(dto.getPlantId()))
.toList();
List<String> attrCode = List.of("A29yy");
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodesAndAttrs(thingCodes,attrCode,false);
BigDecimal sumA29yy = tsKvDTOS.stream()
.map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
try {
sumA29yy.divide(BigDecimal.valueOf(10000));
} catch (Exception e) {
sumA29yy=BigDecimal.ZERO;
}
ScreenData.AttrData numData = new ScreenData.AttrData();
numData.setAttrName("站点数量");
numData.setAttrValue(String.valueOf(dtos.size()));
numData.setAttrUnit("个");
data.add(numData);
ScreenData.AttrData zjrl = new ScreenData.AttrData();
zjrl.setAttrName("装机容量");
zjrl.setAttrValue(String.valueOf(totalCapacity));
zjrl.setAttrUnit("kWp");
data.add(zjrl);
ScreenData.AttrData sum = new ScreenData.AttrData();
sum.setAttrName("年发电量");
sum.setAttrValue(String.valueOf(sumA29yy));
sum.setAttrUnit("万kWh");
data.add(sum);
screenData.setData(data);
}
/**
* 按指定时间范围生成全量空数据
* @param timeRange 时间范围
* @param attrType 属性类型
* @return 空数据列表
*/
private List<EnergyTimeLabelData> generateEmptyData(
List<LocalDateTime> timeRange, String attrType) {
return timeRange.stream()
.map(
t ->
new EnergyTimeLabelData(
DateTimeUtils.parse(t),
EnergyTimeLabelData.getByAttrType(attrType),
null))
.collect(Collectors.toList());
}
@SuppressWarnings("Duplicates")
public LocalDateTime getBeginTime(String dateType,String dateStr) {
AttributeTypeEnum attributeTypeEnum = AttributeTypeEnum.match(dateType);
switch (attributeTypeEnum) {
case am, hh -> {
// yyyy-MM-dd
return DateTimeUtils.parseDateTime(dateStr + " 00:00:00");
}
case dd -> {
// yyyy-MM
return DateTimeUtils.parseDateTime(dateStr + "-01 00:00:00");
}
case mm -> {
// yyyy
return DateTimeUtils.parseDateTime(dateStr + "-01-01 00:00:00");
}
default -> {
}
}
return null;
}
}

557
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/ManageChargeServiceImpl.java

@ -0,0 +1,557 @@
package com.thing.qingyuan.manageboard.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.thing.carbon.energyrepory.dto.EnergyTimeLabelData;
import com.thing.qingyuan.chargeStation.config.StationProperties;
import com.thing.qingyuan.chargeStation.dto.ConnectorStatusInfo;
import com.thing.qingyuan.chargeStation.dto.StationInfoDTO;
import com.thing.qingyuan.chargeStation.entity.StationInfoEntity;
import com.thing.qingyuan.chargeStation.mapper.ConnectorInfoMapper;
import com.thing.qingyuan.chargeStation.service.StationInfoService;
import com.thing.qingyuan.manageboard.dto.*;
import com.thing.qingyuan.manageboard.service.ManageChargeService;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.enumeration.AttributeTypeEnum;
import com.thing.common.core.utils.ConvertUtils;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.core.web.response.Result;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.thing.dict.dto.IotThingDictDTO;
import com.thing.thing.dict.service.IotThingDictService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ManageChargeServiceImpl implements ManageChargeService {
private final TsKvService tskvService;
private final IotThingDictService iotThingDictService;
private final StationInfoService stationInfoService;
private final ConnectorInfoMapper connectorInfoMapper;
private final StationProperties stationProperties;
@Override
public Result<List<ScreenData>> mapInfoByNameAndType(MapParam mapParam) {
List<ScreenData> result = new ArrayList<>();
Map<String,List<StationInfoDTO>> infoList = stationInfoService.findByParam(mapParam);
if(mapParam.getType().equals("3")||mapParam.getType().equals("4")){
//全市的话按个统计
List<StationInfoDTO> dtos =infoList.values().stream()
.flatMap(List::stream)
.toList();
this.getAttrDataWithArea(dtos,result);
}else {
infoList.forEach((key, value) -> {
ScreenData screenData = new ScreenData();
screenData.setName(key);
this.getAttrDataWithCity(value,screenData);
result.add(screenData);
});
}
return new Result<List<ScreenData>>().ok(result);
}
@Override
public Result<ChargeTotalInfo> totalInfo() {
ChargeTotalInfo result = new ChargeTotalInfo();
List<StationInfoEntity> dtos = stationInfoService.list();
List<String> stationIds = dtos.stream()
.map(dto -> String.valueOf(dto.getStationId()))
.toList();
Integer connectorCount = connectorInfoMapper.getCountByStationIds(stationIds);
result.setStationCount(dtos.size());
result.setConnectorCount(connectorCount);
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodesAndAttrs(stationIds, List.of("A29yy", "A204yy"), false);
Map<String, List<TsKvDTO>> map = tsKvDTOS.stream()
.collect(Collectors.groupingBy(TsKvDTO::getAttrKey));
BigDecimal a29yy = sumValuesForKey(map, "A29yy");
BigDecimal a204yy = sumValuesForKey(map, "A204yy");
result.setYearCharge(a29yy);
result.setYearMoney(a204yy);
return new Result<ChargeTotalInfo>().ok(result);
}
/**
* 根据key的值 获取对应的属性合
* @param map
* @param key
* @return
*/
private BigDecimal sumValuesForKey(Map<String, List<TsKvDTO>> map, String key) {
return map.getOrDefault(key, List.of()).stream()
.map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(4, RoundingMode.UP);
}
@Override
public Result<List<SiteTypeInfo>> siteTypeInfo() {
List<StationInfoEntity> dtos = stationInfoService.list();
Map<Integer, List<StationInfoEntity>> map = dtos.stream()
.collect(Collectors.groupingBy(StationInfoEntity::getStationType));
BigDecimal totalA29 = BigDecimal.ZERO;
List<SiteTypeInfo> result = new ArrayList<>();
for (Map.Entry<Integer, List<StationInfoEntity>> entry : map.entrySet()) {
Integer key = entry.getKey();
List<StationInfoEntity> val = entry.getValue();
List<String> stationIds = val.stream()
.map(dto -> String.valueOf(dto.getStationId()))
.toList();
List<TsKvDTO> tsKvDTOS = tskvService.findLatestByCodesAndAttrs(stationIds, List.of("A29yy"), false);
BigDecimal a29yy = tsKvDTOS.stream()
.map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal yearPower = a29yy.divide(BigDecimal.valueOf(100), 4, RoundingMode.UP);
String name = Constant.CARTYPES.get(key);
SiteTypeInfo info = new SiteTypeInfo(name, key.toString(), yearPower, BigDecimal.ZERO);
result.add(info);
totalA29 = totalA29.add(yearPower);
}
// 计算比例
if (totalA29.compareTo(BigDecimal.ZERO) > 0) {
for (SiteTypeInfo siteTypeInfo : result) {
BigDecimal proportion = siteTypeInfo.getYearCharge().divide(totalA29, 4, RoundingMode.UP);
siteTypeInfo.setProportion(proportion.multiply(new BigDecimal("100")));
}
}
// 补全没有数据的类型
List<SiteTypeInfo> finalResult = Constant.CARTYPES.entrySet().stream()
.map(entry -> result.stream()
.filter(r -> r.getSiteTypeCode().equals(entry.getKey().toString()))
.findFirst()
.orElse(new SiteTypeInfo(entry.getValue(), entry.getKey().toString(), BigDecimal.ZERO, BigDecimal.ZERO)))
.collect(Collectors.toList());
return new Result<List<SiteTypeInfo>>().ok(finalResult);
}
@Override
public Result<List<ChargingGunState>> chargingGunState() {
List<ChargingGunState> result = new ArrayList<>();
List<StationInfoEntity> dtos = stationInfoService.list();
List<String> stationIds = dtos.stream().map(dto -> String.valueOf(dto.getStationId())).toList();
List<ConnectorStatusInfo> statusInfos = connectorInfoMapper.getStatusByStationIds(stationIds);
Map<String, Integer> map = statusInfos.stream()
.collect(Collectors.toMap(ConnectorStatusInfo::getStatus, ConnectorStatusInfo::getNum, (a, b) -> b));
for (Map.Entry<String, String> entry : Constant.STATUS_MAP.entrySet()) {
String key = entry.getKey();
String val= entry.getValue();
Integer count = map.get(key);
if(ObjectUtil.isNotEmpty(count)){
result.add(new ChargingGunState(val,key,count));
}else {
result.add(new ChargingGunState(val,key,0));
}
}
return new Result<List<ChargingGunState>>().ok(result);
}
@Override
public Result<List<StationInfoReq>> stationInfo(FindParam param) {
List<StationInfoDTO> dtos = stationInfoService.findByName(param.getPlantName(),null);
List<StationInfoReq> reqs = new ArrayList<>();
dtos.forEach(temp->{
StationInfoReq req = new StationInfoReq();
req.setStationName(temp.getStationName());
List<TsKvDTO> tsKvDTOS =tskvService.findLatestByCodeAndAttrs(temp.getStationId(),List.of("A29dd","A29yy","A201yy","A202yy"),false);
Map<String, BigDecimal> sumMap = new HashMap<>();
for (TsKvDTO dto : tsKvDTOS) {
String key = dto.getAttrKey();
BigDecimal val = new BigDecimal(dto.getVal());
sumMap.put(key, sumMap.getOrDefault(key, BigDecimal.ZERO).add(val));
}
BigDecimal a29dd = sumMap.getOrDefault("A29dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
// 年度数据单位换算
BigDecimal a29yy = sumMap.getOrDefault("A29yy", BigDecimal.ZERO).divide(BigDecimal.valueOf(1000), 4, RoundingMode.UP);
BigDecimal a201yy = sumMap.getOrDefault("A201yy", BigDecimal.ZERO).divide(BigDecimal.valueOf(1000), 4, RoundingMode.UP);
BigDecimal a202yy = sumMap.getOrDefault("A202yy", BigDecimal.ZERO).divide(BigDecimal.valueOf(1000), 4, RoundingMode.UP);
req.setDayCharge(a29dd);
req.setYearCharge(a29yy);
req.setYearOften(a201yy);
req.setYearChargeCount(a202yy);
reqs.add(req);
});
return new Result<List<StationInfoReq>>().ok(reqs);
}
@Override
public Result<DataReq> findListByAttrCode(GunDataParam dataParam) {
DataReq req = new DataReq();
Long startTime;
Long endTime;
if(ObjectUtil.isNotEmpty(dataParam.getStartTime())&&ObjectUtil.isNotEmpty(dataParam.getEndTime())&&dataParam.getStartTime()!=0){
startTime = dataParam.getStartTime();
endTime = dataParam.getEndTime();
}else {
if(dataParam.getAttrType().equals("dd")){
startTime= DateTimeUtils.getMonthBeginTimestamp(System.currentTimeMillis());
}else {
startTime = DateTimeUtils.getYearBeginTimestamp(System.currentTimeMillis());
}
endTime = DateTimeUtils.getMonthEndTimestamp(System.currentTimeMillis());
}
AttributeTypeEnum attributeTypeEnum = AttributeTypeEnum.match(dataParam.getAttrType());
Instant instant = Instant.ofEpochMilli(startTime);
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
List<LocalDateTime> timeRange = attributeTypeEnum.getTimeRange(dateTime);
List<EnergyTimeLabelData> energyTimeLabelData = this.generateEmptyData(timeRange, dataParam.getAttrType());
List<TsKvDTO> tskvs = new ArrayList<>();
List<StationInfoEntity> dtos = stationInfoService.list();
List<String> entityCodes = dtos.stream().map(StationInfoEntity::getStationId).map(String::valueOf).toList();
tskvs = tskvService.findTsKvByCodesAndAttrs(entityCodes,List.of(dataParam.getAttrCode()),startTime,endTime,false);
Map<Long,List<TsKvDTO>> tsMap = tskvs.stream()
.collect(Collectors.groupingBy(TsKvDTO::getTs));
List<TsKvDTO> allInfo = new ArrayList<>();
energyTimeLabelData.forEach(temp->{
if(ObjectUtil.isNotEmpty(tsMap.get(temp.getTs()))){
BigDecimal val = tsMap.get(temp.getTs()).stream().map(dto -> new BigDecimal(dto.getVal()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
String value = dataUnitConvert(dataParam.getAttrCode(), val).toPlainString();
TsKvDTO tskv = new TsKvDTO("all",dataParam.getAttrCode(),temp.getTs(),value);
allInfo.add(tskv);
}else {
TsKvDTO tskv = new TsKvDTO("all",dataParam.getAttrCode(),temp.getTs(),BigDecimal.ZERO.toString());
allInfo.add(tskv);
}
});
req.setTskvs(allInfo);
DataReq.AttrInfo attrInfo = new DataReq.AttrInfo();
IotThingDictDTO dictDTO = iotThingDictService.findDictByCode(dataParam.getAttrCode());
if(ObjectUtil.isNotEmpty(dictDTO)){
attrInfo.setAttrCode(dictDTO.getCode());
attrInfo.setAttrName(dictDTO.getName());
attrInfo.setAttrUint(dictDTO.getUnit());
req.setAttrInfo(attrInfo);
}
return new Result<DataReq>().ok(req);
}
private BigDecimal dataUnitConvert(String attrCode, BigDecimal value) {
if (attrCode.startsWith("A201")) {
return value.divide(BigDecimal.valueOf(60 * 60 * 1000), 4, RoundingMode.HALF_UP);
}
if (attrCode.equals("A29mm")) {
return value.divide(BigDecimal.valueOf(1000), 4, RoundingMode.HALF_UP);
}
return value;
}
@Override
public Result<List<YOYDataReq>> findYOYList(GunDataParam dataParam) {
List<YOYDataReq> result = new ArrayList<>();
DataReq nowYearList = this.findListByAttrCode(dataParam).getData();
dataParam.setStartTime(DateTimeUtils.fistDayOfLastYear());
dataParam.setEndTime(DateTimeUtils.lastDayOfLastYear());
DataReq lastYearList = this.findListByAttrCode(dataParam).getData();
List<TsKvDTO> last = lastYearList.getTskvs();
Map<Integer, List<TsKvDTO>> groupedMap = last.stream()
.collect(Collectors.groupingBy(dto -> Instant.ofEpochMilli(dto.getTs())
.atZone(ZoneId.systemDefault())
.toLocalDateTime()
.getMonth().getValue()));
nowYearList.getTskvs().forEach(temp->{
YOYDataReq req = new YOYDataReq();
LocalDate date = LocalDate.ofEpochDay(temp.getTs() / 86400000); // 将毫秒时间戳转换为 LocalDate 对象
Integer month = date.getMonthValue();
req.setTs(temp.getTs());
req.setAttrName(nowYearList.getAttrInfo().getAttrName());
req.setAttrCode(nowYearList.getAttrInfo().getAttrCode());
req.setUnit(nowYearList.getAttrInfo().getAttrUint());
List<TsKvDTO> tsKvDTOS = groupedMap.get(month);
if(ObjectUtil.isNotEmpty(tsKvDTOS)){
req.setLastYearVal(new BigDecimal(tsKvDTOS.stream().findFirst().get().getVal()));
}
req.setNowYearVal(new BigDecimal(temp.getVal()));
result.add(req);
});
return new Result<List<YOYDataReq>>().ok(result);
}
@Override
public Result<List<StationInfoReq>> gunReport(PVParam param) {
List<StationInfoDTO> reqs = stationInfoService.findByName(param.getPlantName(),param.getArea());
reqs.forEach(r->{
r.setOperatorName(stationProperties.getOperatorNameById(r.getOperatorId()));
});
List<StationInfoReq> result = ConvertUtils.sourceToTarget(reqs,StationInfoReq.class);
LocalDateTime startTime = getBeginTime(param.getDateType(),param.getDate());
Instant instant = startTime.atZone(ZoneId.systemDefault()).toInstant();
long startTs = instant.toEpochMilli();
long endTs = startTs+1000L;
StationInfoReq total = new StationInfoReq();
total.setStationName("合计");
total.setArea("--");
total.setSort(-1);
int sort = 1;
for (StationInfoReq report : result) {
//充电枪数量
int count = connectorInfoMapper.getCountByStationIds(List.of(report.getStationId()));
report.setGunCount(count);
if(param.getDateType().equals("dd")){
getDataWithMonth(report,startTs,endTs,total);
}else {
getDataWithYear(report,startTs,endTs,total);
}
report.setSort(sort++);
}
try {
total.setGunCharge(total.getYearCharge().divide(BigDecimal.valueOf(total.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
total.setGunCharge(BigDecimal.ZERO);
}
try {
total.setGunOften(total.getYearChargeCount().divide(BigDecimal.valueOf(total.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
total.setGunOften(BigDecimal.ZERO);
}
try {
total.setGunChargeCount(total.getYearOften().divide(BigDecimal.valueOf(total.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
total.setGunCharge(BigDecimal.ZERO);
}
result.add(total);
result.sort(Comparator.comparing(StationInfoReq::getSort));
return new Result<List<StationInfoReq>>().ok(result);
}
private void getDataWithYear(StationInfoReq report, long startTs, long endTs, StationInfoReq total) {
List<TsKvDTO> tsKvDTOS =tskvService.findTsKvByCodeAndAttrs(report.getStationId(),List.of("A29yy","A201yy","A202yy"),startTs,endTs,false);
Map<String, BigDecimal> sumMap = new HashMap<>();
for (TsKvDTO dto : tsKvDTOS) {
String key = dto.getAttrKey();
BigDecimal val = new BigDecimal(dto.getVal());
sumMap.put(key, sumMap.getOrDefault(key, BigDecimal.ZERO).add(val));
}
BigDecimal a29yy = sumMap.getOrDefault("A29yy", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a201yy = sumMap.getOrDefault("A201yy", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a202yy = sumMap.getOrDefault("A202yy", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a201hh = BigDecimal.ZERO;
try {
a201hh = a201yy.divide(BigDecimal.valueOf(60 * 60 * 1000), 1, RoundingMode.HALF_UP);
} catch (Exception e) {
}
report.setYearCharge(a29yy);
report.setYearOften(a201hh);
report.setYearChargeCount(a202yy);
try {
report.setGunCharge(a29yy.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunCharge(BigDecimal.ZERO);
}
try {
report.setGunOften(a202yy.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunOften(BigDecimal.ZERO);
}
try {
report.setGunChargeCount(a201hh.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunCharge(BigDecimal.ZERO);
}
total.setYearOften(total.getYearOften().add(report.getYearOften()));
total.setYearOften(total.getYearOften().add(report.getYearOften()));
total.setYearChargeCount(total.getYearChargeCount().add(report.getYearChargeCount()));
total.setGunCount(total.getGunCount()+report.getGunCount());
}
/**
* 按月份统计报表
* @param report
*/
private void getDataWithMonth(StationInfoReq report,Long startTs,Long endTs,StationInfoReq total){
List<TsKvDTO> tsKvDTOS =tskvService.findTsKvByCodeAndAttrs(report.getStationId(),List.of("A29mm","A201mm","A202mm"),startTs,endTs,false);
Map<String, BigDecimal> sumMap = new HashMap<>();
for (TsKvDTO dto : tsKvDTOS) {
String key = dto.getAttrKey();
BigDecimal val = new BigDecimal(dto.getVal());
sumMap.put(key, sumMap.getOrDefault(key, BigDecimal.ZERO).add(val));
}
BigDecimal a29mm = sumMap.getOrDefault("A29mm", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a201mm = sumMap.getOrDefault("A201mm", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a202mm = sumMap.getOrDefault("A202mm", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
report.setYearCharge(a29mm);
report.setYearChargeCount(a202mm);
BigDecimal a201hh = BigDecimal.ZERO;
try {
a201hh = a201mm.divide(BigDecimal.valueOf(60 * 60 * 1000), 1, RoundingMode.HALF_UP);
} catch (Exception e) {
}
report.setYearOften(a201hh);
try {
report.setGunCharge(a29mm.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunCharge(BigDecimal.ZERO);
}
try {
report.setGunOften(a202mm.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunOften(BigDecimal.ZERO);
}
try {
report.setGunChargeCount(a201hh.divide(BigDecimal.valueOf(report.getGunCount()),4,RoundingMode.UP));
} catch (Exception e) {
report.setGunCharge(BigDecimal.ZERO);
}
total.setYearCharge(total.getYearCharge().add(report.getYearCharge()));
total.setYearOften(total.getYearOften().add(report.getYearOften()));
total.setYearChargeCount(total.getYearChargeCount().add(report.getYearChargeCount()));
total.setGunCount(total.getGunCount()+report.getGunCount());
}
/**
* 区域统计
* @param dtos
* @param result
*/
private void getAttrDataWithArea(List<StationInfoDTO> dtos, List<ScreenData> result) {
dtos.forEach(temp->{
ScreenData screenData = new ScreenData();
List<ScreenData.AttrData> data = new ArrayList<>();
screenData.setName(temp.getStationName());
screenData.setLon(temp.getStationLng());
screenData.setLat(temp.getStationLat());
List<ConnectorStatusInfo> list = connectorInfoMapper.getStatusByStationId(temp.getStationId());
int sum = list.stream()
.mapToInt(ConnectorStatusInfo::getNum)
.sum();
int num = list. stream()
.filter(info -> info.getStatus().equals("3"))
.mapToInt(ConnectorStatusInfo::getNum)
.findFirst()
.orElse(0);
data.add(initAttrData("充电枪数量",sum,"个"));
data.add(initAttrData("正在充电",num,"个"));
List<TsKvDTO> tsKvDTOS =tskvService.findLatestByCodeAndAttrs(temp.getStationId(),List.of("A29dd","A201dd","A202dd"),false);
Map<String, BigDecimal> sumMap = new HashMap<>();
for (TsKvDTO dto : tsKvDTOS) {
String key = dto.getAttrKey();
BigDecimal val = new BigDecimal(dto.getVal());
sumMap.put(key, sumMap.getOrDefault(key, BigDecimal.ZERO).add(val));
}
BigDecimal a29dd = sumMap.getOrDefault("A29dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a201dd = sumMap.getOrDefault("A201dd", BigDecimal.ZERO).divide(BigDecimal.valueOf(3600),4,RoundingMode.UP);
BigDecimal a202dd = sumMap.getOrDefault("A202dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
data.add(initAttrData("今日充电量",a29dd,"kWh"));
data.add(initAttrData("今日充电时长",a201dd,"h"));
data.add(initAttrData("今日充电次数",a202dd,"次"));
screenData.setData(data);
result.add(screenData);
});
}
/**
* 省市统计
* @param screenData
*/
private void getAttrDataWithCity(List<StationInfoDTO> dtos, ScreenData screenData) {
List<ScreenData.AttrData> data = new ArrayList<>();
List<String> thingCodes = dtos.stream()
.map(dto -> String.valueOf(dto.getStationId()))
.toList();
int totalNum=0;
int runNum=0;
for (StationInfoDTO dto : dtos) {
List<ConnectorStatusInfo> list = connectorInfoMapper.getStatusByStationId(dto.getStationId());
int num = list. stream()
.filter(info -> info.getStatus().equals("3"))
.mapToInt(ConnectorStatusInfo::getNum)
.findFirst()
.orElse(0);
runNum=runNum+num;
int sum = list.stream()
.mapToInt(ConnectorStatusInfo::getNum)
.sum();
totalNum = totalNum+sum;
}
data.add(initAttrData("充电枪数量",totalNum,"个"));
data.add(initAttrData("正在充电",runNum,"个"));
List<TsKvDTO> tsKvDTOS =tskvService.findLatestByCodesAndAttrs(thingCodes,List.of("A29dd","A201dd","A202dd"),false);
Map<String, BigDecimal> sumMap = new HashMap<>();
for (TsKvDTO dto : tsKvDTOS) {
String key = dto.getAttrKey();
BigDecimal val = new BigDecimal(dto.getVal());
sumMap.put(key, sumMap.getOrDefault(key, BigDecimal.ZERO).add(val));
}
BigDecimal a29dd = sumMap.getOrDefault("A29dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a201dd = sumMap.getOrDefault("A201dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
BigDecimal a202dd = sumMap.getOrDefault("A202dd", BigDecimal.ZERO).setScale(4, RoundingMode.UP);
data.add(initAttrData("今日充电量",a29dd,"kWh"));
data.add(initAttrData("今日充电时长",a201dd,"h"));
data.add(initAttrData("今日充电次数",a202dd,"次"));
screenData.setData(data);
}
private ScreenData.AttrData initAttrData(String name,Object val,String unit){
ScreenData.AttrData attrData = new ScreenData.AttrData();
attrData.setAttrName(name);
attrData.setAttrValue(val.toString());
attrData.setAttrUnit(unit);
return attrData;
}
/**
* 按指定时间范围生成全量空数据
* @param timeRange 时间范围
* @param attrType 属性类型
* @return 空数据列表
*/
private List<EnergyTimeLabelData> generateEmptyData(
List<LocalDateTime> timeRange, String attrType) {
return timeRange.stream()
.map(
t ->
new EnergyTimeLabelData(
DateTimeUtils.parse(t),
EnergyTimeLabelData.getByAttrType(attrType),
null))
.collect(Collectors.toList());
}
@SuppressWarnings("Duplicates")
public LocalDateTime getBeginTime(String dateType,String dateStr) {
AttributeTypeEnum attributeTypeEnum = AttributeTypeEnum.match(dateType);
switch (attributeTypeEnum) {
case am, hh -> {
// yyyy-MM-dd
return DateTimeUtils.parseDateTime(dateStr + " 00:00:00");
}
case dd -> {
// yyyy-MM
return DateTimeUtils.parseDateTime(dateStr + "-01 00:00:00");
}
case mm -> {
// yyyy
return DateTimeUtils.parseDateTime(dateStr + "-01-01 00:00:00");
}
default -> {
}
}
return null;
}
}

107
modules/qingyuan/src/main/java/com/thing/qingyuan/manageboard/service/impl/PlantServiceImpl.java

@ -0,0 +1,107 @@
package com.thing.qingyuan.manageboard.service.impl;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.qingyuan.manageboard.dto.MapParam;
import com.thing.qingyuan.manageboard.dto.PlantDTO;
import com.thing.qingyuan.manageboard.dto.PlantInfoReq;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.qingyuan.manageboard.mapper.PlantMapper;
import com.thing.qingyuan.manageboard.service.PlantService;
import com.thing.common.core.utils.ConvertUtils;
import com.thing.common.orm.service.impl.BaseServiceImpl;
import com.thing.sys.security.context.UserContext;
import com.thing.thing.entity.dto.IotThingEntityDTO;
import com.thing.thing.entity.service.IotThingEntityService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.mybatisflex.core.query.QueryMethods.column;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Service
@RequiredArgsConstructor
public class PlantServiceImpl extends BaseServiceImpl<PlantMapper, PlantEntity> implements PlantService {
@Autowired
IotThingEntityService iotThingEntityService;
@Override
public QueryWrapper getWrapper(Map<String, Object> params){
QueryWrapper wrapper = new QueryWrapper();
QueryColumn name= column("plant_name");
QueryColumn id = column("plant_id");
String buildDate = MapUtil.getStr(params,"buildDate");
String area = MapUtil.getStr(params,"area");
String key = MapUtil.getStr(params,"key");
Long idParam= null;
try {
idParam = Long.parseLong(key);
} catch (NumberFormatException ignored) {
}
wrapper.eq("build_date",buildDate,StringUtils.isNotEmpty(buildDate));
wrapper.like("area",area,StringUtils.isNotEmpty(area));
if(StringUtils.isNotEmpty(key)){
wrapper.and(name.like(key).or(id.eq(idParam)));
}
return wrapper;
}
@Override
public Map<String,List<PlantDTO>> findByParam(MapParam mapParam) {
QueryWrapper wrapper = new QueryWrapper();
if (mapParam.getType().equals("2")) {
wrapper.eq(PlantEntity::getProvince, mapParam.getCityName());
} else if (mapParam.getType().equals("3")) {
wrapper.eq(PlantEntity::getCity, mapParam.getCityName());
} else if (mapParam.getType().equals("4")) {
wrapper.eq(PlantEntity::getArea, mapParam.getCityName());
}
List<PlantDTO> dtos = ConvertUtils.sourceToTarget(this.list(wrapper), PlantDTO.class);
dtos.forEach(temp->{
Optional<IotThingEntityDTO> optional = iotThingEntityService.findEntityByCode(String.valueOf(temp.getPlantId()), UserContext.getRealTenantCode(), true);
if(optional.isPresent()){
temp.setPlantName(optional.get().getName());
}
});
if (mapParam.getType().equals("2") || mapParam.getType().equals("3") || mapParam.getType().equals("4")) {
return dtos.stream().collect(Collectors.groupingBy(PlantDTO::getCity));
} else {
return dtos.stream().collect(Collectors.groupingBy(PlantDTO::getProvince));
}
}
@Override
public List<PlantInfoReq> findByName(String plantName,String area) {
QueryWrapper wrapper = new QueryWrapper();
wrapper.like(PlantEntity::getPlantName,plantName,StringUtils.isNotEmpty(plantName));
wrapper.like(PlantEntity::getArea,area,StringUtils.isNotEmpty(area));
List<PlantEntity> entities = this.list(wrapper);
entities.forEach(temp->{
Optional<IotThingEntityDTO> optional = iotThingEntityService.findEntityByCode(String.valueOf(temp.getPlantId()), UserContext.getRealTenantCode(), true);
if(optional.isPresent()){
temp.setPlantName(optional.get().getName());
}
});
return ConvertUtils.sourceToTarget(entities,PlantInfoReq.class);
}
}

129
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/controller/PhotovoltaicController.java

@ -0,0 +1,129 @@
package com.thing.qingyuan.photovoltaic.controller;
import com.thing.common.core.annotation.LogOperation;
import com.thing.common.core.web.response.Result;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicOverviewDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicReportDTO;
import com.thing.qingyuan.photovoltaic.service.PhotovoltaicService;
import com.thing.qingyuan.screen.ScreenData;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@RestController
@RequestMapping("photovoltaic")
@Tag(name="光伏项目点位信息")
@RequiredArgsConstructor
public class PhotovoltaicController {
private final PhotovoltaicService photovoltaicService;
@GetMapping("overview")
@Operation(summary="获取光伏概览数据信息")
public Result<PhotovoltaicOverviewDTO> getOverview(){
PhotovoltaicOverviewDTO data = photovoltaicService.getOverview();
return new Result<PhotovoltaicOverviewDTO>().ok(data);
}
@GetMapping("{plantId}")
@Operation(summary="获取电站信息")
public Result<PhotovoltaicDTO> get(@PathVariable("plantId") Long plantId){
PhotovoltaicDTO data = photovoltaicService.findById(plantId);
return new Result<PhotovoltaicDTO>().ok(data);
}
@GetMapping("video/{plantId}")
@Operation(summary="获取视频信息")
public Result getVideo(@PathVariable("plantId") Long plantId){
PhotovoltaicDTO data = photovoltaicService.findById(plantId);
return new Result<PhotovoltaicDTO>().ok(data);
}
@GetMapping("heatMap")
@Operation(summary="获取热力图信息")
public Result<List<ScreenData>> getHeatMap(){
List<ScreenData> heatMap = photovoltaicService.getHeatMap();
return new Result<List<ScreenData>>().ok(heatMap);
}
@GetMapping("powerAnalysis/{plantId}/{type}")
@Operation(summary="发电分析")
public Result<Map<String,List<TsKvDTO>>> powerAnalysis(@PathVariable("plantId") Long plantId,@PathVariable("type") String type){
Map<String,List<TsKvDTO>> resultData = photovoltaicService.getPowerAnalysis(plantId,type);
return new Result<Map<String,List<TsKvDTO>>>().ok(resultData);
}
@GetMapping("electricPowerAnalysis/{plantId}/{type}")
@Operation(summary="发电消纳分析")
public Result<Map<String,List<TsKvDTO>>> electricPowerAnalysis(@PathVariable("plantId") Long plantId,@PathVariable("type") String type){
Map<String,List<TsKvDTO>> resultData = photovoltaicService.getElectricPowerAnalysis(plantId,type);
return new Result<Map<String,List<TsKvDTO>>>().ok(resultData);
}
@GetMapping("inverter/{code}")
@Operation(summary="逆变器详情")
public Result<Map<String,List<TsKvDTO>>> inverterDetails(@PathVariable String code){
Map<String,List<TsKvDTO>> resultData = photovoltaicService.getInverterDetails(code);
return new Result<Map<String,List<TsKvDTO>>>().ok(resultData);
}
@PostMapping("report/electric")
@Operation(summary="发电报表")
public Result<List<PhotovoltaicReportDTO>> reportElectric(@RequestBody ChargeStatisticRequest chargeStatisticRequest){
List<PhotovoltaicReportDTO> reportElectric = photovoltaicService.getReportElectric(chargeStatisticRequest);
return new Result<List<PhotovoltaicReportDTO>>().ok(reportElectric);
}
@PostMapping("report/electric/export")
@Operation(summary="发电报表导出")
@LogOperation("发电报表导出")
public void electricExport( @RequestBody ChargeStatisticRequest chargeStatisticRequest, HttpServletResponse response) throws Exception {
photovoltaicService.electricExport(chargeStatisticRequest, response);
}
@PostMapping("report/consumption")
@Operation(summary="上网消纳量报表")
public Result<List<PhotovoltaicReportDTO>> reportConsumption(@RequestBody ChargeStatisticRequest chargeStatisticRequest){
List<PhotovoltaicReportDTO> reportElectric = photovoltaicService.getReportConsumption(chargeStatisticRequest);
return new Result<List<PhotovoltaicReportDTO>>().ok(reportElectric);
}
@PostMapping("report/consumption/export")
@Operation(summary="上网消纳量报表导出")
@LogOperation("上网消纳量报表导出")
public void reportElectric(@RequestBody ChargeStatisticRequest chargeStatisticRequest,HttpServletResponse response){
photovoltaicService.consumptionExport(chargeStatisticRequest, response);
}
/* @GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始") ,
@Parameter(name = Constant.LIMIT, description = "每页显示记录数") ,
@Parameter(name = Constant.ORDER_FIELD, description = "排序字段") ,
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)"),
@Parameter(name = Constant.ORDER, description = "排序方式,可选值(asc、desc)")
})
public Result<PageData<PlantDTO>> page(@RequestParam Map<String, Object> params){
PageData<PlantDTO> page = photovoltaicService.getP(params, PlantDTO.class);
return new Result<PageData<PlantDTO>>().ok(page);
}*/
}

33
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicConsumptionDTO.java

@ -0,0 +1,33 @@
package com.thing.qingyuan.photovoltaic.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目概览数据信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "消纳报表数据信息")
public class PhotovoltaicConsumptionDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "发电量")
private BigDecimal electricityUsage = BigDecimal.ZERO;
@Schema(description = "消纳量")
private BigDecimal consumptionUsage = BigDecimal.ZERO;
@Schema(description = "上网量")
private BigDecimal internetUsage = BigDecimal.ZERO;
@Schema(description = "消纳率")
private BigDecimal consumptionRate = BigDecimal.ZERO;
@Schema(description = "时间")
private Long ts ;
}

45
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicDTO.java

@ -0,0 +1,45 @@
package com.thing.qingyuan.photovoltaic.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏项目点位信息")
public class PhotovoltaicDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "电站Id")
private Long plantId;
@Schema(description = "电站名称")
private String plantName;
@Schema(description = "电站装机容量 (单位:kWp)")
private BigDecimal capacity;
@Schema(description = "经度")
private Object longitude;
@Schema(description = "纬度")
private Object latitude;
@Schema(description = "逆变器数量")
private Integer inverterNum = 0;
@Schema(description = "今日发电量")
private BigDecimal electricityUsage = BigDecimal.ZERO;
@Schema(description = "今日上网量")
private BigDecimal internetUsage = BigDecimal.ZERO;
@Schema(description = "今日减碳量")
private BigDecimal carbonUsage = BigDecimal.ZERO;
@Schema(description = "检测点运行正常")
private BigDecimal pointNormal = BigDecimal.ZERO;
@Schema(description = "检测点运行总量")
private BigDecimal pointTotal = BigDecimal.ZERO;
}

36
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicOverviewDTO.java

@ -0,0 +1,36 @@
package com.thing.qingyuan.photovoltaic.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 光伏项目概览数据信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏项目概览数据信息")
public class PhotovoltaicOverviewDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "光伏数量")
private BigDecimal num = BigDecimal.ZERO;
@Schema(description = "电站装机容量 (单位:kWp)")
private BigDecimal capacity = BigDecimal.ZERO;
@Schema(description = "年发电量(单位:kWp)")
private BigDecimal electricityUsage = BigDecimal.ZERO;
@Schema(description = "年上网量(单位:kWp)")
private BigDecimal internetUsage = BigDecimal.ZERO;
@Schema(description = "年节能量(单位:tce)")
private BigDecimal energySaveUsage = BigDecimal.ZERO;
@Schema(description = "年减排量(单位:tCO2)")
private BigDecimal reductionUsage = BigDecimal.ZERO;
}

43
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/dto/PhotovoltaicReportDTO.java

@ -0,0 +1,43 @@
package com.thing.qingyuan.photovoltaic.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
* 光伏项目概览数据信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Data
@Schema( description= "光伏和消纳报表数据信息")
public class PhotovoltaicReportDTO implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "物的id")
private Long thingId;
@Schema(description = "结构编码")
private String code;
@Schema(description = "结构名称")
private String name;
@Schema(description = "发电总量 (单位:kwh)")
private BigDecimal electricityUsage = BigDecimal.ZERO;
@Schema(description = "光伏报表数据,key: ts,val ")
private List<Map<String,Object>> plantDataList;
@Schema(description = "消纳报表总量数据")
private PhotovoltaicConsumptionDTO consumptionTotal;
@Schema(description = "消纳报表数据")
private List<PhotovoltaicConsumptionDTO> consumptionDataList;
@Schema(description = "时间列表:暂时后端使用")
private List<Long> timeList;
}

45
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/service/PhotovoltaicService.java

@ -0,0 +1,45 @@
package com.thing.qingyuan.photovoltaic.service;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicOverviewDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicReportDTO;
import com.thing.qingyuan.screen.ScreenData;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
public interface PhotovoltaicService {
PhotovoltaicOverviewDTO getOverview();
PhotovoltaicDTO findById(Long plantId);
List<String> findVideoById(Long plantId);
List<ScreenData> getHeatMap();
Map<String,List<TsKvDTO>> getPowerAnalysis(Long plantId, String type);
Map<String,List<TsKvDTO>> getElectricPowerAnalysis(Long plantId, String type);
Map<String,List<TsKvDTO>> getInverterDetails(String code);
List<PhotovoltaicReportDTO> getReportElectric(ChargeStatisticRequest chargeStatisticRequest);
void electricExport(ChargeStatisticRequest chargeStatisticRequest, HttpServletResponse response);
List<PhotovoltaicReportDTO> getReportConsumption(ChargeStatisticRequest chargeStatisticRequest);
void consumptionExport(ChargeStatisticRequest chargeStatisticRequest, HttpServletResponse response);
}

776
modules/qingyuan/src/main/java/com/thing/qingyuan/photovoltaic/service/impl/PhotovoltaicServiceImpl.java

@ -0,0 +1,776 @@
package com.thing.qingyuan.photovoltaic.service.impl;
import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.util.ObjectUtil;
import com.google.common.collect.Lists;
import com.thing.common.core.enumeration.ThingAttrType;
import com.thing.common.core.enumeration.TimeType;
import com.thing.common.core.exception.SysException;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.core.utils.excel.ExcelUtils;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.qingyuan.basedevice.dto.DeviceDTO;
import com.thing.qingyuan.basedevice.service.IotDeviceService;
import com.thing.qingyuan.chargeStation.dto.ChargeStatisticRequest;
import com.thing.qingyuan.manageboard.entity.PlantEntity;
import com.thing.qingyuan.manageboard.service.PlantService;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicConsumptionDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicOverviewDTO;
import com.thing.qingyuan.photovoltaic.dto.PhotovoltaicReportDTO;
import com.thing.qingyuan.photovoltaic.service.PhotovoltaicService;
import com.thing.qingyuan.screen.ScreenData;
import com.thing.qingyuan.util.CalculationUtil;
import com.thing.sys.security.context.UserContext;
import com.thing.thing.entity.dto.IotThingEntityDTO;
import com.thing.thing.entity.entity.IotThingEntity;
import com.thing.thing.entity.service.IotThingEntityService;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* 光伏项目点位信息
*
* @author xc
* @since 3.0 2024-01-29
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PhotovoltaicServiceImpl implements PhotovoltaicService {
private final PlantService plantService;
private final IotThingEntityService thingEntityService;
private final TsKvService tsKvService;
private final IotDeviceService iotDeviceService;
private final static BigDecimal coefficient = BigDecimal.ONE.divide(BigDecimal.TEN.pow(3));
private final static BigDecimal reductionFactor = new BigDecimal("0.475");
private final static BigDecimal energySaveFactor = new BigDecimal("0.4");
private final static String attrA16 = "A16";
private final static String attrA29 = "A29";
private final static String attrA29dd = "A29dd";
private final static String attrA29mm = "A29mm";
private final static String attrA30 = "A30";
private final static String attrA30hh = "A30hh";
private final static String attrA30dd = "A30dd";
private final static String attrA30mm = "A30mm";
private final static String attrA30yy = "A30yy";
private final static String attrA29yy = "A29yy";
private final static Long ONE_DAY = 86400000L;
@Override
public PhotovoltaicOverviewDTO getOverview() {
PhotovoltaicOverviewDTO photovoltaicOverviewDTO = new PhotovoltaicOverviewDTO();
List<PlantEntity> list = plantService.list();
if (CollectionUtils.isNotEmpty(list)) {
photovoltaicOverviewDTO.setNum(new BigDecimal(CollectionUtils.size(list)));
BigDecimal capacity = list.stream().map(PlantEntity::getCapacity).reduce(BigDecimal.ZERO, BigDecimal::add);
photovoltaicOverviewDTO.setCapacity(capacity);
List<String> entityCodes = list.stream().map(PlantEntity::getPlantId).map(Object::toString).toList();
Optional<List<IotThingEntityDTO>> thingEntities = thingEntityService.findByCodes(entityCodes, UserContext.getRealTenantCode(), true);
if (thingEntities.isPresent()) {
List<TsKvDTO> tsKvDTOList = tsKvService.findLatestByCodesAndAttrs(thingEntities.get().stream().map(IotThingEntityDTO::getCode).toList(), Lists.newArrayList(attrA29yy, attrA30yy), false);
if (CollectionUtils.isNotEmpty(tsKvDTOList)) {
//年发电总量
BigDecimal electricityUsage = tsKvDTOList.stream().filter(s -> StringUtils.equals(s.getAttrKey(), attrA29yy)).map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal performance = CalculationUtil.getPerformance(electricityUsage, new BigDecimal(10000), 2);
photovoltaicOverviewDTO.setElectricityUsage(performance);
BigDecimal internetUsage = tsKvDTOList.stream().filter(s -> StringUtils.equals(s.getAttrKey(), attrA30yy)).map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
photovoltaicOverviewDTO.setInternetUsage(internetUsage);
//年节能量
BigDecimal energySaveUsage = CalculationUtil.getCarbonUsage(electricityUsage, energySaveFactor, coefficient, 2);
photovoltaicOverviewDTO.setEnergySaveUsage(energySaveUsage);
//年减排量
BigDecimal reductionUsage = CalculationUtil.getCarbonUsage(electricityUsage, reductionFactor, coefficient, 2);
photovoltaicOverviewDTO.setReductionUsage(reductionUsage);
}
}
}
return photovoltaicOverviewDTO;
}
@Override
public PhotovoltaicDTO findById(Long plantId) {
PhotovoltaicDTO photovoltaicDTO = plantService.getByIdAs(plantId, PhotovoltaicDTO.class);
if (ObjectUtil.isNull(photovoltaicDTO)) {
throw new SysException("电站信息不存在,请重新选择");
}
Optional<IotThingEntityDTO> entityByCode = thingEntityService.findEntityByCode(String.valueOf(photovoltaicDTO.getPlantId()), UserContext.getRealTenantCode(), true);
if (entityByCode.isEmpty()) {
throw new SysException("当前电站实体不存在,请重新选择");
}
List<DeviceDTO> deviceDTOS = iotDeviceService.findByPlantId(photovoltaicDTO.getPlantId(), 2);
//逆变器数量
photovoltaicDTO.setInverterNum(CollectionUtils.size(deviceDTOS));
//今日发电量A29dd和今日上网量(??)
List<TsKvDTO> tsKvDTOList = tsKvService.findLatestByCodeAndAttrs(String.valueOf(photovoltaicDTO.getPlantId()), Lists.newArrayList(attrA29dd, attrA30dd), false);
if (CollectionUtils.isNotEmpty(tsKvDTOList)) {
BigDecimal a29dd = tsKvDTOList.stream()
.filter(s -> StringUtils.equals(attrA29dd, s.getAttrKey()))
.map(s -> new BigDecimal(s.getVal())/*.divide(new BigDecimal("1000"),2, RoundingMode.UP)*/)
.findFirst()
.orElse(BigDecimal.ZERO);
photovoltaicDTO.setElectricityUsage(a29dd);
//今日减碳排量
// BigDecimal carbonUsage = CalculationUtil.getCarbonUsage(a29dd, reductionFactor, coefficient, 2);
BigDecimal carbonUsage = CalculationUtil.getCarbonUsage(a29dd, reductionFactor, BigDecimal.ONE, 2);
photovoltaicDTO.setCarbonUsage(carbonUsage);
//今日上网量
BigDecimal internetUsage = tsKvDTOList.stream()
.filter(s -> StringUtils.equals(attrA30dd, s.getAttrKey()))
.map(s -> new BigDecimal(s.getVal()))
.findFirst()
.orElse(BigDecimal.ZERO);
photovoltaicDTO.setInternetUsage(internetUsage);
}
//调用大华视频接口获取检测点数获取正常和总数
return photovoltaicDTO;
}
@Override
public List<String> findVideoById(Long plantId) {
//调用大华视频接口,获取最新视频数据
return null;
}
@Override
public List<ScreenData> getHeatMap() {
List<PlantEntity> list = plantService.list();
if (CollectionUtils.isEmpty(list)) {
throw new SysException("光伏信息不存在");
}
List<String> entityCodes = list.stream().map(PlantEntity::getPlantId).map(String::valueOf).toList();
Optional<List<IotThingEntityDTO>> entityDTOList = thingEntityService.findByCodes(entityCodes, UserContext.getRealTenantCode(), true);
if (entityDTOList.isEmpty()) {
throw new SysException("光伏信息不存在");
}
return list.stream().flatMap(s -> {
ScreenData screenData = new ScreenData();
IotThingEntityDTO iotThingEntity = entityDTOList.get().stream().filter(t -> StringUtils.equals(s.getPlantId().toString(), t.getCode())).findFirst().orElse(null);
if(ObjectUtil.isNotNull(iotThingEntity)){
screenData.setId(s.getPlantId());
screenData.setName(iotThingEntity.getName());
screenData.setLon(s.getLongitude());
screenData.setLat(s.getLatitude());
List<ScreenData.AttrData> attrDataList = Lists.newArrayList();
//装机容量单独处理
ScreenData.AttrData attrCapacity = getAttr(null, "capacity", "装机容量", "kWp", s.getCapacity());
attrDataList.add(attrCapacity);
//日发电量日上网量实时功率
List<TsKvDTO> tsKvDTOList = tsKvService.findLatestByCodeAndAttrs(String.valueOf(s.getPlantId()), Lists.newArrayList(attrA29dd, attrA30dd, attrA16), false);
//发电功率
ScreenData.AttrData attr16 = getAttr(tsKvDTOList, attrA16, "发电功率", "W", BigDecimal.ZERO);
attrDataList.add(attr16);
//日发电量
ScreenData.AttrData attrA29 = getAttr(tsKvDTOList, attrA29dd, "日发电量", "kWh", BigDecimal.ZERO);
attrDataList.add(attrA29);
BigDecimal dayUsage = filterAttrVal(tsKvDTOList, attrA29dd);
screenData.setMeasure(dayUsage);
//日上网量
ScreenData.AttrData attrA30 = getAttr(tsKvDTOList, attrA30dd, "日上网量", "kWh", BigDecimal.ZERO);
attrDataList.add(attrA30);
//性能比
ScreenData.AttrData performance = getAttr(null, "performance", "性能比", "",
CalculationUtil.getPerformance(filterAttrVal(tsKvDTOList, attrA16).divide(new BigDecimal("1000")), s.getCapacity(), 2));
attrDataList.add(performance);
screenData.setData(attrDataList);
return Stream.of(screenData);
}
return null;
}).collect(Collectors.toList());
}
@Override
public Map<String, List<TsKvDTO>> getPowerAnalysis(Long plantId, String type) {
Map<String, List<TsKvDTO>> result = new HashMap<>();
Optional<IotThingEntityDTO> entityByCode = thingEntityService.findEntityByCode(plantId.toString(), UserContext.getRealTenantCode(), true);
//获取今天的开始时间和结束时间
String dayBeginTime = DateTimeUtils.getDayBeginTime();
Long startTimeT = DateTimeUtils.convertTimeToLong(dayBeginTime);
//获取昨天的开始时间和结束时间
Long endTimeT = startTimeT + ONE_DAY - 1;
Long startTimeY = startTimeT - ONE_DAY;
Long endTimeY = startTimeT - 1;
String attrCode;
if (StringUtils.equals(type, "2")) {
attrCode = attrA30hh;
} else {
attrCode = attrA16;
}
List<TsKvDTO> tsKvDTOST = tsKvService.findTsKvByCodeAndAttr(entityByCode.get().getCode(), attrCode, startTimeT, endTimeT, true);
tsKvDTOST.forEach(temp->{
temp.setTs(getStartOfHour(temp.getTs()));
});
List<TsKvDTO> distinctAndSortedTsKvDTOST = tsKvDTOST.stream()
// ts 字段去重保留每个 ts 的第一个出现的对象
.collect(Collectors.collectingAndThen(
Collectors.toMap(
TsKvDTO::getTs, // 假设 TsKvDTO getTs() 方法
tsKvDTO -> tsKvDTO,
(existing, replacement) -> existing),
map -> map.values().stream().sorted(
(o1, o2) -> o1.getTs().compareTo(o2.getTs()) // ts 字段升序排序
).collect(Collectors.toList())
));
List<TsKvDTO> tsKvDTOSY = tsKvService.findTsKvByCodeAndAttr(entityByCode.get().getCode(), attrCode, startTimeY, endTimeY, true);
tsKvDTOSY.forEach(temp->{
temp.setTs(getStartOfHour(temp.getTs()));
});
List<TsKvDTO> distinctAndSortedTsKvDTOSY = tsKvDTOSY.stream()
// ts 字段去重保留每个 ts 的第一个出现的对象
.collect(Collectors.collectingAndThen(
Collectors.toMap(
TsKvDTO::getTs, // 假设 TsKvDTO getTs() 方法
tsKvDTO -> tsKvDTO,
(existing, replacement) -> existing),
map -> map.values().stream().sorted(
(o1, o2) -> o1.getTs().compareTo(o2.getTs()) // ts 字段升序排序
).collect(Collectors.toList())
));
List<TsKvDTO> yyTskv = Lists.newArrayList();
for (int i = 0; i < distinctAndSortedTsKvDTOSY.size(); i++) {
//本期的数据
TsKvDTO tsKvDTOY = distinctAndSortedTsKvDTOSY.get(i);
Long ts = tsKvDTOY.getTs();
//同期的数据
List<TsKvDTO> tsKvDTOT = distinctAndSortedTsKvDTOST.stream().filter(s->s.getTs().compareTo(ts) == 0 ).toList();
if(CollectionUtil.isEmpty(tsKvDTOT)){
TsKvDTO yy = new TsKvDTO(tsKvDTOY.getThingCode(), tsKvDTOY.getAttrKey(), ts, "0");
yyTskv.add(yy);
}else{
BigDecimal yoy = CalculationUtil.getYOY(new BigDecimal(tsKvDTOT.get(0).getVal()), new BigDecimal(tsKvDTOY.getVal()));
TsKvDTO yy = new TsKvDTO(tsKvDTOY.getThingCode(), tsKvDTOY.getAttrKey(), ts, yoy.toString());
yyTskv.add(yy);
}
tsKvDTOY.setVal(new BigDecimal(tsKvDTOY.getVal()).divide(new BigDecimal(1000),2,RoundingMode.HALF_UP).toString());
}
for (int i = 0; i < distinctAndSortedTsKvDTOST.size(); i++) {
//本期的数据
TsKvDTO tsKvDTOY = distinctAndSortedTsKvDTOST.get(i);
tsKvDTOY.setVal(new BigDecimal(tsKvDTOY.getVal()).divide(new BigDecimal(1000),2,RoundingMode.HALF_UP).toString());
}
result.put("today", distinctAndSortedTsKvDTOST);
result.put("yesterday", distinctAndSortedTsKvDTOSY);
result.put("yy", yyTskv);
return result;
}
/**
* 获取指定时间戳所在的整点时间戳
*
* @param timestamp 时间戳
* @return 整点时间戳
*/
public static long getStartOfHour(long timestamp) {
// 将时间戳截断到整点小时
return (timestamp / 3600000) * 3600000;
}
@Override
public Map<String, List<TsKvDTO>> getElectricPowerAnalysis(Long plantId, String type) {
Map<String, List<TsKvDTO>> result = new HashMap<>();
Optional<IotThingEntityDTO> entityByCode = thingEntityService.findEntityByCode(plantId.toString(), UserContext.getRealTenantCode(), true);
if (StringUtils.endsWithIgnoreCase(type, ThingAttrType.YY.getTime().getName())) {
String yearBeginTime = DateTimeUtils.getYearBeginTime();
Long startTime = DateTimeUtils.convertTimeToLong(yearBeginTime);
String yearEndTime = DateTimeUtils.getYearEndTime();
Long endTime = DateTimeUtils.convertTimeToLong(yearEndTime);
//时间列表
List<Long> intervalTimeList = DateTimeUtils.getIntervalMonthList(startTime, endTime, 1);
consumption(entityByCode.get(), startTime, endTime, intervalTimeList, attrA29mm, attrA30mm, 1, TimeType.MONTH, result);
}
if (StringUtils.endsWithIgnoreCase(type, ThingAttrType.MM.getTime().getName())) {
String monthBeginTime = DateTimeUtils.getMonthBeginTime();
Long startTime = DateTimeUtils.convertTimeToLong(monthBeginTime);
String monthEndTime = DateTimeUtils.getMonthEndTime();
Long endTime = DateTimeUtils.convertTimeToLong(monthEndTime);
List<Long> intervalTimeList = DateTimeUtils.getIntervalDayList(startTime, endTime, 1);
consumption(entityByCode.get(), startTime, endTime, intervalTimeList, attrA29dd, attrA30dd, 1, TimeType.DAY, result);
}
return result;
}
@Override
public Map<String, List<TsKvDTO>> getInverterDetails(String code) {
return null;
}
@Override
public List<PhotovoltaicReportDTO> getReportElectric(ChargeStatisticRequest chargeStatisticRequest) {
List<PhotovoltaicReportDTO> resultList = new ArrayList<>();
List<Long> thingIds = chargeStatisticRequest.getThingIds();
List<IotThingEntityDTO> entities = thingEntityService.findEntityByIds(thingIds);
if (CollectionUtils.isEmpty(entities)) {
return resultList;
}
List<String> codes = entities.stream().map(IotThingEntityDTO::getCode).toList();
String attrType = chargeStatisticRequest.getAttrType();
Long startTime = 0L;
Long endTime = 0L;
List<Long> timeList = new ArrayList<>();
String timeType = chargeStatisticRequest.getTimeType();
if (StringUtils.equalsIgnoreCase(TimeType.DAY.getName(), timeType)) {
String dayBeginTime = DateTimeUtils.getDayBeginTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.dateToTimestamp(dayBeginTime);
endTime = startTime + ONE_DAY - 1;
timeList = DateTimeUtils.getIntervalList(startTime, endTime, 60 * 60 * 1000);
}
if (StringUtils.equalsIgnoreCase(TimeType.MONTH.getName(), timeType)) {
String monthBeginTime = DateTimeUtils.getMonthBeginTime(chargeStatisticRequest.getBeginTime());
String monthEndTime = DateTimeUtils.getMonthEndTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.dateToTimestamp(monthBeginTime);
endTime = DateTimeUtils.dateToTimestamp(monthEndTime);
timeList = DateTimeUtils.getIntervalDayList(startTime, endTime, 1);
}
if (StringUtils.equalsIgnoreCase(TimeType.YEAR.getName(), timeType)) {
String monthBeginTime = DateTimeUtils.getYearBeginTime(chargeStatisticRequest.getBeginTime());
String monthEndTime = DateTimeUtils.getYearEndTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.convertTimeToLong(monthBeginTime);
endTime = DateTimeUtils.convertTimeToLong(monthEndTime);
timeList = DateTimeUtils.getIntervalMonthList(startTime, endTime, 1);
}
if (StringUtils.equalsIgnoreCase(TimeType.ANY.getName(), timeType)) {
startTime = DateTimeUtils.dateToTimestamp(chargeStatisticRequest.getBeginTime());
endTime = DateTimeUtils.dateToTimestamp(chargeStatisticRequest.getEndTime());
}
long currentTime = DateTimeUtils.getCurrentTime();
//去除超过的时间
timeList.removeIf(s -> CompareUtil.compare(s, currentTime) > 0);
List<TsKvDTO> tsKvList = tsKvService.findTsKvByCodesAndAttrs(codes, Lists.newArrayList(attrA29 + attrType), startTime, endTime, false);
List<Long> finalTimeList = timeList;
if (CollectionUtils.isEmpty(tsKvList)) {
return entities.stream().map(e -> {
PhotovoltaicReportDTO reportDTO = new PhotovoltaicReportDTO();
reportDTO.setThingId(e.getId());
reportDTO.setCode(e.getCode());
reportDTO.setName(e.getName());
reportDTO.setTimeList(finalTimeList);
return reportDTO;
}).toList();
}
return entities.stream().map(e -> {
PhotovoltaicReportDTO reportDTO = new PhotovoltaicReportDTO();
reportDTO.setThingId(e.getId());
reportDTO.setCode(e.getCode());
reportDTO.setName(e.getName());
reportDTO.setTimeList(finalTimeList);
//过滤数据
List<TsKvDTO> dataList = tsKvList.stream().filter(tsKvDTO -> StringUtils.equals(tsKvDTO.getThingCode(), e.getCode())).toList();
List<Map<String, Object>> collect = Lists.newArrayList();
for (int i = 0; i < finalTimeList.size(); i++) {
int finalI = i;
List<TsKvDTO> list;
if(i== (finalTimeList.size()-1)){
list = dataList.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 )
.toList();
}else {
list = dataList.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 && CompareUtil.compare(s.getTs(), finalTimeList.get(finalI + 1)) < 0).toList();
}
BigDecimal total = list.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
collect.addAll(list.stream().map(data -> Map.<String, Object>of("ts", finalTimeList.get(finalI), "val", total)).toList());
}
reportDTO.setPlantDataList(collect);
BigDecimal total = dataList.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
reportDTO.setElectricityUsage(total);
return reportDTO;
}).toList();
}
@Override
public void electricExport(ChargeStatisticRequest chargeStatisticRequest, HttpServletResponse response) {
List<PhotovoltaicReportDTO> reportDTOList = getReportElectric(chargeStatisticRequest);
//获取动态时间
List<Long> timeList = reportDTOList.get(0).getTimeList();
//创建表头
List<ExcelExportEntity> tableHeaderList = getTableHeader(timeList, chargeStatisticRequest.getTimeType());
if (CollectionUtils.isEmpty(reportDTOList)) {
ExportParams exportParams = new ExportParams("发电统计报表", "发电统计");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, tableHeaderList, Lists.newArrayList());
ExcelUtils.downLoadExcel("发电统计报表.xls", response, workbook);
}
List<Map<String, Object>> dataList = new ArrayList<>();
for (PhotovoltaicReportDTO photovoltaicReportDTO : reportDTOList) {
Map<String, Object> valMap = new HashMap<>();
valMap.put("name", photovoltaicReportDTO.getName());
valMap.put("electricityUsage", photovoltaicReportDTO.getElectricityUsage());
List<Map<String, Object>> plantDataList = photovoltaicReportDTO.getPlantDataList();
if (CollectionUtils.isNotEmpty(plantDataList)) {
for (Map<String, Object> plantData : plantDataList) {
Long ts = MapUtils.getLong(plantData, "ts");
String val = MapUtils.getString(plantData, "val");
valMap.put(String.valueOf(ts), val);
}
}
dataList.add(valMap);
}
ExportParams exportParams = new ExportParams("发电统计报表", "发电统计");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, tableHeaderList, dataList);
ExcelUtils.downLoadExcel("发电统计报表.xls", response, workbook);
}
@Override
public List<PhotovoltaicReportDTO> getReportConsumption(ChargeStatisticRequest chargeStatisticRequest) {
List<PhotovoltaicReportDTO> resultList = new ArrayList<>();
List<Long> thingIds = chargeStatisticRequest.getThingIds();
List<IotThingEntityDTO> entities = thingEntityService.findEntityByIds(thingIds);
if (CollectionUtils.isEmpty(entities)) {
return resultList;
}
List<String> codes = entities.stream().map(IotThingEntityDTO::getCode).toList();
String attrType = chargeStatisticRequest.getAttrType();
Long startTime = 0L;
Long endTime = 0L;
List<Long> timeList = new ArrayList<>();
String timeType = chargeStatisticRequest.getTimeType();
if (StringUtils.equalsIgnoreCase(TimeType.DAY.getName(), timeType)) {
String dayBeginTime = DateTimeUtils.getDayBeginTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.dateToTimestamp(dayBeginTime);
endTime = startTime + ONE_DAY - 1;
timeList = DateTimeUtils.getIntervalList(startTime, endTime, 60 * 60 * 1000);
}
if (StringUtils.equalsIgnoreCase(TimeType.MONTH.getName(), timeType)) {
String monthBeginTime = DateTimeUtils.getMonthBeginTime(chargeStatisticRequest.getBeginTime());
String monthEndTime = DateTimeUtils.getMonthEndTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.dateToTimestamp(monthBeginTime);
endTime = DateTimeUtils.dateToTimestamp(monthEndTime);
timeList = DateTimeUtils.getIntervalDayList(startTime, endTime, 1);
}
if (StringUtils.equalsIgnoreCase(TimeType.YEAR.getName(), timeType)) {
String monthBeginTime = DateTimeUtils.getYearBeginTime(chargeStatisticRequest.getBeginTime());
String monthEndTime = DateTimeUtils.getYearEndTime(chargeStatisticRequest.getBeginTime());
startTime = DateTimeUtils.convertTimeToLong(monthBeginTime);
endTime = DateTimeUtils.convertTimeToLong(monthEndTime);
timeList = DateTimeUtils.getIntervalMonthList(startTime, endTime, 1);
}
if (StringUtils.equalsIgnoreCase(TimeType.ANY.getName(), timeType)) {
startTime = DateTimeUtils.dateToTimestamp(chargeStatisticRequest.getBeginTime());
endTime = DateTimeUtils.dateToTimestamp(chargeStatisticRequest.getEndTime());
}
long currentTime = DateTimeUtils.getCurrentTime();
//去除超过的时间
timeList.removeIf(s -> CompareUtil.compare(s, currentTime) > 0);
//发电量
List<TsKvDTO> tsKvList29 = getFillDataList(codes, attrA29 + attrType, startTime, endTime, timeList);
//上网量
List<TsKvDTO> tsKvList30 = getFillDataList(codes, attrA30 + attrType, startTime, endTime, timeList);
//获取总量
List<Long> finalTimeList = timeList;
entities.forEach(e -> {
PhotovoltaicReportDTO photovoltaicReportDTO = new PhotovoltaicReportDTO();
photovoltaicReportDTO.setThingId(e.getId());
photovoltaicReportDTO.setCode(e.getCode());
photovoltaicReportDTO.setName(e.getName());
photovoltaicReportDTO.setTimeList(finalTimeList);
List<TsKvDTO> list29 = tsKvList29.stream().filter(tsKvDTO -> StringUtils.equals(tsKvDTO.getThingCode(), e.getCode()) && StringUtils.startsWith(tsKvDTO.getAttrKey(), attrA29)).toList();
BigDecimal reduce29 = list29.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
List<TsKvDTO> list30 = tsKvList30.stream().filter(tsKvDTO -> StringUtils.equals(tsKvDTO.getThingCode(), e.getCode()) && StringUtils.startsWith(tsKvDTO.getAttrKey(), attrA30)).toList();
BigDecimal reduce30 = list30.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
//消纳量 = 发电量 - 上网量
BigDecimal consumption = reduce29.subtract(reduce30);
//消纳率
BigDecimal performance = CalculationUtil.getPerformance(consumption, reduce29, 4);
PhotovoltaicConsumptionDTO consumptionTotal = new PhotovoltaicConsumptionDTO();
consumptionTotal.setElectricityUsage(reduce29);
consumptionTotal.setInternetUsage(reduce30);
consumptionTotal.setConsumptionUsage(consumption);
consumptionTotal.setConsumptionRate(performance);
photovoltaicReportDTO.setConsumptionTotal(consumptionTotal);
//时间段的消纳报表数据
List<PhotovoltaicConsumptionDTO> consumptionDTOList = Lists.newArrayList();
for (int i = 0; i < finalTimeList.size(); i++) {
int finalI = i;
List<TsKvDTO> list2;
List<TsKvDTO> list3;
if(i== (finalTimeList.size()-1)){
list2 = list29.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 )
.toList();
list3 = list30.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 )
.toList();
}else {
list2 = list29.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 && CompareUtil.compare(s.getTs(), finalTimeList.get(finalI + 1)) < 0)
.toList();
list3 = list30.stream().filter(s -> CompareUtil.compare(s.getTs(), finalTimeList.get(finalI)) >= 0 && CompareUtil.compare(s.getTs(), finalTimeList.get(finalI + 1)) < 0)
.toList();
}
BigDecimal reduce2 = list2.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal reduce3 = list3.stream().map(s -> new BigDecimal(s.getVal())).reduce(BigDecimal.ZERO, BigDecimal::add);
PhotovoltaicConsumptionDTO consumptionDTO = new PhotovoltaicConsumptionDTO();
consumptionDTO.setElectricityUsage(reduce2);
consumptionDTO.setInternetUsage(reduce3);
BigDecimal subtract = reduce2.subtract(reduce3);
consumptionDTO.setConsumptionUsage(subtract);
consumptionDTO.setConsumptionRate(CalculationUtil.getPerformance(subtract, reduce2, 4));
consumptionDTO.setTs(finalTimeList.get(finalI));
consumptionDTOList.add(consumptionDTO);
}
photovoltaicReportDTO.setConsumptionDataList(consumptionDTOList);
resultList.add(photovoltaicReportDTO);
});
return resultList;
}
@Override
public void consumptionExport(ChargeStatisticRequest chargeStatisticRequest, HttpServletResponse response) {
try {
List<PhotovoltaicReportDTO> reportDTOList = getReportConsumption(chargeStatisticRequest);
//获取动态时间
List<Long> timeList = reportDTOList.get(0).getTimeList();
//创建表头
List<ExcelExportEntity> tableHeaderList = getConsumptionTableHeader(timeList, chargeStatisticRequest.getTimeType());
if (CollectionUtils.isEmpty(reportDTOList)) {
ExportParams exportParams = new ExportParams("上网消纳报表", "上网消纳");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, tableHeaderList, Lists.newArrayList());
ExcelUtils.downLoadExcel("上网消纳报表.xls", response, workbook);
}
List<Map<String, Object>> dataList = new ArrayList<>();
for (PhotovoltaicReportDTO photovoltaicReportDTO : reportDTOList) {
Map<String, Object> valMap = new HashMap<>();
valMap.put("name", photovoltaicReportDTO.getName());
//发电总量的数据
PhotovoltaicConsumptionDTO consumptionTotal = photovoltaicReportDTO.getConsumptionTotal();
List<Map<String, Object>> yhxxList = new ArrayList<>();
Map<String, Object> yhxxMap = new HashMap<>();
yhxxMap.put("electricityUsage", consumptionTotal.getElectricityUsage());
yhxxMap.put("consumptionUsage", consumptionTotal.getConsumptionUsage());
yhxxMap.put("internetUsage", consumptionTotal.getInternetUsage());
yhxxMap.put("consumptionRate", consumptionTotal.getConsumptionRate());
yhxxList.add(yhxxMap);
valMap.put("electricityUsage", yhxxList);
//动态时间量
List<PhotovoltaicConsumptionDTO> consumptionDataList = photovoltaicReportDTO.getConsumptionDataList();
consumptionDataList.forEach(c -> {
// int time = 0;
// if (StringUtils.equalsIgnoreCase(TimeType.DAY.getName(), chargeStatisticRequest.getTimeType())){
// time = DateTimeUtils.parseDateTime(c.getTs()).getHour();
// }
// if (StringUtils.equalsIgnoreCase(TimeType.MONTH.getName(), chargeStatisticRequest.getTimeType())){
// time = DateTimeUtils.parseDateTime(c.getTs()).getDayOfMonth();
// }
// if (StringUtils.equalsIgnoreCase(TimeType.YEAR.getName(), chargeStatisticRequest.getTimeType())){
// time = DateTimeUtils.parseDateTime(c.getTs()).getMonth().getValue();
// }
List<Map<String, Object>> yhxxList1 = new ArrayList<>();
Map<String, Object> yhxxMap1 = new HashMap<>();
yhxxMap1.put("electricityUsage", c.getElectricityUsage());
yhxxMap1.put("consumptionUsage", c.getConsumptionUsage());
yhxxMap1.put("internetUsage", c.getInternetUsage());
yhxxMap1.put("consumptionRate", c.getConsumptionRate());
yhxxList1.add(yhxxMap1);
valMap.put(String.valueOf(c.getTs()), yhxxList1);
});
dataList.add(valMap);
}
ExportParams exportParams = new ExportParams("发电统计报表", "发电统计");
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, tableHeaderList, dataList);
ExcelUtils.downLoadExcel("发电统计报表.xls", response, workbook);
} catch (Exception e) {
log.error("222222", e);
}
}
private List<TsKvDTO> getFillDataList(List<String> codes, String attr, Long startTime, Long endTime, List<Long> timeList) {
List<TsKvDTO> tsKvList29 = tsKvService.findTsKvByCodesAndAttrs(codes, Lists.newArrayList(attr), startTime, endTime, false);
return codes.stream().flatMap(s -> fillData(timeList, tsKvList29, s, attr).stream()).toList();
}
private void consumption(IotThingEntityDTO thingEntityDTO, Long startTime, Long endTime, List<Long> intervalTimeList, String attrA29, String attrA30, Integer interval, TimeType timeType, Map<String, List<TsKvDTO>> result) {
//月发电量
List<TsKvDTO> tsKvYYList = tsKvService.findTsKvByCodeAndAttr(thingEntityDTO.getCode(), attrA29, startTime, endTime, true);
//补全数据
List<TsKvDTO> tsKvDTOS = fillData(intervalTimeList, tsKvYYList, thingEntityDTO.getCode(), attrA29);
//月上网量
List<TsKvDTO> tsKvYY30List = tsKvService.findTsKvByCodeAndAttr(thingEntityDTO.getCode(), attrA30, startTime, endTime, true);
//List<TsKvDTO> tsKvYY30List = tsKvService.findTsKvIntervalAggByCodeAndAttr(thingEntityDTO.getCode(), attrA30, startTime, endTime, AggType.SUM, interval, timeType, true);
//补全数据
List<TsKvDTO> tsKv30DTOS = fillData(intervalTimeList, tsKvYY30List, thingEntityDTO.getCode(), attrA30);
//消纳量
List<TsKvDTO> consumptionTskv = Lists.newArrayList();
List<TsKvDTO> consumptionTskvRate = Lists.newArrayList();
for (int i = 0; i < tsKvDTOS.size(); i++) {
TsKvDTO tsKvDTO29 = tsKvDTOS.get(i);
tsKvDTO29.setVal(new BigDecimal(tsKvDTO29.getVal())/*.divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP)*/.toPlainString());
TsKvDTO tsKvDTO30 = tsKv30DTOS.get(i);
//消纳量
BigDecimal consumption = new BigDecimal(tsKvDTO29.getVal()).subtract(new BigDecimal(tsKvDTO30.getVal()));
TsKvDTO tsKv = new TsKvDTO(thingEntityDTO.getCode(), "consumption", tsKvDTO29.getTs(), consumption.toString());
consumptionTskv.add(tsKv);
//消纳比
BigDecimal consumptionPerformance = CalculationUtil.getPerformance(consumption, new BigDecimal(tsKvDTO29.getVal()), 4);
TsKvDTO tsKvDTO = new TsKvDTO(thingEntityDTO.getCode(), "consumptionRate", tsKvDTO29.getTs(), consumptionPerformance.toString());
consumptionTskvRate.add(tsKvDTO);
}
result.put("A29", tsKvDTOS);
result.put("consumption",consumptionTskv);
result.put("consumptionRate", consumptionTskvRate);
}
private ScreenData.AttrData getAttr(List<TsKvDTO> tsKvDTOList, String attrCode, String attrName, String attrUnit, BigDecimal defaultVal) {
ScreenData.AttrData attrData = new ScreenData.AttrData();
attrData.setAttrCode(attrCode);
attrData.setAttrName(attrName);
attrData.setAttrUnit(attrUnit);
if (CollectionUtils.isNotEmpty(tsKvDTOList)) {
if(attrCode.startsWith(attrA29)){
//attrData.setAttrValue(filterAttrVal(tsKvDTOList, attrCode).toString());
attrData.setAttrValue(filterAttrVal(tsKvDTOList, attrCode)/*.divide(new BigDecimal("1000"),2, RoundingMode.UP)*/.toPlainString());
}else {
attrData.setAttrValue(filterAttrVal(tsKvDTOList, attrCode).divide(new BigDecimal("1000"),2, RoundingMode.UP).toPlainString());
}
} else {
attrData.setAttrValue(defaultVal.toString());
}
return attrData;
}
private static BigDecimal filterAttrVal(List<TsKvDTO> tsKvDTOList, String attrCode) {
return tsKvDTOList.stream()
.filter(d -> StringUtils.equals(attrCode, d.getAttrKey()))
.map(d -> new BigDecimal(d.getVal()))
.findFirst()
.orElse(BigDecimal.ZERO);
}
private static List<TsKvDTO> fillData(List<Long> intervalTimeList, List<TsKvDTO> tsKvList, String code, String attr) {
if (CollectionUtils.isEmpty(tsKvList)) {
return intervalTimeList.stream()
.map(s -> new TsKvDTO(code, attr, s, "0"))
.collect(Collectors.toList());
}
if(CollectionUtils.isEmpty(intervalTimeList)){
return tsKvList;
}
List<TsKvDTO> handleList = tsKvList.stream().filter(d -> StringUtils.equals(code, d.getThingCode()) && StringUtils.equals(attr, d.getAttrKey())).toList();
Map<String, Map<String, List<TsKvDTO>>> groupedMap = handleList.stream()
.collect(Collectors.groupingBy(TsKvDTO::getThingCode,
Collectors.groupingBy(TsKvDTO::getAttrKey)));
List<TsKvDTO> result = new ArrayList<>();
for (Map.Entry<String, Map<String, List<TsKvDTO>>> stringMapEntry : groupedMap.entrySet()) {
String thingCode = stringMapEntry.getKey();
for (Map.Entry<String, List<TsKvDTO>> stringListEntry : stringMapEntry.getValue().entrySet()) {
String attrKey = stringListEntry.getKey();
List<TsKvDTO> value = stringListEntry.getValue();
List<Long> existingTimestamps = value.stream().map(TsKvDTO::getTs).toList();
for (Long timestamp : intervalTimeList) {
if (existingTimestamps.contains(timestamp)) {
TsKvDTO tsKvDTO1 = value.stream()
.filter(tsKvDTO -> tsKvDTO.getTs().equals(timestamp))
.findAny().orElse(null);
//电力要/1000
if (ObjectUtil.isNotNull(tsKvDTO1) && tsKvDTO1.getAttrKey().startsWith(attrA16)) {
BigDecimal performance = CalculationUtil.getPerformance(new BigDecimal(tsKvDTO1.getVal()), new BigDecimal(1000), 2);
tsKvDTO1.setVal(performance.toString());
}
result.add(tsKvDTO1);
} else {
result.add(new TsKvDTO(thingCode, attrKey, timestamp, "0"));
}
}
}
}
return result;
}
private List<ExcelExportEntity> getConsumptionTableHeader(List<Long> timeList, String timeType) {
List<ExcelExportEntity> paramCols = new ArrayList<>();
ExcelExportEntity colEntity1 = new ExcelExportEntity("结构", "name");
colEntity1.setNeedMerge(true);
paramCols.add(colEntity1);
ExcelExportEntity colEntity2 = new ExcelExportEntity("发电总量(kWh)", "electricityUsage");
List<ExcelExportEntity> yyxxList = new ArrayList<>();
yyxxList.add(new ExcelExportEntity("发电量", "electricityUsage"));
yyxxList.add(new ExcelExportEntity("消纳量", "consumptionUsage"));
yyxxList.add(new ExcelExportEntity("上网量", "internetUsage"));
yyxxList.add(new ExcelExportEntity("消纳率", "consumptionRate"));
colEntity2.setList(yyxxList);
paramCols.add(colEntity2);
//动态表头集合
paramCols.addAll(new ArrayList<>(timeList.stream()
.flatMap(c -> {
ExcelExportEntity excelExportEntity = null;
if (StringUtils.equalsIgnoreCase(TimeType.DAY.getName(), timeType)) {
int hour = DateTimeUtils.parseDateTime(c).getHour();
excelExportEntity = new ExcelExportEntity(hour + "时", String.valueOf(c));
}
if (StringUtils.equalsIgnoreCase(TimeType.MONTH.getName(), timeType)) {
int day = DateTimeUtils.parseDateTime(c).getDayOfMonth();
excelExportEntity = new ExcelExportEntity(day + "日", String.valueOf(c));
}
if (StringUtils.equalsIgnoreCase(TimeType.YEAR.getName(), timeType)) {
int month = DateTimeUtils.parseDateTime(c).getMonth().getValue();
excelExportEntity = new ExcelExportEntity(month + "月", String.valueOf(c));
}
List<ExcelExportEntity> yyxxList1 = new ArrayList<>();
yyxxList1.add(new ExcelExportEntity("发电量", "electricityUsage"));
yyxxList1.add(new ExcelExportEntity("消纳量", "consumptionUsage"));
yyxxList1.add(new ExcelExportEntity("上网量", "internetUsage"));
yyxxList1.add(new ExcelExportEntity("消纳率", "consumptionRate"));
if (ObjectUtil.isNotNull(excelExportEntity)) {
excelExportEntity.setList(yyxxList1);
return Stream.of(excelExportEntity);
}
return Stream.empty();
}).toList()));
return paramCols;
}
private List<ExcelExportEntity> getTableHeader(List<Long> timeList, String timeType) {
List<ExcelExportEntity> paramCols = new ArrayList<>();
ExcelExportEntity colEntity1 = new ExcelExportEntity("结构", "name");
paramCols.add(colEntity1);
ExcelExportEntity colEntity2 = new ExcelExportEntity("发电总量(kWh)", "electricityUsage");
paramCols.add(colEntity2);
//动态表头集合
paramCols.addAll(new ArrayList<>(timeList.stream()
.flatMap(c -> {
if (StringUtils.equalsIgnoreCase(TimeType.DAY.getName(), timeType)) {
int hour = DateTimeUtils.parseDateTime(c).getHour();
return Stream.of(new ExcelExportEntity(hour + "时", String.valueOf(c)));
}
if (StringUtils.equalsIgnoreCase(TimeType.MONTH.getName(), timeType)) {
int day = DateTimeUtils.parseDateTime(c).getDayOfMonth();
return Stream.of(new ExcelExportEntity(day + "日", String.valueOf(c)));
}
if (StringUtils.equalsIgnoreCase(TimeType.YEAR.getName(), timeType)) {
int month = DateTimeUtils.parseDateTime(c).getMonth().getValue();
return Stream.of(new ExcelExportEntity(month + "月", String.valueOf(c)));
}
return Stream.empty();
}).toList()));
return paramCols;
}
}

100
modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/controller/IotEnergyConsumptionTargetController.java

@ -0,0 +1,100 @@
package com.thing.qingyuan.regionalenterprises.consumptionTarget.controller;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.dto.IotEnergyConsumptionTargetDTO;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.dto.IotEnergyValueDTO;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.service.IotEnergyConsumptionTargetService;
import com.thing.common.core.annotation.LogOperation;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.validator.AssertUtils;
import com.thing.common.core.validator.ValidatorUtils;
import com.thing.common.core.validator.group.AddGroup;
import com.thing.common.core.validator.group.DefaultGroup;
import com.thing.common.core.validator.group.UpdateGroup;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("target")
@Tag(name = "工业增加值")
public class IotEnergyConsumptionTargetController {
@Autowired
private IotEnergyConsumptionTargetService iotEnergyConsumptionTargetService;
@GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE,description ="当前页码,从1开始") ,
@Parameter(name = Constant.LIMIT,description ="每页显示记录数") ,
@Parameter(name = Constant.ORDER_FIELD,description ="排序字段") ,
@Parameter(name = "regionCode",description ="区域"),
@Parameter(name = "industryType",description ="行业"),
@Parameter(name = "name",description ="企业名称"),
@Parameter(name = "year",description ="年份"),
})
public Result<PageData<IotEnergyConsumptionTargetDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){
PageData<IotEnergyConsumptionTargetDTO> pageData = iotEnergyConsumptionTargetService.pageList(params);
return new Result<PageData<IotEnergyConsumptionTargetDTO>>().ok(pageData);
}
// @GetMapping("list")
// @Operation(summary="列表")
// @Parameters({
// @Parameter(name = Constant.PAGE,description ="当前页码,从1开始") ,
// @Parameter(name = Constant.LIMIT,description ="每页显示记录数") ,
// @Parameter(name = Constant.ORDER_FIELD,description ="排序字段") ,
// @Parameter(name = Constant.ORDER,description ="排序方式,可选值(asc、desc)")
// })
// public Result<List<IotEnergyConsumptionTargetDTO>> list(@RequestParam Map<String, Object> params){
// List<IotEnergyConsumptionTargetDTO> list = iotEnergyConsumptionTargetService.findAllList(params);
// return new Result<List<IotEnergyConsumptionTargetDTO>>().ok(list);
// }
//
@GetMapping("{id}")
@Operation(summary="信息")
public Result<IotEnergyValueDTO> get(@PathVariable("id") Long id){
IotEnergyValueDTO data = iotEnergyConsumptionTargetService.getByIds(id);
return new Result<IotEnergyValueDTO>().ok(data);
}
@PostMapping
@Operation(summary="保存")
@LogOperation("保存")
public Result<Object> save(@RequestBody IotEnergyValueDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
iotEnergyConsumptionTargetService.addTarget(dto);
return new Result<>();
}
@PutMapping
@Operation(summary="修改")
@LogOperation("修改")
public Result<Void> update(@RequestBody IotEnergyValueDTO dto){
// 效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
iotEnergyConsumptionTargetService.updateList(dto);
return new Result<>();
}
@DeleteMapping
@Operation(summary="删除")
@LogOperation("删除")
public Result<Void> delete(@RequestBody Long[] ids){
// 效验数据
AssertUtils.isArrayEmpty(ids, "id");
iotEnergyConsumptionTargetService.deleteByids(ids);
return new Result<>();
}
}

101
modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/controller/IotValueAddedController.java

@ -0,0 +1,101 @@
package com.thing.qingyuan.regionalenterprises.consumptionTarget.controller;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.dto.IotValueAddDTO;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.dto.iotValueAddedDTO;
import com.thing.qingyuan.regionalenterprises.consumptionTarget.service.IotValueAddedService;
import com.thing.common.core.annotation.LogOperation;
import com.thing.common.core.constants.Constant;
import com.thing.common.core.validator.AssertUtils;
import com.thing.common.core.validator.ValidatorUtils;
import com.thing.common.core.validator.group.AddGroup;
import com.thing.common.core.validator.group.DefaultGroup;
import com.thing.common.core.validator.group.UpdateGroup;
import com.thing.common.core.web.response.PageData;
import com.thing.common.core.web.response.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("valueAdded")
@Tag(name = "能碳指标")
public class IotValueAddedController {
@Autowired
private IotValueAddedService iotValueAddedService;
@GetMapping("page")
@Operation(summary="分页")
@Parameters({
@Parameter(name = Constant.PAGE,description ="当前页码,从1开始") ,
@Parameter(name = Constant.LIMIT,description ="每页显示记录数") ,
@Parameter(name = Constant.ORDER_FIELD,description ="排序字段") ,
@Parameter(name = "regionCode",description ="区域"),
@Parameter(name = "industryType",description ="行业"),
@Parameter(name = "name",description ="企业名称"),
@Parameter(name = "year",description ="年份"),
})
public Result<PageData<iotValueAddedDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params){
PageData<iotValueAddedDTO> pageData = iotValueAddedService.pageList(params);
return new Result<PageData<iotValueAddedDTO>>().ok(pageData);
}
// @GetMapping("list")
// @Operation(summary="列表")
// @Parameters({
// @Parameter(name = Constant.PAGE,description ="当前页码,从1开始") ,
// @Parameter(name = Constant.LIMIT,description ="每页显示记录数") ,
// @Parameter(name = Constant.ORDER_FIELD,description ="排序字段") ,
// @Parameter(name = Constant.ORDER,description ="排序方式,可选值(asc、desc)")
// })
// public Result<List<IotEnergyConsumptionTargetDTO>> list(@RequestParam Map<String, Object> params){
// List<IotEnergyConsumptionTargetDTO> list = iotValueAddedService.findAllList(params);
// return new Result<List<IotEnergyConsumptionTargetDTO>>().ok(list);
// }
//
@GetMapping("{id}")
@Operation(summary="信息")
public Result<IotValueAddDTO> get(@PathVariable("id") Long id){
IotValueAddDTO data = iotValueAddedService.getByIds(id);
return new Result<IotValueAddDTO>().ok(data);
}
@PostMapping
@Operation(summary="保存")
@LogOperation("保存")
public Result<Object> save(@RequestBody IotValueAddDTO dto){
//效验数据
ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);
iotValueAddedService.addTarget(dto);
return new Result<>();
}
@PutMapping
@Operation(summary="修改")
@LogOperation("修改")
public Result<Void> update(@RequestBody IotValueAddDTO dto){
// 效验数据
ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);
iotValueAddedService.updateList(dto);
return new Result<>();
}
@DeleteMapping
@Operation(summary="删除")
@LogOperation("删除")
public Result<Void> delete(@RequestBody Long[] ids){
// 效验数据
AssertUtils.isArrayEmpty(ids, "id");
iotValueAddedService.deleteByids(ids);
return new Result<>();
}
}

26
modules/qingyuan/src/main/java/com/thing/qingyuan/regionalenterprises/consumptionTarget/dto/IotAddedDateDTO.java

@ -0,0 +1,26 @@
package com.thing.qingyuan.regionalenterprises.consumptionTarget.dto;
import com.thing.common.orm.entity.BaseDateEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class IotAddedDateDTO extends BaseDateEntity {
@Schema(description = "租户code")
private Long tenantCode;
@Schema(description = "能耗目标")
private BigDecimal addedValue;
@Schema(description = "月份")
private String month;
@Schema(description = "类型")
private Integer type;
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save