|
|
@@ -1,11 +1,33 @@
|
|
|
package com.jjt.dye.service.impl;
|
|
|
|
|
|
-import java.util.List;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-import com.jjt.dye.mapper.DyeCalcHourMapper;
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
+import com.jjt.common.utils.DateUtils;
|
|
|
import com.jjt.dye.domain.DyeCalcHour;
|
|
|
+import com.jjt.dye.domain.DyeDevicePara;
|
|
|
+import com.jjt.dye.domain.DyeTypePara;
|
|
|
+import com.jjt.dye.mapper.DyeCalcHourMapper;
|
|
|
import com.jjt.dye.service.IDyeCalcHourService;
|
|
|
+import com.jjt.dye.service.IDyeDeviceService;
|
|
|
+import com.jjt.dye.service.IDyeHourLineService;
|
|
|
+import com.jjt.dye.vo.DyeDeviceVO;
|
|
|
+import com.jjt.utils.IotService;
|
|
|
+import com.jjt.utils.Tools;
|
|
|
+import org.apache.ibatis.session.ExecutorType;
|
|
|
+import org.apache.ibatis.session.SqlSession;
|
|
|
+import org.apache.ibatis.session.SqlSessionFactory;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.LocalTime;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
|
|
|
/**
|
|
|
* 小时统计数据Service业务层处理
|
|
|
@@ -17,6 +39,14 @@ import javax.annotation.Resource;
|
|
|
public class DyeCalcHourServiceImpl implements IDyeCalcHourService {
|
|
|
@Resource
|
|
|
private DyeCalcHourMapper dyeCalcHourMapper;
|
|
|
+ @Resource
|
|
|
+ private IotService iotService;
|
|
|
+ @Resource
|
|
|
+ private SqlSessionFactory factory;
|
|
|
+ @Resource
|
|
|
+ private IDyeDeviceService dyeDeviceService;
|
|
|
+ @Resource
|
|
|
+ private IDyeHourLineService dyeHourLineService;
|
|
|
|
|
|
/**
|
|
|
* 查询小时统计数据
|
|
|
@@ -48,7 +78,7 @@ public class DyeCalcHourServiceImpl implements IDyeCalcHourService {
|
|
|
*/
|
|
|
@Override
|
|
|
public int insertDyeCalcHour(DyeCalcHour dyeCalcHour) {
|
|
|
- return dyeCalcHourMapper.insertDyeCalcHour(dyeCalcHour);
|
|
|
+ return dyeCalcHourMapper.insertDyeCalcHour(dyeCalcHour);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -83,4 +113,218 @@ public class DyeCalcHourServiceImpl implements IDyeCalcHourService {
|
|
|
public int deleteDyeCalcHourByChId(Long chId) {
|
|
|
return dyeCalcHourMapper.deleteDyeCalcHourByChId(chId);
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算上一小时数据
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void calcLastHour() {
|
|
|
+ LocalDateTime end = Tools.currWholeTime();
|
|
|
+ LocalDateTime start = end.minusHours(1);
|
|
|
+ calc(start.toLocalDate(), start.getHour());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算指定时间指定小时数据
|
|
|
+ *
|
|
|
+ * @param date 时间
|
|
|
+ * @param hour 小时
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void calc(LocalDate date, int hour) {
|
|
|
+ LocalDateTime start = LocalDateTime.of(date, LocalTime.MIN).plusHours(hour);
|
|
|
+ LocalDateTime end = start.plusHours(1);
|
|
|
+ dyeCalcHourMapper.deleteByHour(DateUtils.toDate(date), hour);
|
|
|
+ Map<String, List<DyeDeviceVO>> deviceByLine = dyeDeviceService.deviceByLine();
|
|
|
+ deviceByLine.forEach((line, devices) -> {
|
|
|
+ // 计算能源参数
|
|
|
+ calcCommon(start, end, devices,
|
|
|
+ (device, d) -> device.getEngParas(),
|
|
|
+ (exp, device) -> exp);
|
|
|
+
|
|
|
+ // 计算类型参数
|
|
|
+ calcCommon(start, end, devices,
|
|
|
+ (device, d) -> device.getTypeParas(),
|
|
|
+ (exp, device) -> exp.replace("${code}", device.getDeviceCode()));
|
|
|
+ });
|
|
|
+ dyeHourLineService.calc(date, hour);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询指定时间指定小时数据
|
|
|
+ *
|
|
|
+ * @param date 时间
|
|
|
+ * @param hour 小时
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<DyeCalcHour> selectByTime(LocalDate date, int hour) {
|
|
|
+ DyeCalcHour dyeCalcHour = new DyeCalcHour();
|
|
|
+ dyeCalcHour.setDataDate(DateUtils.toDate(date));
|
|
|
+ dyeCalcHour.setHour(hour);
|
|
|
+ return selectDyeCalcHourList(dyeCalcHour);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通用计算方法
|
|
|
+ *
|
|
|
+ * @param start 开始时间
|
|
|
+ * @param end 结束时间
|
|
|
+ * @param devices 设备列表
|
|
|
+ * @param parasSupplier 参数提供者函数
|
|
|
+ * @param expProcessor 表达式处理器
|
|
|
+ */
|
|
|
+ private void calcCommon(LocalDateTime start, LocalDateTime end, List<DyeDeviceVO> devices,
|
|
|
+ java.util.function.BiFunction<DyeDeviceVO, Object, List<?>> parasSupplier,
|
|
|
+ java.util.function.BiFunction<String, DyeDeviceVO, String> expProcessor) {
|
|
|
+ Map<String, DyeCalcHour> calcMap = new HashMap<>(16);
|
|
|
+ List<String> fields = new ArrayList<>();
|
|
|
+
|
|
|
+ devices.forEach(device -> {
|
|
|
+ List<?> paras = parasSupplier.apply(device, device);
|
|
|
+ if (paras != null) {
|
|
|
+ paras.forEach(para -> {
|
|
|
+ String key;
|
|
|
+ String paraCode;
|
|
|
+ String paraName;
|
|
|
+ String paraExp;
|
|
|
+ String remark = "";
|
|
|
+
|
|
|
+ // 根据参数类型获取相应属性
|
|
|
+ if (para instanceof DyeDevicePara) {
|
|
|
+ DyeDevicePara dyePara = (DyeDevicePara) para;
|
|
|
+ key = dyePara.getParaCode() + device.getDeviceId();
|
|
|
+ paraCode = dyePara.getParaCode();
|
|
|
+ paraName = dyePara.getParaName();
|
|
|
+ paraExp = dyePara.getParaExp();
|
|
|
+ } else if (para instanceof DyeTypePara) {
|
|
|
+ DyeTypePara typePara = (DyeTypePara) para;
|
|
|
+ key = typePara.getParaCode() + device.getDeviceId();
|
|
|
+ paraCode = typePara.getParaCode();
|
|
|
+ paraName = typePara.getParaName();
|
|
|
+ paraExp = typePara.getParaExp();
|
|
|
+ } else {
|
|
|
+ return; // 未知类型,跳过处理
|
|
|
+ }
|
|
|
+ if (paraCode.equals("P_uptime")) {
|
|
|
+ remark = "UPTIME";
|
|
|
+ } else {
|
|
|
+ if (paraExp.contains("AVG")) {
|
|
|
+ remark = "AVG";
|
|
|
+ } else if (paraExp.contains("SUM")) {
|
|
|
+ remark = "SUM";
|
|
|
+ } else if (paraExp.contains("MAX")) {
|
|
|
+ remark = "MAX";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ String processedExp = expProcessor.apply(paraExp, device);
|
|
|
+ String fieldExp = processedExp + " AS " + key;
|
|
|
+ fields.add(fieldExp);
|
|
|
+
|
|
|
+ DyeCalcHour calcHour = new DyeCalcHour();
|
|
|
+ calcHour.setDeviceId(device.getDeviceId());
|
|
|
+ calcHour.setDataDate(DateUtils.toDate(start.toLocalDate()));
|
|
|
+ calcHour.setHour(start.getHour());
|
|
|
+ calcHour.setParaCode(paraCode);
|
|
|
+ calcHour.setParaName(paraName);
|
|
|
+ calcHour.setRemark(remark);
|
|
|
+ calcMap.put(key, calcHour);
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ process(start, end, calcMap, fields);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void process(LocalDateTime start, LocalDateTime end, Map<String, DyeCalcHour> paraMap, List<String> paraFields) {
|
|
|
+ String sql = "select %s from root.tl.suxi group by ((%s,%s],1m)";
|
|
|
+ sql = String.format(sql, String.join(",", paraFields), DateUtils.parseIso(start), DateUtils.parseIso(end));
|
|
|
+ iotService.query(sql);
|
|
|
+ JSONObject jsonObject = iotService.query(sql);
|
|
|
+ JSONObject data = jsonObject.getJSONObject("data");
|
|
|
+ JSONArray values = data.getJSONArray("values");
|
|
|
+ JSONArray columnNames = data.getJSONArray("columnNames");
|
|
|
+ JSONArray timestamps = data.getJSONArray("timestamps");
|
|
|
+ if (values.size() > 0) {
|
|
|
+ for (int j = 0; j < values.size(); j++) {
|
|
|
+ JSONArray da = values.getJSONArray(j);
|
|
|
+ for (int i = 0; i < da.size(); i++) {
|
|
|
+ String field = columnNames.getStr(i);
|
|
|
+ long timestamp = timestamps.getLong(j);
|
|
|
+
|
|
|
+ if (da.getDouble(i) != null) {
|
|
|
+ Double v = da.getDouble(i);
|
|
|
+ DyeCalcHour calc = paraMap.get(field);
|
|
|
+ calc.setNum(da.size());
|
|
|
+ List<BigDecimal> mValues = calc.getMValues();
|
|
|
+ List<String> times = calc.getTimes();
|
|
|
+ if (mValues == null) {
|
|
|
+ mValues = new ArrayList<>();
|
|
|
+ }
|
|
|
+ if (times == null) {
|
|
|
+ times = new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将timestamp转换为LocalDateTime,然后提取分钟数作为字符串添加到times列表中
|
|
|
+ LocalDateTime dateTime = LocalDateTime.ofInstant(
|
|
|
+ java.time.Instant.ofEpochMilli(timestamp),
|
|
|
+ java.time.ZoneId.systemDefault());
|
|
|
+ times.add(String.valueOf(dateTime.getMinute()));
|
|
|
+
|
|
|
+ mValues.add(BigDecimal.valueOf(v).setScale(2, RoundingMode.HALF_UP));
|
|
|
+ calc.setMValues(mValues);
|
|
|
+ calc.setTimes(times);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ paraMap.forEach((k, v) -> {
|
|
|
+ if (v.getMValues() != null && !v.getMValues().isEmpty() && v.getTimes() != null) {
|
|
|
+ // 创建JSON对象来存储time和value的对应关系
|
|
|
+ JSONArray dataArray = new JSONArray();
|
|
|
+ List<BigDecimal> mValues = v.getMValues();
|
|
|
+ List<String> times = v.getTimes();
|
|
|
+
|
|
|
+ // 确保两个列表的大小相同
|
|
|
+ int size = Math.min(mValues.size(), times.size());
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ JSONObject dataObj = new JSONObject();
|
|
|
+ dataObj.set("time", times.get(i));
|
|
|
+ dataObj.set("value", mValues.get(i));
|
|
|
+ dataArray.add(dataObj);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将JSON数组转换为字符串并存储在paraMValue字段中
|
|
|
+ v.setParaMValue(dataArray.toString());
|
|
|
+
|
|
|
+ BigDecimal sum = v.getMValues().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ switch (v.getRemark()) {
|
|
|
+ case "AVG":
|
|
|
+ v.setParaValue(sum.divide(new BigDecimal(v.getMValues().size()), 2, RoundingMode.HALF_UP));
|
|
|
+ break;
|
|
|
+ case "SUM":
|
|
|
+ v.setParaValue(sum);
|
|
|
+ break;
|
|
|
+ case "MAX":
|
|
|
+ v.setParaValue(v.getMValues().stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO));
|
|
|
+ break;
|
|
|
+ case "UPTIME":
|
|
|
+ //针对稼动率专门处理
|
|
|
+ v.setParaValue(sum.divide(new BigDecimal(v.getNum()), 2, RoundingMode.HALF_UP));
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ List<DyeCalcHour> list = new ArrayList<>(paraMap.values());
|
|
|
+
|
|
|
+ try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {
|
|
|
+ if (list.size() > 0) {
|
|
|
+ DyeCalcHourMapper mapper = sqlSession.getMapper(DyeCalcHourMapper.class);
|
|
|
+ list.forEach(mapper::insertDyeCalcHour);
|
|
|
+ sqlSession.commit();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|