|
|
@ -2,6 +2,7 @@ package com.thing.calculation.service.impl; |
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
import cn.hutool.core.util.ObjectUtil; |
|
|
|
|
|
import com.google.common.collect.Lists; |
|
|
import com.mybatisflex.core.query.QueryWrapper; |
|
|
import com.mybatisflex.core.query.QueryWrapper; |
|
|
import com.thing.calculation.dto.*; |
|
|
import com.thing.calculation.dto.*; |
|
|
import com.thing.calculation.entity.CalcSourceConfigEntity; |
|
|
import com.thing.calculation.entity.CalcSourceConfigEntity; |
|
|
@ -23,22 +24,28 @@ import com.thing.common.core.utils.DateTimeUtils; |
|
|
import com.thing.common.core.utils.FormulaUtil; |
|
|
import com.thing.common.core.utils.FormulaUtil; |
|
|
import com.thing.common.core.utils.excel.ExcelUtils; |
|
|
import com.thing.common.core.utils.excel.ExcelUtils; |
|
|
import com.thing.common.core.web.response.PageData; |
|
|
import com.thing.common.core.web.response.PageData; |
|
|
|
|
|
import com.thing.common.data.event.QueueConsumerEvent; |
|
|
|
|
|
import com.thing.common.data.proto.QueueProto; |
|
|
import com.thing.common.data.tskv.TsKvDTO; |
|
|
import com.thing.common.data.tskv.TsKvDTO; |
|
|
import com.thing.common.orm.service.impl.BaseServiceImpl; |
|
|
import com.thing.common.orm.service.impl.BaseServiceImpl; |
|
|
import com.thing.common.orm.utils.IdGenerator; |
|
|
import com.thing.common.orm.utils.IdGenerator; |
|
|
import com.thing.common.tskv.service.TsKvService; |
|
|
import com.thing.common.tskv.service.TsKvService; |
|
|
|
|
|
import com.thing.queue.util.Topics; |
|
|
import com.thing.sys.security.context.UserContext; |
|
|
import com.thing.sys.security.context.UserContext; |
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
import jakarta.servlet.http.HttpServletResponse; |
|
|
import lombok.RequiredArgsConstructor; |
|
|
import lombok.RequiredArgsConstructor; |
|
|
import org.apache.commons.collections4.MapUtils; |
|
|
import org.apache.commons.collections4.MapUtils; |
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
|
|
import org.jetbrains.annotations.NotNull; |
|
|
import org.springframework.cache.annotation.CacheEvict; |
|
|
import org.springframework.cache.annotation.CacheEvict; |
|
|
import org.springframework.cache.annotation.Cacheable; |
|
|
import org.springframework.cache.annotation.Cacheable; |
|
|
|
|
|
import org.springframework.context.ApplicationEventPublisher; |
|
|
import org.springframework.stereotype.Service; |
|
|
import org.springframework.stereotype.Service; |
|
|
import org.springframework.util.CollectionUtils; |
|
|
import org.springframework.util.CollectionUtils; |
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
|
|
|
|
|
import java.math.BigDecimal; |
|
|
import java.math.BigDecimal; |
|
|
|
|
|
import java.math.RoundingMode; |
|
|
import java.util.*; |
|
|
import java.util.*; |
|
|
import java.util.function.Consumer; |
|
|
import java.util.function.Consumer; |
|
|
import java.util.function.Function; |
|
|
import java.util.function.Function; |
|
|
@ -64,6 +71,7 @@ public class CalcTargetConfigServiceImpl |
|
|
private final CalcExecuteHandler calcExecuteHandler; |
|
|
private final CalcExecuteHandler calcExecuteHandler; |
|
|
private final CalcLogSaveHandler calcLogSaveHandler; |
|
|
private final CalcLogSaveHandler calcLogSaveHandler; |
|
|
private final CalcSourceConfigService calcSourceConfigService; |
|
|
private final CalcSourceConfigService calcSourceConfigService; |
|
|
|
|
|
private final ApplicationEventPublisher publisher; |
|
|
|
|
|
|
|
|
/** 变量池:A ~ Z */ |
|
|
/** 变量池:A ~ Z */ |
|
|
// private static final List<String> variablePool = new ArrayList<>(); |
|
|
// private static final List<String> variablePool = new ArrayList<>(); |
|
|
@ -380,7 +388,33 @@ public class CalcTargetConfigServiceImpl |
|
|
List<Long> ids = request.getCalcTargetConfigIds(); |
|
|
List<Long> ids = request.getCalcTargetConfigIds(); |
|
|
List<CalcTargetConfigDTO> configList = getListByIdsAs(ids, CalcTargetConfigDTO.class); |
|
|
List<CalcTargetConfigDTO> configList = getListByIdsAs(ids, CalcTargetConfigDTO.class); |
|
|
fillData(configList); |
|
|
fillData(configList); |
|
|
List<CalcSourceConfigDTO> sourceConfigs = |
|
|
|
|
|
|
|
|
Long startTime = DateTimeUtils.convertTimeToLong(request.getStartTime()); |
|
|
|
|
|
Long endTime = DateTimeUtils.convertTimeToLong(request.getEndTime()); |
|
|
|
|
|
//开始====================================================== |
|
|
|
|
|
List<QueueProto.DataProto> protoList = new ArrayList<>(); |
|
|
|
|
|
for (CalcTargetConfigDTO config : configList) { |
|
|
|
|
|
List<CalcSourceConfigDTO> sourceConfigs = config.getSourceConfigs(); |
|
|
|
|
|
//转换入参 |
|
|
|
|
|
Map<String, Collection<String>> multiMap = convertParam(sourceConfigs); |
|
|
|
|
|
//查询计算目标的最新值 |
|
|
|
|
|
List<TsKvDTO> tsKvByMultiMap = tsKvService.findTsKvByMultiMap(multiMap, startTime, endTime, true); |
|
|
|
|
|
if(CollectionUtil.isEmpty(tsKvByMultiMap)){ |
|
|
|
|
|
//若是source tskv值是空的,则跳过 |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
getCalResult(config, tsKvByMultiMap, protoList, sourceConfigs); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(CollectionUtil.isEmpty(protoList)){ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
List<QueueProto.DataProto> list = protoList.stream().sorted(Comparator.comparing(s -> s.getTskvProto().getTs())).toList(); |
|
|
|
|
|
// 批量推送 |
|
|
|
|
|
publisher.publishEvent( |
|
|
|
|
|
new QueueConsumerEvent(Topics.V1_TSKV_CALC_LOG_CAL.getValue(), list)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* List<CalcSourceConfigDTO> sourceConfigs = |
|
|
configList.stream() |
|
|
configList.stream() |
|
|
.map(CalcTargetConfigDTO::getSourceConfigs) |
|
|
.map(CalcTargetConfigDTO::getSourceConfigs) |
|
|
.filter(Objects::nonNull) |
|
|
.filter(Objects::nonNull) |
|
|
@ -403,7 +437,69 @@ public class CalcTargetConfigServiceImpl |
|
|
calcLogSaveHandler.handleLogSave(tskvList, configList, true); |
|
|
calcLogSaveHandler.handleLogSave(tskvList, configList, true); |
|
|
|
|
|
|
|
|
// 立即执行计算 |
|
|
// 立即执行计算 |
|
|
calcExecuteHandler.handleCalculate(new ExecuteCalcRequest(request.getStartTime(), request.getEndTime()),ids); |
|
|
|
|
|
|
|
|
calcExecuteHandler.handleCalculate(new ExecuteCalcRequest(request.getStartTime(), request.getEndTime()),ids);*/ |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void getCalResult(CalcTargetConfigDTO config, List<TsKvDTO> tsKvByMultiMap, List<QueueProto.DataProto> protoList, List<CalcSourceConfigDTO> sourceConfigs) { |
|
|
|
|
|
//若有source tskv值,则计算结果 |
|
|
|
|
|
Map<Long, List<TsKvDTO>> tsMap = tsKvByMultiMap.stream().collect(Collectors.groupingBy(TsKvDTO::getTs)); |
|
|
|
|
|
for (Map.Entry<Long, List<TsKvDTO>> entry : tsMap.entrySet()) { |
|
|
|
|
|
if(config.getConfigType().equals(CalcConfigType.DATA_MAPPING.getCode()) || config.getConfigType().equals(CalcConfigType.AGG_MAPPING.getCode())){ |
|
|
|
|
|
//直接计算结果 |
|
|
|
|
|
BigDecimal totalVal = |
|
|
|
|
|
entry.getValue().stream() |
|
|
|
|
|
.map(s-> new BigDecimal(s.getVal())) |
|
|
|
|
|
.reduce(BigDecimal.ZERO, BigDecimal::add).setScale(4, RoundingMode.HALF_UP); |
|
|
|
|
|
QueueProto.TsKvProto tsKvProto = |
|
|
|
|
|
QueueProto.TsKvProto.newBuilder() |
|
|
|
|
|
.setThingCode(config.getTargetThingCode()) |
|
|
|
|
|
.setKey(config.getTargetAttrCode()) |
|
|
|
|
|
.setTs(entry.getKey()) |
|
|
|
|
|
.setVal(totalVal.toPlainString()) |
|
|
|
|
|
.build(); |
|
|
|
|
|
protoList.add( |
|
|
|
|
|
QueueProto.DataProto.newBuilder().setTskvProto(tsKvProto).build()); |
|
|
|
|
|
}else{ |
|
|
|
|
|
//公式计算 |
|
|
|
|
|
Map<String, Object> variableMap = new HashMap<>(); |
|
|
|
|
|
for (CalcSourceConfigDTO sourceConfig : sourceConfigs) { |
|
|
|
|
|
TsKvDTO tsKvDTO = entry.getValue().stream().filter(s -> s.getThingCode().equals(sourceConfig.getSourceThingCode()) |
|
|
|
|
|
&& s.getAttrKey().equals(sourceConfig.getSourceAttrCode())).findFirst().orElse(null); |
|
|
|
|
|
if(!Objects.isNull(tsKvDTO)){ |
|
|
|
|
|
variableMap.put(sourceConfig.getSourceAttrAlias(), new BigDecimal(tsKvDTO.getVal())); |
|
|
|
|
|
}else{ |
|
|
|
|
|
variableMap.put(sourceConfig.getSourceAttrAlias(), BigDecimal.ZERO); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
Object result = FormulaUtil.executeFormula(config.getFormula(), variableMap); |
|
|
|
|
|
QueueProto.TsKvProto tsKvProto = |
|
|
|
|
|
QueueProto.TsKvProto.newBuilder() |
|
|
|
|
|
.setThingCode(config.getTargetThingCode()) |
|
|
|
|
|
.setKey(config.getTargetAttrCode()) |
|
|
|
|
|
.setTs(entry.getKey()) |
|
|
|
|
|
.setVal(new BigDecimal(result.toString()).setScale(4, RoundingMode.HALF_UP).toPlainString()) |
|
|
|
|
|
.build(); |
|
|
|
|
|
protoList.add( |
|
|
|
|
|
QueueProto.DataProto.newBuilder().setTskvProto(tsKvProto).build()); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@NotNull |
|
|
|
|
|
private static Map<String, Collection<String>> convertParam(List<CalcSourceConfigDTO> sourceConfigs) { |
|
|
|
|
|
//将sourceConfigs 转换入参 |
|
|
|
|
|
Map<String, Collection<String>> multiMap = new HashMap<>(); |
|
|
|
|
|
for (CalcSourceConfigDTO sourceConfig : sourceConfigs) { |
|
|
|
|
|
if(multiMap.containsKey(sourceConfig.getSourceThingCode())){ |
|
|
|
|
|
Collection<String> list = multiMap.get(sourceConfig.getSourceThingCode()); |
|
|
|
|
|
list.add(sourceConfig.getSourceAttrCode()); |
|
|
|
|
|
multiMap.put(sourceConfig.getSourceThingCode(), list); |
|
|
|
|
|
}else{ |
|
|
|
|
|
multiMap.put(sourceConfig.getSourceThingCode(), Lists.newArrayList(sourceConfig.getSourceAttrCode())); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return multiMap; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@Override |
|
|
@Override |
|
|
|