|
@@ -0,0 +1,224 @@
|
|
|
+package com.gyee.runeconomy.service.agc;
|
|
|
+
|
|
|
+
|
|
|
+import cn.hutool.core.lang.TypeReference;
|
|
|
+import com.gyee.runeconomy.config.GyeeConfig;
|
|
|
+import com.gyee.runeconomy.controller.agc.AgcDeviateTag;
|
|
|
+import com.gyee.runeconomy.controller.agc.AiPoints;
|
|
|
+import com.gyee.runeconomy.controller.agc.FileService;
|
|
|
+import com.gyee.runeconomy.init.CacheContext;
|
|
|
+import com.gyee.runeconomy.util.realtimesource.feign.IDataAdapter;
|
|
|
+import com.gyee.runeconomy.util.realtimesource.feign.RemoteServiceBuilder;
|
|
|
+import com.gyee.runeconomy.util.realtimesource.feign.TsDoubleTsData;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.boot.system.ApplicationHome;
|
|
|
+import org.springframework.core.annotation.Order;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.Arrays;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Optional;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 读取数据库配置文件
|
|
|
+ */
|
|
|
+@Order(0)
|
|
|
+@Component
|
|
|
+public class AgcDeviateService {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是离线版本
|
|
|
+ */
|
|
|
+ private boolean isOffline;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 离线数据保存路径
|
|
|
+ */
|
|
|
+ private String filePathPower = "data\\power\\";
|
|
|
+
|
|
|
+ public File jarF = null;
|
|
|
+
|
|
|
+ {
|
|
|
+ ApplicationHome h = new ApplicationHome(getClass());
|
|
|
+ jarF = h.getSource();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 文件读写
|
|
|
+ */
|
|
|
+ private FileService fileService;
|
|
|
+
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private GyeeConfig config;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private IDataAdapter iDataAdapter;
|
|
|
+ @Autowired
|
|
|
+ private RemoteServiceBuilder remoteService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取agc曲线偏差分析需要的数据
|
|
|
+ *
|
|
|
+ * @param id 场站ID
|
|
|
+ * @param startTs 开始时间戳
|
|
|
+ * @param endTs 结束时间戳
|
|
|
+ * @param interval 数据时间间隔
|
|
|
+ * @return 分析数据
|
|
|
+ */
|
|
|
+ public List<AgcDeviateTag> getAgcDeviateTags(String id, long startTs, long endTs, int interval) {
|
|
|
+ List<AgcDeviateTag> ladt = new ArrayList<>();
|
|
|
+ List<AiPoints> laps = getAiPoints(id);
|
|
|
+ if (laps == null) {
|
|
|
+ return ladt;
|
|
|
+ }
|
|
|
+ for (AiPoints ap : laps) {
|
|
|
+ AgcDeviateTag adt = new AgcDeviateTag();
|
|
|
+ adt.setName(ap.getName());
|
|
|
+ List<TsDoubleTsData> lpd = getPointData(ap, startTs, endTs, interval);
|
|
|
+ adt.setValues(lpd);
|
|
|
+ ladt.add(adt);
|
|
|
+ }
|
|
|
+ // 上限下限
|
|
|
+ List<AgcDeviateTag> upperLowerLimits = getUpperLowerLimits(ladt, id);
|
|
|
+ ladt.addAll(upperLowerLimits);
|
|
|
+ return ladt;
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<TsDoubleTsData> getPointData(AiPoints ap, long startTs, long endTs, int interval) {
|
|
|
+ List<TsDoubleTsData> lpds = null;
|
|
|
+ if (ap.getTag().contains(",")) {
|
|
|
+ lpds = getMultiple(ap, startTs, endTs, interval);
|
|
|
+ } else {
|
|
|
+
|
|
|
+
|
|
|
+ if (ap.getTag().startsWith("NEM")) {
|
|
|
+ lpds = remoteService.taos().getHistorytsSnap(ap.getTag(), startTs, endTs, interval);
|
|
|
+ } else {
|
|
|
+ lpds = remoteService.adapterfd().getHistorytsSnap(ap.getTag(), startTs, endTs, interval);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ if (ap.getMultiplier() != 1) {
|
|
|
+ for (TsDoubleTsData pd : lpds) {
|
|
|
+ pd.setDoubleValue(pd.getDoubleValue() * ap.getMultiplier());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return lpds;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取多个标签点数值
|
|
|
+ */
|
|
|
+ private List<TsDoubleTsData> getMultiple(AiPoints ap, long startTs, long endTs, int interval) {
|
|
|
+ String[] tags = ap.getTag().split(",");
|
|
|
+ boolean isFirst = true;
|
|
|
+ List<TsDoubleTsData> lpd = new ArrayList<>();
|
|
|
+ for (String tag : tags) {
|
|
|
+ if (tag.equals("")) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<TsDoubleTsData> vals = iDataAdapter.getHistorySnap(tag, startTs, endTs, interval);
|
|
|
+ for (int i = 0; i < vals.size(); ++i) {
|
|
|
+ if (isFirst) {
|
|
|
+ lpd.addAll(vals);
|
|
|
+ isFirst = false;
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ TsDoubleTsData pd = lpd.get(i);
|
|
|
+ pd.setDoubleValue(vals.get(i).getDoubleValue() + pd.getDoubleValue());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return lpd;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取上限下限
|
|
|
+ */
|
|
|
+ private List<AgcDeviateTag> getUpperLowerLimits(List<AgcDeviateTag> ladt, String id) {
|
|
|
+ // 装机容量
|
|
|
+ double capacity = getCapacity(id);
|
|
|
+ // 偏差
|
|
|
+ double deviation = capacity * 0.03;
|
|
|
+ // 有功设定
|
|
|
+ Optional<AgcDeviateTag> agcLimit = ladt.stream().filter(ad -> ad.getName().equals("有功设定限值")).findFirst();
|
|
|
+
|
|
|
+ List<AgcDeviateTag> la = new ArrayList<>();
|
|
|
+ if (!agcLimit.isPresent()) {
|
|
|
+ return la;
|
|
|
+ }
|
|
|
+ AgcDeviateTag adtUper = new AgcDeviateTag();
|
|
|
+ adtUper.setName("偏差上限");
|
|
|
+ adtUper.setValues(new ArrayList<>());
|
|
|
+ AgcDeviateTag adtLimt = new AgcDeviateTag();
|
|
|
+ adtLimt.setName("偏差下限");
|
|
|
+ adtLimt.setValues(new ArrayList<>());
|
|
|
+
|
|
|
+ for (TsDoubleTsData pd : agcLimit.get().getValues()) {
|
|
|
+ long ts = pd.getTs();
|
|
|
+ TsDoubleTsData pdUper = new TsDoubleTsData();
|
|
|
+ pdUper.setTs(ts);
|
|
|
+ pdUper.setDoubleValue(pd.getDoubleValue() * 1.03);
|
|
|
+ TsDoubleTsData pdLimt = new TsDoubleTsData();
|
|
|
+ pdLimt.setTs(ts);
|
|
|
+ pdLimt.setDoubleValue(pd.getDoubleValue() * 0.97);
|
|
|
+ adtUper.getValues().add(pdUper);
|
|
|
+ adtLimt.getValues().add(pdLimt);
|
|
|
+ }
|
|
|
+ la.add(adtUper);
|
|
|
+ la.add(adtLimt);
|
|
|
+ return la;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据ID获取agc配置信息
|
|
|
+ *
|
|
|
+ * @param id 场站ID
|
|
|
+ * @return 配置信息
|
|
|
+ */
|
|
|
+ private List<AiPoints> getAiPoints(String id) {
|
|
|
+ if (!CacheContext.agcDeviateConfigMap.containsKey(id)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ AiPoints[] aiPoints = CacheContext.agcDeviateConfigMap.get(id).getAiPoints();
|
|
|
+ return Arrays.stream(aiPoints).filter(ap -> ap.getName().contains("功") && !ap.getName().contains("预测")).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ private double getCapacity(String id) {
|
|
|
+ if (!CacheContext.agcDeviateConfigMap.containsKey(id)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return CacheContext.agcDeviateConfigMap.get(id).getInstalledCapacity();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取配置
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Object getConfig() {
|
|
|
+ return CacheContext.agcDeviateConfigMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<AgcDeviateTag> getAgcDeviateTagsOffline(String id, long startTs, long endTs, int interval) {
|
|
|
+ if (!CacheContext.files.containsKey(id)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ List<String> ls = CacheContext.files.get(id);
|
|
|
+
|
|
|
+ if (ls == null) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ int ran = (int) (Math.random() * ls.size());
|
|
|
+ return fileService.getFromFile(ls.get(ran), new TypeReference<List<AgcDeviateTag>>() {
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|