Browse Source

Merge pull request 'master' (#47) from master into V3

Reviewed-on: http://git.lrdaiot.cn:9000/thing/thing_api/pulls/47
qingyuan_dev_new
李帅 2 years ago
parent
commit
99b98b9d74
  1. 17
      application/src/main/resources/application.yml
  2. 29
      common/core/src/main/java/com/thing/common/core/utils/excel/ExcelUtils.java
  3. 20
      help/sql/dml_1.0.1.sql
  4. 2
      modules/equipment/src/main/java/com/thing/eq/eqmanager/service/impl/IotThingsServiceImpl.java
  5. 43
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/controller/EnergyLossController.java
  6. 35
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossDTO.java
  7. 31
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossInfoDTO.java
  8. 37
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossReportParam.java
  9. 21
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/KeyAndCodeDTO.java
  10. 19
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/NameAndCodeDTO.java
  11. 33
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/excel/EnergyLossExcel.java
  12. 15
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/EnergyLossService.java
  13. 245
      modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/impl/EnergyLossServiceImpl.java
  14. 1
      modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java
  15. 1
      modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java
  16. 9
      modules/thing/src/main/java/com/thing/thing/relation/detail/service/impl/IotThingRelationDetailServiceImpl.java

17
application/src/main/resources/application.yml

@ -169,6 +169,23 @@ aviator:
# no limitation on loop count.Default is zero.
max_loop_count: 1000
actors:
system:
# 每个邮箱处理完这些数量的邮件后会重新找一个线程池中的线程进行消费,避免单个线程占用过多CPU
throughput: 5
# actor系统最大重启次数
maxActorInitAttempts: 3
# 定时线程数,目前没什么用
schedulerPoolSize: 1
# 顶级转发器线程数,由于不需要做任何实质性操作,因此只需要单线程即可
rootDispatcherSize: 1
# 租户线程可能会涉及到业务操作,给2个线程
tenantDispatcherSize: 2
# 非租户线程也可能会涉及到业务操作,给2个线程
nonTenantDispatcherSize: 2
# 设备处理是直接涉及到业务操作的,因此可以给多一点线程数,具体多少看企业数据量
device-dispatcher-size: 4
#队列相关配置
queue:
type: in-memory # 队列类型: inMemory / disruptor

29
common/core/src/main/java/com/thing/common/core/utils/excel/ExcelUtils.java

@ -16,7 +16,7 @@ import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
@ -48,6 +48,33 @@ public class ExcelUtils {
public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response){
defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
public static void exportExcel1(List<?> list, String title, String sheetName, Class<?> pojoClass, String fileName, HttpServletResponse response){
defaultExport1(list, pojoClass, fileName, response, new ExportParams(title, sheetName));
}
private static void defaultExport1(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) {
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, pojoClass, list);
if (workbook != null) {
// 设置第一列左对齐
Sheet sheet = workbook.getSheetAt(0);
CellStyle style = workbook.createCellStyle();
style.setAlignment(HorizontalAlignment.LEFT);
style.setVerticalAlignment(VerticalAlignment.CENTER);
// 获取第一列列索引
int firstColumnIndex = 0;
// 遍历所有行
for (Row row : sheet) {
Cell cell = row.getCell(firstColumnIndex);
if (cell != null) {
cell.setCellStyle(style);
}
}
// 下载文件
downLoadExcel(fileName, response, workbook);
}
}
public static void exportExcel(List<?> list, Class<?> pojoClass, String title, String sheetName, String fileName, ExcelType excelType, HttpServletResponse response){

20
help/sql/dml_1.0.1.sql

@ -8,4 +8,22 @@ ALTER TABLE iot_thing_source ADD COLUMN if not EXISTS start_status VARCHAR(255)
COMMENT ON COLUMN "public"."iot_thing_source"."start_status" IS '属性启用状态';
ALTER TABLE iot_visual_component ADD COLUMN if not EXISTS config text;
COMMENT ON COLUMN "public"."iot_visual_component"."config" IS '部件配置';
COMMENT ON COLUMN "public"."iot_visual_component"."config" IS '部件配置';
INSERT INTO "public"."qrtz_cron_triggers" VALUES ('ThingScheduler', 'TASK_192082754584838144', 'DEFAULT', '0 0/10 * * * ?', 'Asia/Shanghai');
INSERT INTO "public"."qrtz_cron_triggers" VALUES ('ThingScheduler', 'TASK_192082542600519680', 'DEFAULT', '0 1/5 * * * ? *', 'Asia/Shanghai');
INSERT INTO "public"."qrtz_cron_triggers" VALUES ('ThingScheduler', 'TASK_192082651446902784', 'DEFAULT', '0 0/1 * * * ? *', 'Asia/Shanghai');
INSERT INTO "public"."qrtz_job_details" VALUES ('ThingScheduler', 'TASK_192082542600519680', 'DEFAULT', NULL, 'com.thing.quartz.timetask.utils.ScheduleJob', 'f', 'f', 'f', 'f', E'\\254\\355\\000\\005sr\\000\\025org.quartz.JobDataMap\\237\\260\\203\\350\\277\\251\\260\\313\\002\\000\\000xr\\000&org.quartz.utils.StringKeyDirtyFlagMap\\202\\010\\350\\303\\373\\305](\\002\\000\\001Z\\000\\023allowsTransientDataxr\\000\\035org.quartz.utils.DirtyFlagMap\\023\\346.\\255(v\\012\\316\\002\\000\\002Z\\000\\005dirtyL\\000\\003mapt\\000\\017Ljava/util/Map;xp\\001sr\\000\\021java.util.HashMap\\005\\007\\332\\301\\303\\026`\\321\\003\\000\\002F\\000\\012loadFactorI\\000\\011thresholdxp?@\\000\\000\\000\\000\\000\\014w\\010\\000\\000\\000\\020\\000\\000\\000\\001t\\000\\015JOB_PARAM_KEYsr\\0002com.thing.quartz.timetask.entity.ScheduleJobEntity\\000\\000\\000\\000\\000\\000\\000\\001\\002\\000\\005L\\000\\010beanNamet\\000\\022Ljava/lang/String;L\\000\\016cronExpressionq\\000~\\000\\011L\\000\\006paramsq\\000~\\000\\011L\\000\\006remarkq\\000~\\000\\011L\\000\\006statust\\000\\023Ljava/lang/Integer;xr\\000*com.thing.common.orm.entity.BaseDateEntity\\025Q\\000\\257\\341\\177a\\350\\002\\000\\005L\\000\\012createDatet\\000\\020Ljava/lang/Long;L\\000\\007creatorq\\000~\\000\\014L\\000\\002idq\\000~\\000\\014L\\000\\012updateDateq\\000~\\000\\014L\\000\\007updaterq\\000~\\000\\014xpsr\\000\\016java.lang.Long;\\213\\344\\220\\314\\217#\\337\\002\\000\\001J\\000\\005valuexr\\000\\020java.lang.Number\\206\\254\\225\\035\\013\\224\\340\\213\\002\\000\\000xp\\000\\000\\001\\221\\351\\377F\\375sq\\000~\\000\\016\\016\\317\\237a\\007\\264V\\001sq\\000~\\000\\016\\002\\252j\\016\\007B\\000\\000q\\000~\\000\\020q\\000~\\000\\021t\\000\\011AlarmTaskt\\000\\0170 1/5 * * * ? *t\\000\\000t\\000\\006\\345\\221\\212\\350\\255\\246sr\\000\\021java.lang.Integer\\022\\342\\240\\244\\367\\201\\2078\\002\\000\\001I\\000\\005valuexq\\000~\\000\\017\\000\\000\\000\\001x\\000');
INSERT INTO "public"."qrtz_job_details" VALUES ('ThingScheduler', 'TASK_192082651446902784', 'DEFAULT', NULL, 'com.thing.quartz.timetask.utils.ScheduleJob', 'f', 'f', 'f', 'f', E'\\254\\355\\000\\005sr\\000\\025org.quartz.JobDataMap\\237\\260\\203\\350\\277\\251\\260\\313\\002\\000\\000xr\\000&org.quartz.utils.StringKeyDirtyFlagMap\\202\\010\\350\\303\\373\\305](\\002\\000\\001Z\\000\\023allowsTransientDataxr\\000\\035org.quartz.utils.DirtyFlagMap\\023\\346.\\255(v\\012\\316\\002\\000\\002Z\\000\\005dirtyL\\000\\003mapt\\000\\017Ljava/util/Map;xp\\001sr\\000\\021java.util.HashMap\\005\\007\\332\\301\\303\\026`\\321\\003\\000\\002F\\000\\012loadFactorI\\000\\011thresholdxp?@\\000\\000\\000\\000\\000\\014w\\010\\000\\000\\000\\020\\000\\000\\000\\001t\\000\\015JOB_PARAM_KEYsr\\0002com.thing.quartz.timetask.entity.ScheduleJobEntity\\000\\000\\000\\000\\000\\000\\000\\001\\002\\000\\005L\\000\\010beanNamet\\000\\022Ljava/lang/String;L\\000\\016cronExpressionq\\000~\\000\\011L\\000\\006paramsq\\000~\\000\\011L\\000\\006remarkq\\000~\\000\\011L\\000\\006statust\\000\\023Ljava/lang/Integer;xr\\000*com.thing.common.orm.entity.BaseDateEntity\\025Q\\000\\257\\341\\177a\\350\\002\\000\\005L\\000\\012createDatet\\000\\020Ljava/lang/Long;L\\000\\007creatorq\\000~\\000\\014L\\000\\002idq\\000~\\000\\014L\\000\\012updateDateq\\000~\\000\\014L\\000\\007updaterq\\000~\\000\\014xpsr\\000\\016java.lang.Long;\\213\\344\\220\\314\\217#\\337\\002\\000\\001J\\000\\005valuexr\\000\\020java.lang.Number\\206\\254\\225\\035\\013\\224\\340\\213\\002\\000\\000xp\\000\\000\\001\\221\\351\\377\\254\\\\sq\\000~\\000\\016\\016\\317\\237a\\007\\264V\\001sq\\000~\\000\\016\\002\\252j''_\\002\\000\\000q\\000~\\000\\020q\\000~\\000\\021t\\000\\010CalcTaskt\\000\\0170 0/1 * * * ? *t\\000\\000t\\000\\011\\347\\211\\251\\350\\256\\241\\347\\256\\227sr\\000\\021java.lang.Integer\\022\\342\\240\\244\\367\\201\\2078\\002\\000\\001I\\000\\005valuexq\\000~\\000\\017\\000\\000\\000\\001x\\000');
INSERT INTO "public"."qrtz_job_details" VALUES ('ThingScheduler', 'TASK_192082754584838144', 'DEFAULT', NULL, 'com.thing.quartz.timetask.utils.ScheduleJob', 'f', 'f', 'f', 'f', E'\\254\\355\\000\\005sr\\000\\025org.quartz.JobDataMap\\237\\260\\203\\350\\277\\251\\260\\313\\002\\000\\000xr\\000&org.quartz.utils.StringKeyDirtyFlagMap\\202\\010\\350\\303\\373\\305](\\002\\000\\001Z\\000\\023allowsTransientDataxr\\000\\035org.quartz.utils.DirtyFlagMap\\023\\346.\\255(v\\012\\316\\002\\000\\002Z\\000\\005dirtyL\\000\\003mapt\\000\\017Ljava/util/Map;xp\\001sr\\000\\021java.util.HashMap\\005\\007\\332\\301\\303\\026`\\321\\003\\000\\002F\\000\\012loadFactorI\\000\\011thresholdxp?@\\000\\000\\000\\000\\000\\014w\\010\\000\\000\\000\\020\\000\\000\\000\\001t\\000\\015JOB_PARAM_KEYsr\\0002com.thing.quartz.timetask.entity.ScheduleJobEntity\\000\\000\\000\\000\\000\\000\\000\\001\\002\\000\\005L\\000\\010beanNamet\\000\\022Ljava/lang/String;L\\000\\016cronExpressionq\\000~\\000\\011L\\000\\006paramsq\\000~\\000\\011L\\000\\006remarkq\\000~\\000\\011L\\000\\006statust\\000\\023Ljava/lang/Integer;xr\\000*com.thing.common.orm.entity.BaseDateEntity\\025Q\\000\\257\\341\\177a\\350\\002\\000\\005L\\000\\012createDatet\\000\\020Ljava/lang/Long;L\\000\\007creatorq\\000~\\000\\014L\\000\\002idq\\000~\\000\\014L\\000\\012updateDateq\\000~\\000\\014L\\000\\007updaterq\\000~\\000\\014xpsr\\000\\016java.lang.Long;\\213\\344\\220\\314\\217#\\337\\002\\000\\001J\\000\\005valuexr\\000\\020java.lang.Number\\206\\254\\225\\035\\013\\224\\340\\213\\002\\000\\000xp\\000\\000\\001\\221\\352\\000\\014jsq\\000~\\000\\016\\016\\317\\237a\\007\\264V\\001sq\\000~\\000\\016\\002\\252j?b\\202\\000\\000q\\000~\\000\\020q\\000~\\000\\021t\\000\\017ThingStatusTaskt\\000\\0160 0/10 * * * ?t\\000\\000t\\000\\017\\350\\256\\276\\345\\244\\207\\345\\234\\250\\347\\246\\273\\347\\272\\277sr\\000\\021java.lang.Integer\\022\\342\\240\\244\\367\\201\\2078\\002\\000\\001I\\000\\005valuexq\\000~\\000\\017\\000\\000\\000\\001x\\000');
INSERT INTO "public"."qrtz_locks" VALUES ('ThingScheduler', 'STATE_ACCESS');
INSERT INTO "public"."qrtz_locks" VALUES ('ThingScheduler', 'TRIGGER_ACCESS');
INSERT INTO "public"."qrtz_scheduler_state" VALUES ('ThingScheduler', 'pro-tb31726133564891', 1726210701477, 15000);
INSERT INTO "public"."qrtz_triggers" VALUES ('ThingScheduler', 'TASK_192082754584838144', 'DEFAULT', 'TASK_192082754584838144', 'DEFAULT', NULL, 1726210800000, 1726210200000, 5, 'WAITING', 'CRON', 1726207757000, 0, NULL, 2, '');
INSERT INTO "public"."qrtz_triggers" VALUES ('ThingScheduler', 'TASK_192082542600519680', 'DEFAULT', 'TASK_192082542600519680', 'DEFAULT', NULL, 1726210860000, 1726210560000, 5, 'WAITING', 'CRON', 1726207706000, 0, NULL, 2, '');
INSERT INTO "public"."qrtz_triggers" VALUES ('ThingScheduler', 'TASK_192082651446902784', 'DEFAULT', 'TASK_192082651446902784', 'DEFAULT', NULL, 1726210740000, 1726210680000, 5, 'WAITING', 'CRON', 1726207732000, 0, NULL, 2, '');

2
modules/equipment/src/main/java/com/thing/eq/eqmanager/service/impl/IotThingsServiceImpl.java

@ -195,7 +195,7 @@ public class IotThingsServiceImpl implements IotThingsService {
//保存设备的关系
List<IotThingRelationDetailDTO> relationDetailDTOS =
iotThingRelationDetailService.findRootDetailChildNodeByRootIdAndFromIdAndRootThingId(dto.getRelationTypeId(), parentThing.getId(), dto.getRelationTopId());
iotThingRelationDetailService.findRootDetailChildNodeByRootIdAndToIdAndRootThingId(dto.getRelationTypeId(), parentThing.getId(), dto.getRelationTopId());
IotThingRelationDetailParamDTO relationDTO = new IotThingRelationDetailParamDTO();
relationDTO.setRootId(dto.getRelationTypeId());

43
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/controller/EnergyLossController.java

@ -0,0 +1,43 @@
package com.thing.carbon.energyloss.controller;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import com.thing.carbon.energyloss.service.EnergyLossService;
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.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping("energy/loss")
@Tag(name="能源损耗")
@RequiredArgsConstructor
public class EnergyLossController {
@Autowired
private EnergyLossService energyLossService;
@PostMapping("report")
@Operation(summary="能源损耗报表")
public Result<List<EnergyLossDTO>> energyLossReport(@RequestBody EnergyLossReportParam param) {
List<EnergyLossDTO> list = energyLossService.energyLossReport(param);
return new Result<List<EnergyLossDTO>>().ok(list);
}
@PostMapping("export")
@Operation(summary="能源损耗报表导出")
public void energyLossReport(@RequestBody EnergyLossReportParam param, HttpServletResponse response){
List<EnergyLossExcel> list = energyLossService.getEnergyLossList(param);
ExcelUtils.exportExcel1(list, null, "能源损耗报表", EnergyLossExcel.class, "能源损耗报表.xls", response);
}
}

35
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossDTO.java

@ -0,0 +1,35 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "损耗报表数据")
public class EnergyLossDTO {
@Schema(description = "能源节点")
private String thingName;
@Schema(description = "能源code")
private String thingCode;
@Schema(description = "当前支路能耗")
private BigDecimal currentValue;
@Schema(description = "下级支路能耗合计")
private BigDecimal lastValue;
@Schema(description = "差值")
private BigDecimal differenceValue;
@Schema(description = "相差百分比")
private BigDecimal percentValue;
@Schema(description = "子项")
private List<EnergyLossDTO> childs;
}

31
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossInfoDTO.java

@ -0,0 +1,31 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "损耗报表数据1")
public class EnergyLossInfoDTO {
@Schema(description = "能源节点")
private String thingName;
@Schema(description = "能源code")
private String thingCode;
@Schema(description = "当前支路能耗")
private BigDecimal currentValue;
@Schema(description = "下级支路能耗合计")
private BigDecimal lastValue;
@Schema(description = "差值")
private BigDecimal differenceValue;
@Schema(description = "相差百分比")
private BigDecimal percentValue;
}

37
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/EnergyLossReportParam.java

@ -0,0 +1,37 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
@Data
@Schema( name= "能源损耗入参")
public class EnergyLossReportParam implements Serializable {
@Serial
private static final long serialVersionUID = -8868412528182030308L;
@Schema(description = "开始时间")
private String beginTime;
@Schema(description = "结束时间")
private String endTime;
@Schema(description = "标签组名称")
private String labelGroupName;
@NotNull(message = "根主键不能为空", groups = Default.class)
@Schema(description = "根主键")
private Long rootId;
@Schema(description = "物属性code类型(hh mm yy),分别对应日月年")
private String thingAttrCodeType;
@Schema(description = "配置类型 例如:监控分析配置,用量分析配置")
private String configType;
}

21
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/KeyAndCodeDTO.java

@ -0,0 +1,21 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
@Data
@Schema( name= "属性和物code")
public class KeyAndCodeDTO {
@Schema(description = "属性key")
private String key;
@Schema(description = "物code")
private String code;
}

19
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/dto/NameAndCodeDTO.java

@ -0,0 +1,19 @@
package com.thing.carbon.energyloss.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema( name= "物名称和物code")
public class NameAndCodeDTO {
@Schema(description = "物名称")
private String name;
@Schema(description = "物code")
private String code;
@Schema(description = "物id")
private Long thingId;
}

33
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/excel/EnergyLossExcel.java

@ -0,0 +1,33 @@
package com.thing.carbon.energyloss.excel;
import cn.afterturn.easypoi.excel.annotation.Excel;
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;
import java.math.BigDecimal;
@Data
public class EnergyLossExcel {
@Excel(name = "能源节点", orderNum = "1", width = 30)
private String thingName;
// @Excel(name = "能源code", orderNum = "1")
// private String thingCode;
@Excel(name = "当前支路能耗", orderNum = "2", width = 30)
private BigDecimal currentValue;
@Excel(name = "下级支路能耗合计", orderNum = "3", width = 30)
private BigDecimal lastValue;
@Excel(name = "差值", orderNum = "4", width = 30)
private BigDecimal differenceValue;
@Excel(name = "相差百分比(%)", orderNum = "5", width = 30)
private BigDecimal percentValue;
}

15
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/EnergyLossService.java

@ -0,0 +1,15 @@
package com.thing.carbon.energyloss.service;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossInfoDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import java.util.List;
public interface EnergyLossService {
List<EnergyLossDTO> energyLossReport(EnergyLossReportParam param);
List<EnergyLossExcel> getEnergyLossList(EnergyLossReportParam param);
}

245
modules/report-analysis/src/main/java/com/thing/carbon/energyloss/service/impl/EnergyLossServiceImpl.java

@ -0,0 +1,245 @@
package com.thing.carbon.energyloss.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.mybatisflex.core.query.QueryWrapper;
import com.thing.carbon.energyloss.dto.EnergyLossDTO;
import com.thing.carbon.energyloss.dto.EnergyLossReportParam;
import com.thing.carbon.energyloss.excel.EnergyLossExcel;
import com.thing.carbon.energyloss.service.EnergyLossService;
import com.thing.common.core.utils.DateTimeUtils;
import com.thing.common.data.tskv.TsKvDTO;
import com.thing.common.tskv.service.TsKvService;
import com.thing.device.source.entity.IotThingSourceEntity;
import com.thing.device.source.mapper.IotThingSourceMapper;
import com.thing.thing.context.service.ThingManageContextService;
import com.thing.thing.relation.detail.dto.IotThingRelationDetailDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@RequiredArgsConstructor
public class EnergyLossServiceImpl implements EnergyLossService {
@Autowired
private ThingManageContextService thingManageContextService;
@Autowired
private TsKvService tsKvService;
@Resource
private IotThingSourceMapper iotThingSourceDao;
@Override
public List<EnergyLossDTO> energyLossReport(EnergyLossReportParam param) {
List<EnergyLossDTO> result = new ArrayList<>();
String beginTime = param.getBeginTime();
String endTime = param.getEndTime();
Long beginTs = DateTimeUtils.dateToStamp(beginTime);
Long endTs = DateTimeUtils.dateToStamp(endTime);
Long rootId = param.getRootId();
String labelGroupName = param.getLabelGroupName();
if (rootId==null){
return result;
}
//根据rootId获取该结构下所有的物
Optional<List<IotThingRelationDetailDTO>> relationDetailDTOS = thingManageContextService.findRootDetailAllByRootId(rootId);
List<IotThingRelationDetailDTO> relations = relationDetailDTOS.orElseGet(Collections::emptyList).stream().toList();
if (CollectionUtil.isEmpty(relations)){
return result;
}
List<String> codes = relationDetailDTOS.orElseGet(Collections::emptyList).stream().map(IotThingRelationDetailDTO::getToCode).toList();
Map<String, Collection<String>> multiMap = new HashMap<>();
//根据物code和标签组名称遍历查询对应配置的属性key
if (CollectionUtil.isNotEmpty(codes)){
for (String code:codes){
List<IotThingSourceEntity> iotThingSourceEntities = iotThingSourceDao.selectListExt(QueryWrapper.create()
.eq(IotThingSourceEntity::getThingCode, code)
.eq(IotThingSourceEntity::getRootId, rootId)
.eq(IotThingSourceEntity::getConfigType, param.getConfigType())
.eq(IotThingSourceEntity::getThingAttrGroup,labelGroupName)
.eq(IotThingSourceEntity::getStartStatus,"0"));
String key=null;
if (CollectionUtil.isNotEmpty(iotThingSourceEntities)){
key = iotThingSourceEntities.get(0).getThingAttrCode();
}
List<String> keys = new ArrayList<>();
keys.add(key);
if (StringUtils.isNotBlank(key)){
multiMap.put(code,keys);
}
}
}
//获取物 对应时间的能耗值
Map<String, BigDecimal> codeAndValueMap = new HashMap<>();
List<TsKvDTO> dataList = tsKvService.findTsKvByMultiMap(multiMap, beginTs, endTs, Boolean.FALSE);
if (CollectionUtil.isNotEmpty(dataList)){
codeAndValueMap = dataList.stream()
.filter(dto -> dto.getVal() != null && !dto.getVal().isEmpty())
.collect(Collectors.groupingBy(
TsKvDTO::getThingCode,
Collectors.mapping(
dto -> new BigDecimal(dto.getVal()),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
//处理结构,根据fromId分组并排序
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap = relations.stream()
.collect(Collectors.groupingBy(IotThingRelationDetailDTO::getFromId));
fromIdMap.forEach((fromId, list) ->
list.sort(Comparator.comparing(IotThingRelationDetailDTO::getSort))
);
//组装数据并赋值
result = buildEnergyLossDTOListRecursive(fromIdMap, rootId,codeAndValueMap);
return result;
}
@Override
public List<EnergyLossExcel> getEnergyLossList(EnergyLossReportParam param) {
List<EnergyLossExcel> result = new ArrayList<>();
List<EnergyLossDTO> result1;
String beginTime = param.getBeginTime();
String endTime = param.getEndTime();
Long beginTs = DateTimeUtils.dateToStamp(beginTime);
Long endTs = DateTimeUtils.dateToStamp(endTime);
Long rootId = param.getRootId();
String labelGroupName = param.getLabelGroupName();
if (rootId==null){
return result;
}
//根据rootId获取该结构下所有的物
Optional<List<IotThingRelationDetailDTO>> relationDetailDTOS = thingManageContextService.findRootDetailAllByRootId(rootId);
List<IotThingRelationDetailDTO> relations = relationDetailDTOS.orElseGet(Collections::emptyList).stream().toList();
if (CollectionUtil.isEmpty(relations)){
return result;
}
List<String> codes = relationDetailDTOS.orElseGet(Collections::emptyList).stream().map(IotThingRelationDetailDTO::getToCode).toList();
Map<String, Collection<String>> multiMap = new HashMap<>();
//根据物code和标签组名称遍历查询对应配置的属性key
if (CollectionUtil.isNotEmpty(codes)){
for (String code:codes){
List<IotThingSourceEntity> iotThingSourceEntities = iotThingSourceDao.selectListExt(QueryWrapper.create()
.eq(IotThingSourceEntity::getThingCode, code)
.eq(IotThingSourceEntity::getRootId, rootId)
.eq(IotThingSourceEntity::getConfigType, param.getConfigType())
.eq(IotThingSourceEntity::getThingAttrGroup,labelGroupName)
.eq(IotThingSourceEntity::getStartStatus,"0"));
String key=null;
if (CollectionUtil.isNotEmpty(iotThingSourceEntities)){
key = iotThingSourceEntities.get(0).getThingAttrCode();
}
List<String> keys = new ArrayList<>();
keys.add(key);
if (StringUtils.isNotBlank(key)){
multiMap.put(code,keys);
}
}
}
//获取物 对应时间的能耗值
Map<String, BigDecimal> codeAndValueMap = new HashMap<>();
List<TsKvDTO> dataList = tsKvService.findTsKvByMultiMap(multiMap, beginTs, endTs, Boolean.FALSE);
if (CollectionUtil.isNotEmpty(dataList)){
codeAndValueMap = dataList.stream()
.filter(dto -> dto.getVal() != null && !dto.getVal().isEmpty())
.collect(Collectors.groupingBy(
TsKvDTO::getThingCode,
Collectors.mapping(
dto -> new BigDecimal(dto.getVal()),
Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))));
}
//处理结构,根据fromId分组并排序
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap = relations.stream()
.collect(Collectors.groupingBy(IotThingRelationDetailDTO::getFromId));
fromIdMap.forEach((fromId, list) ->
list.sort(Comparator.comparing(IotThingRelationDetailDTO::getSort))
);
//组装数据并赋值
result1 = buildEnergyLossDTOListRecursive(fromIdMap, rootId,codeAndValueMap);
int depth=0;
processWithHierarchy(result,result1,depth);
return result;
}
private String getIndentedName(String name, int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++) {
sb.append(" "); // Four spaces for each level of indentation
}
sb.append(name);
return sb.toString();
}
private EnergyLossExcel convertToEnergyLossInfoDTO(EnergyLossDTO energyLossDTO,int depth) {
if (energyLossDTO == null) {
return null;
}
EnergyLossExcel energyLossInfoDTO = new EnergyLossExcel();
energyLossInfoDTO.setThingName(getIndentedName(energyLossDTO.getThingName(),depth));
// energyLossInfoDTO.setThingCode(energyLossDTO.getThingCode());
energyLossInfoDTO.setCurrentValue(energyLossDTO.getCurrentValue());
energyLossInfoDTO.setLastValue(energyLossDTO.getLastValue());
energyLossInfoDTO.setDifferenceValue(energyLossDTO.getDifferenceValue());
energyLossInfoDTO.setPercentValue(energyLossDTO.getPercentValue());
return energyLossInfoDTO;
}
public List<EnergyLossExcel> processWithHierarchy(List<EnergyLossExcel> result,List<EnergyLossDTO> energyLossDTOList,int depth) {
for (EnergyLossDTO dto : energyLossDTOList) {
EnergyLossExcel infoDTO = convertToEnergyLossInfoDTO(dto,depth);
result.add(infoDTO);
// Recursively process child items
if (dto.getChilds() != null) {
processWithHierarchy(result,dto.getChilds(),depth + 1);
}
}
return result;
}
private List<EnergyLossDTO> buildEnergyLossDTOListRecursive(
Map<Long, List<IotThingRelationDetailDTO>> fromIdMap,
Long rootId,Map<String, BigDecimal> codeAndValueMap) {
List<IotThingRelationDetailDTO> childDataList = fromIdMap.getOrDefault(rootId, Collections.emptyList());
List<EnergyLossDTO> dtos = new ArrayList<>();
for (IotThingRelationDetailDTO data : childDataList) {
EnergyLossDTO dto = new EnergyLossDTO();
dto.setThingName(data.getToName());
dto.setThingCode(data.getToCode());
BigDecimal currentValue = codeAndValueMap.getOrDefault(data.getToCode(), BigDecimal.ZERO);
dto.setCurrentValue(currentValue);
List<EnergyLossDTO> children = buildEnergyLossDTOListRecursive(fromIdMap,data.getToId(),codeAndValueMap);
dto.setChilds(children);
BigDecimal lastValue = children.stream()
.map(EnergyLossDTO::getCurrentValue)
.reduce(BigDecimal.ZERO, BigDecimal::add);
dto.setLastValue(lastValue);
BigDecimal differenceValue = currentValue.subtract(lastValue);
BigDecimal percentValue = currentValue.compareTo(BigDecimal.ZERO) == 0
? BigDecimal.ZERO
: differenceValue.divide(currentValue, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
dto.setDifferenceValue(differenceValue);
dto.setPercentValue(percentValue);
dtos.add(dto);
}
return dtos;
}
}

1
modules/thing/src/main/java/com/thing/thing/entity/service/impl/IotThingEntityServiceImpl.java

@ -689,6 +689,7 @@ public class IotThingEntityServiceImpl extends BaseServiceImpl<IotThingEntityMap
.setAuthNum(1L)
.setStatusTs(DateTimeUtils.getCurrentTime())
.setOrigin(QueueOriginType.MQTT_CLIENT.name())
.setRealType(data.getRealType())
.setToken(TokenGenerator.generateValue())).toList();
if(CollectionUtils.isNotEmpty(modelEntities)){
modelService.saveOrUpdateBatch(modelEntities);

1
modules/thing/src/main/java/com/thing/thing/relation/detail/service/IotThingRelationDetailService.java

@ -75,4 +75,5 @@ public interface IotThingRelationDetailService extends IBaseService<IotThingRela
void saveRelationNodes(ThingRelationDTO relationDTO);
List<IotThingRelationDetailDTO> findRootDetailChildNodeByRootIdAndToIdAndRootThingId(Long relationTypeId, Long id, Long relationTopId);
}

9
modules/thing/src/main/java/com/thing/thing/relation/detail/service/impl/IotThingRelationDetailServiceImpl.java

@ -708,6 +708,15 @@ public class IotThingRelationDetailServiceImpl extends BaseServiceImpl<IotThingR
, IotThingRelationDetailDTO.class);
}
@Override
public List<IotThingRelationDetailDTO> findRootDetailChildNodeByRootIdAndToIdAndRootThingId(Long rootId, Long toId, Long rootThingId) {
return mapper.selectListByQueryAs(QueryWrapper.create()
.eq(IotThingRelationDetailEntity::getRootId, rootId)
.eq(IotThingRelationDetailEntity::getToId, toId)
.eq(IotThingRelationDetailEntity::getRootThingId, rootThingId, ObjectUtil.isNotNull(rootThingId))
, IotThingRelationDetailDTO.class);
}
@Override
public IotThingRelationDetailDTO findRootDetailParentNodeByRootIdAndToIdAndRootThingId(Long rootId, Long toId, Long rootThingId) {
return mapper.selectOneByQueryAs(QueryWrapper.create()

Loading…
Cancel
Save