RealTimeDisplayServiceImpl.java 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. package com.jiayue.biz.service.impl;
  2. import cn.hutool.db.Entity;
  3. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  4. import com.jiayue.biz.domain.*;
  5. import com.jiayue.biz.eunms.WindDirectionEnum;
  6. import com.jiayue.biz.mapper.ProphaseAnemometryDataMapper;
  7. import com.jiayue.biz.mapper.ProphaseWeatherDataMapper;
  8. import com.jiayue.biz.mapper.WindTowerDataParentTableMapper;
  9. import com.jiayue.biz.service.*;
  10. import com.jiayue.biz.util.CalculationUtil;
  11. import com.jiayue.biz.util.DateTimeUtil;
  12. import com.jiayue.biz.util.SEDateUtil;
  13. import com.jiayue.common.utils.DateUtil;
  14. import flanagan.analysis.ProbabilityPlot;
  15. import lombok.AllArgsConstructor;
  16. import org.springframework.beans.factory.annotation.Autowired;
  17. import org.springframework.stereotype.Service;
  18. import java.math.BigDecimal;
  19. import java.math.RoundingMode;
  20. import java.sql.Array;
  21. import java.sql.Timestamp;
  22. import java.text.SimpleDateFormat;
  23. import java.util.*;
  24. import java.util.stream.Collectors;
  25. import java.util.stream.Stream;
  26. @Service
  27. @AllArgsConstructor
  28. public class RealTimeDisplayServiceImpl implements RealTimeDisplayService {
  29. private WindTowerDataParentTableService windTowerDataParentTableService;
  30. private WindTowerDataParentTableMapper windTowerDataParentTableMapper;
  31. private WindTowerInfoService windTowerInfoService;
  32. private StatisticsSituationService statisticsSituationService;
  33. private ProphaseAnemometryDataMapper prophaseAnemometryDataMapper;
  34. private ProphaseWeatherDataMapper prophaseWeatherDataMapper;
  35. private final double e = 2.71828183;
  36. /**
  37. * 实时查询 (湍流)
  38. *
  39. * @param startTime 开始时间
  40. * @param endTime 结束时间
  41. * @param equipmentId 设备编号
  42. * @param height 层高
  43. * @return List<Map < String, Object>> 湍流集合
  44. */
  45. public List<Map<String, Object>> turbulence(Long startTime, Long endTime, String equipmentId, String height) {
  46. //查询所有数据
  47. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectAveAndSta(equipmentId, new Timestamp(startTime), new Timestamp(endTime));
  48. ArrayList densityList = new ArrayList<>();
  49. ArrayList<HashMap<String, Object>> densityList2 = new ArrayList<>();
  50. ArrayList<HashMap<String, Object>> densityList3 = new ArrayList<>();
  51. //用于遍历数据
  52. TreeMap<String, Object> map = new TreeMap<>();
  53. if (height == null || height.equals("")) {
  54. //获取测风塔数据获取层高
  55. String wsHeights = windTowerInfoService.getWsHeights(equipmentId);
  56. height = wsHeights;
  57. }
  58. String[] split = height.split(",");
  59. for (String h : split) {
  60. //根据层高获取对应数据
  61. List<ProphaseAnemometryData> dataList = prophaseAnemometryDataList.stream().filter(p -> p.getLayerHeight().equals(h)).collect(Collectors.toList());
  62. BigDecimal content;
  63. //根据风速段进行分组
  64. Map<BigDecimal, List<BigDecimal>> speedLevel_turbulenceMap = new HashMap<>();
  65. BigDecimal speedLevel;
  66. for (ProphaseAnemometryData p : dataList) {
  67. BigDecimal ave = p.getWsAve() != null ? BigDecimal.valueOf(p.getWsAve()) : BigDecimal.ZERO;
  68. BigDecimal sta = p.getWsSta() != null ? BigDecimal.valueOf(p.getWsSta()) : BigDecimal.ZERO;
  69. if (ave.compareTo(BigDecimal.ZERO) != 0 && sta.compareTo(BigDecimal.ZERO) != 0) {
  70. //湍流
  71. content = sta.divide(ave, 2, RoundingMode.HALF_UP);
  72. //风速段 按着风速的正负0.5取值
  73. speedLevel = ave.setScale(0, RoundingMode.HALF_UP);
  74. if (speedLevel_turbulenceMap.containsKey((speedLevel))) {
  75. speedLevel_turbulenceMap.get(speedLevel).add(content);
  76. } else {
  77. speedLevel_turbulenceMap.put(speedLevel, new ArrayList<>());
  78. speedLevel_turbulenceMap.get(speedLevel).add(content);
  79. }
  80. speedLevel_turbulenceMap.remove(BigDecimal.valueOf(0));
  81. }
  82. }
  83. /*
  84. * 风速段-----湍流平均值
  85. */
  86. TreeMap<Object, Object> treeMap = new TreeMap();
  87. Map<BigDecimal, BigDecimal> speedLevel_turbulenceAvgMap = new HashMap<>();
  88. BigDecimal avgContent;
  89. for (Map.Entry<BigDecimal, List<BigDecimal>> e : speedLevel_turbulenceMap.entrySet()) {
  90. avgContent = BigDecimal.ZERO;
  91. if (e.getValue().size() != 0) {
  92. for (BigDecimal a : e.getValue()) {
  93. avgContent = avgContent.add(a);
  94. }
  95. avgContent = avgContent.divide((BigDecimal.valueOf(e.getValue().size())), 2, RoundingMode.HALF_UP);
  96. }
  97. speedLevel_turbulenceAvgMap.put(e.getKey().setScale(0, BigDecimal.ROUND_UP), avgContent);
  98. }
  99. treeMap.putAll(speedLevel_turbulenceAvgMap);
  100. ArrayList<Object> densityList1 = new ArrayList<>();
  101. densityList2 = new ArrayList<>();
  102. BigDecimal TurCount = BigDecimal.ZERO;
  103. BigDecimal TurSum = BigDecimal.ZERO;
  104. BigDecimal TurAve = BigDecimal.ZERO;
  105. int i1 = treeMap.entrySet().size();
  106. TurCount = TurCount.add(BigDecimal.valueOf(i1));
  107. //拼接返回给前台
  108. for (Map.Entry<Object, Object> o1 : treeMap.entrySet()) {
  109. Map<String, Object> map2 = new HashMap();
  110. map2.put("ws", o1.getKey());
  111. map2.put("tur", o1.getValue());
  112. densityList1.add(map2);
  113. if (o1.getValue() != null) {
  114. TurSum = TurSum.add(BigDecimal.valueOf(Double.parseDouble(o1.getValue().toString())));
  115. }
  116. }
  117. //如果不等于0
  118. if (!TurCount.equals(BigDecimal.ZERO)) {
  119. TurAve = TurSum.divide(TurCount, 2, RoundingMode.HALF_UP);
  120. }
  121. //放入风速和湍流值
  122. map.put(h, densityList1);
  123. HashMap<String, BigDecimal> TurAveMap = new HashMap<>();
  124. TurAveMap.put(h, TurAve);
  125. for (Map.Entry<String, BigDecimal> s1 : TurAveMap.entrySet()) {
  126. HashMap<String, Object> map1 = new HashMap<>();
  127. map1.put("height", s1.getKey());
  128. map1.put("TurAve", s1.getValue());
  129. densityList3.add(map1);
  130. }
  131. }
  132. for (Map.Entry<String, Object> m1 : map.entrySet()) {
  133. HashMap<String, Object> map1 = new HashMap<>();
  134. map1.put("height", m1.getKey());
  135. map1.put("arr", m1.getValue());
  136. densityList2.add(map1);
  137. }
  138. densityList.add(densityList2);
  139. densityList.add(densityList3);
  140. return densityList;
  141. }
  142. /**
  143. * 实时查询 (风速/风向折线图)
  144. *
  145. * @param startTime 开始时间
  146. * @param endTime 结束时间
  147. * @param equipmentId 设备Id
  148. * @param height 层高
  149. * @return Map
  150. */
  151. public Map<String, Object> selectWsAndWd(Long startTime, Long endTime, String equipmentId, String height) {
  152. //注释跟下边的一样 这个只是风速的
  153. HashMap<String, Object> map = new HashMap<>();
  154. ArrayList<Object> finalWsList = new ArrayList<>();
  155. ArrayList<Object> finalWdList = new ArrayList<>();
  156. ArrayList<Object> wsChartsData = new ArrayList<>();
  157. ArrayList<Object> wdChartsData = new ArrayList<>();
  158. ArrayList<Object> wsAveList = new ArrayList<>();
  159. ArrayList<Object> wdAveList = new ArrayList<>();
  160. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  161. // 日期集合
  162. ArrayList<String> timeList = new ArrayList<>();
  163. for (long i = startTime; i < endTime; i = i + 1000 * 60 * 10L) {
  164. timeList.add(sdf.format(new Date(i)));
  165. }
  166. // 测风塔数据集合
  167. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectAve(equipmentId, new Timestamp(startTime), new Timestamp(endTime));
  168. List<WindTowerInfo> windTowerInfoList = windTowerInfoService.lambdaQuery().eq(WindTowerInfo::getEquipmentNo, equipmentId).list();
  169. String[] wdHeight = windTowerInfoList.get(0).getWdHeights().split(",");
  170. if (height == null || height.equals("")) {
  171. height = windTowerInfoService.getWsHeights(equipmentId);
  172. }
  173. //拆分层高
  174. String[] split = height.split(",");
  175. for (String h : split) {
  176. List<ProphaseAnemometryData> dataList = prophaseAnemometryDataList.stream().filter(p -> p.getLayerHeight().equals(h)).collect(Collectors.toList());
  177. ArrayList<Object> wslist = new ArrayList<>(); // 风速时间集合
  178. ArrayList<Object> wdlist = new ArrayList<>(); // 风速时间集合
  179. BigDecimal wsSum = new BigDecimal(0); // 风速总和
  180. BigDecimal wsAve = BigDecimal.ZERO; // 平均风速
  181. BigDecimal wdSum = new BigDecimal(0); // 风向总和
  182. BigDecimal wdAve = BigDecimal.ZERO; // 平均风向
  183. boolean flag = false;//判断风向层高中是否包含此层高
  184. if (Arrays.asList(wdHeight).contains(h)) {
  185. flag = true;
  186. }
  187. for (ProphaseAnemometryData p : dataList) {
  188. HashMap<Object, Object> wsMap = new HashMap<>();
  189. String sDate = sdf.format(p.getTs());
  190. String wsStr = p.getWsAve() == null ? "0" : p.getWsAve().toString();
  191. // 时间-风速 / 时间-风向
  192. wsMap.put("time", sDate);
  193. wsMap.put("ws", wsStr);
  194. wslist.add(wsMap);
  195. // 平均值
  196. wsSum = wsSum.add(CalculationUtil.getBigDecimal(wsStr));
  197. // 判断风向层高中是否包含此层高
  198. if (flag) {
  199. HashMap<Object, Object> wdmap = new HashMap<>();
  200. String wdStr = p.getWdAve() == null ? "0" : p.getWdAve().toString();
  201. wdmap.put("time", sDate);
  202. wdmap.put("wd", wdStr);
  203. wdSum = wdSum.add(CalculationUtil.getBigDecimal(wdStr));
  204. wdlist.add(wdmap);
  205. }
  206. }
  207. if (!dataList.isEmpty()) {
  208. wsAve = wsSum.divide(BigDecimal.valueOf(dataList.size()), 2, RoundingMode.HALF_UP);
  209. wdAve = wdSum.divide(BigDecimal.valueOf(dataList.size()), 2, RoundingMode.HALF_UP);
  210. }
  211. // 曲线Map
  212. HashMap<Object, Object> finalWsMap = new HashMap<>();
  213. finalWsMap.put("height", h);
  214. finalWsMap.put("arr", wslist);
  215. wsChartsData.add(finalWsMap);
  216. // 平均值Map
  217. HashMap<Object, Object> aveWsMap = new HashMap<>();
  218. aveWsMap.put("height", h);
  219. aveWsMap.put("wsave", wsAve);
  220. wsAveList.add(aveWsMap);
  221. // 若此层高有风向
  222. if (!wdlist.isEmpty()) {
  223. HashMap<Object, Object> finalWdMap = new HashMap<>();
  224. finalWdMap.put("height", h);
  225. finalWdMap.put("arr", wdlist);
  226. wdChartsData.add(finalWdMap);
  227. HashMap<Object, Object> aveWdMap = new HashMap<>();
  228. aveWdMap.put("height", h);
  229. aveWdMap.put("wdave", wdAve);
  230. wdAveList.add(aveWdMap);
  231. }
  232. }
  233. finalWdList.add(wdChartsData);
  234. finalWdList.add(wdAveList);
  235. finalWsList.add(wsChartsData);
  236. finalWsList.add(wsAveList);
  237. map.put("ws", finalWsList);
  238. map.put("wd", finalWdList);
  239. map.put("time", timeList);
  240. return map;
  241. }
  242. /**
  243. * 实时查询 (威布尔)
  244. *
  245. * @param startTime 开始时间
  246. * @param endTime 结束时间
  247. * @param equipmentId 测风塔id
  248. * @param height 层高
  249. * @return 威布尔
  250. */
  251. public List<Object> weibull(Long startTime, Long endTime, String equipmentId, String height) {
  252. //查询实时数据
  253. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectWsAve(equipmentId, new Timestamp(startTime), new Timestamp(endTime));
  254. List<ProphaseAnemometryData> dataList = prophaseAnemometryDataList.stream().filter(p -> p.getLayerHeight().equals(height)).collect(Collectors.toList());
  255. ArrayList<Object> densityList1 = new ArrayList<>();
  256. ArrayList<Object> densityList = new ArrayList<>();
  257. //key:风速区间 val:风速
  258. Map<BigDecimal, List<BigDecimal>> wsMap = new HashMap<>();
  259. //A K 平均风速map
  260. HashMap<String, Double> map2 = new HashMap<>();
  261. //风速频率map
  262. TreeMap<BigDecimal, Object> map1 = new TreeMap<>();
  263. // 风速频率集合
  264. ArrayList<Object> wsFreList = new ArrayList<>();
  265. //平均风速
  266. BigDecimal avgWs = BigDecimal.ZERO;
  267. //过滤风速集合
  268. List<Float> floatList = dataList.stream().map(ProphaseAnemometryData::getWsAve).collect(Collectors.toList());
  269. //求风速总值
  270. double sum = floatList.stream().mapToDouble(p -> p).sum();
  271. double[] doubles = floatList.stream().mapToDouble(p -> p).toArray();
  272. if (!floatList.isEmpty()) {
  273. //平均风速
  274. avgWs = BigDecimal.valueOf(sum).divide(BigDecimal.valueOf(floatList.size()), 4, RoundingMode.HALF_UP);
  275. }
  276. //威布尔Map
  277. TreeMap<BigDecimal, Object> weibullMap = new TreeMap<>();
  278. if (doubles.length > 0) {
  279. //把风速集合传入,计算A、K
  280. ProbabilityPlot probabilityPlot = new ProbabilityPlot(doubles);
  281. probabilityPlot.suppressDisplay();
  282. double K = probabilityPlot.weibullTwoParGamma();
  283. double A = probabilityPlot.weibullTwoParSigma();
  284. //放入AK 平均风速返回给前台
  285. map2.put("K", K);
  286. map2.put("A", A);
  287. map2.put("avgWs", avgWs.doubleValue());
  288. for (double ws : doubles) {
  289. //四舍五入取风速段
  290. BigDecimal speedLevel = BigDecimal.valueOf(Math.ceil(BigDecimal.valueOf(ws).subtract(BigDecimal.valueOf(0.5)).doubleValue()));
  291. //判断map中是否包含风速段的key 不包含创建list放入风速
  292. if (wsMap.containsKey((speedLevel))) {
  293. wsMap.get(speedLevel).add(BigDecimal.valueOf(ws));
  294. } else {
  295. wsMap.put(speedLevel, new ArrayList<>());
  296. wsMap.get(speedLevel).add(BigDecimal.valueOf(ws));
  297. }
  298. //获得威布尔集合的size,用作风速频率
  299. map1.put(speedLevel.setScale(0), wsMap.get(speedLevel).size());
  300. }
  301. //循环风速map获取风速区间的平均风速用于计算weibull
  302. for (Map.Entry<BigDecimal, List<BigDecimal>> entry : wsMap.entrySet()) {
  303. //求出风速区间的平均风速
  304. BigDecimal wsAve = entry.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(entry.getValue().size()), 2, RoundingMode.HALF_UP);
  305. //计算威布尔值
  306. BigDecimal weibull = CalculationUtil.getBigDecimal(e, wsAve.doubleValue(), K, A);
  307. weibullMap.put(entry.getKey(), weibull);
  308. }
  309. //循环风速区间 风速频率
  310. map1.forEach((key, val) -> {
  311. Map<String, Object> map = new HashMap<String, Object>();
  312. //风速区间
  313. map.put("ws", key);
  314. /*风速频率*/
  315. map.put("cont", new BigDecimal(val.toString()).divide(new BigDecimal(doubles.length), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100)));
  316. wsFreList.add(map);
  317. });
  318. weibullMap.forEach((key, val) -> {
  319. HashMap<String, Object> map = new HashMap<String, Object>();
  320. map.put("ws", key);
  321. map.put("Weibull", val);
  322. densityList1.add(map);
  323. });
  324. densityList.add(densityList1);
  325. densityList.add(wsFreList);
  326. densityList.add(map2);
  327. }
  328. return densityList;
  329. }
  330. /**
  331. * 获取测风塔数据最后一条数据时间到前一周数据 时间段内所有时间点
  332. *
  333. * @return 时间点集合
  334. */
  335. public List<Map<String, Object>> getStartTimeAndEndTime() {
  336. List<Map<String, Object>> list = new ArrayList<>();
  337. List<WindTowerInfo> windTowerInfoList = windTowerInfoService.list();
  338. for (WindTowerInfo windTowerInfo : windTowerInfoList) {
  339. HashMap<String, Object> hashMap = new HashMap<>();
  340. //获取最后一条数据
  341. List<Entity> lastData = prophaseWeatherDataMapper.getLastData(windTowerInfo.getEquipmentNo());
  342. if(lastData.size() > 0){
  343. Timestamp timeEnd = (Timestamp) lastData.get(0).get("last (ts)");
  344. long lastDataTime = timeEnd.getTime();
  345. long startTime = DateTimeUtil.getDayStartTime(lastDataTime - 86400000 * 7).getTime();
  346. long endTime = DateTimeUtil.getDayLastTime(lastDataTime).getTime();
  347. hashMap.put("equipmentId", windTowerInfo.getEquipmentNo());
  348. hashMap.put("startTime", startTime);
  349. hashMap.put("endTime", endTime);
  350. list.add(hashMap);
  351. }
  352. }
  353. return list;
  354. }
  355. /*根据时间范围和设备id查询温度气压对比图,空气密度数据*/
  356. public Map<String, Object> queryTPAndAirDensity(Long startTime, Long endTime, String equipmentId) {
  357. Map<String, Object> map = new HashMap<>();
  358. List dataList = new ArrayList();
  359. List tList = new ArrayList();
  360. List paList = new ArrayList();
  361. List timeList = new ArrayList();
  362. //所有数据
  363. List<ProphaseWeatherData> prophaseWeatherDataList = prophaseWeatherDataMapper.selectTAveAndPaAveAndAir(equipmentId, new Timestamp(startTime), new Timestamp(endTime));
  364. if (prophaseWeatherDataList.size() > 0) {
  365. SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  366. for (long i = startTime; i < endTime; i = i + 1000 * 60 * 10L) {
  367. timeList.add(formatter.format(new Date(i)));
  368. }
  369. /*平均数据*/
  370. BigDecimal avgT = new BigDecimal(0);
  371. BigDecimal avgPa = new BigDecimal(0);
  372. BigDecimal avgAirDensity = new BigDecimal(0);
  373. BigDecimal sumT = new BigDecimal(0);
  374. BigDecimal sumPa = new BigDecimal(0);
  375. BigDecimal sumAirDensity = new BigDecimal(0);
  376. for (ProphaseWeatherData p : prophaseWeatherDataList) {
  377. /*温度曲线*/
  378. Map<String, Object> tMap = new HashMap<>();
  379. /*压强曲线*/
  380. Map<String, Object> paMap = new HashMap<>();
  381. tMap.put("time", formatter.format(p.getTs()));
  382. tMap.put("t", p.getTAve());
  383. paMap.put("time", formatter.format(p.getTs()));
  384. paMap.put("pa", p.getPaAve());
  385. tList.add(tMap);
  386. paList.add(paMap);
  387. // 判断数据是否为空 ,空计算为0
  388. sumT = sumT.add(p.getTAve() == null ? new BigDecimal(0) : BigDecimal.valueOf(p.getTAve()));
  389. sumPa = sumPa.add(p.getPaAve() == null ? new BigDecimal(0) : BigDecimal.valueOf(p.getPaAve()));
  390. sumAirDensity = sumAirDensity.add(p.getAirDensity() == null ? new BigDecimal(0) : BigDecimal.valueOf(p.getAirDensity()));
  391. /*表格数据*/
  392. Map<String, Object> dataMap = new HashMap<>();
  393. dataMap.put("time", formatter.format(p.getTs()));
  394. dataMap.put("t", BigDecimal.valueOf(p.getTAve()).setScale(2, RoundingMode.HALF_UP));
  395. dataMap.put("pa", BigDecimal.valueOf(p.getPaAve()).setScale(2, RoundingMode.HALF_UP));
  396. dataMap.put("airDensity", BigDecimal.valueOf(p.getAirDensity()).setScale(2, RoundingMode.HALF_UP));
  397. dataList.add(dataMap);
  398. }
  399. /*计算平均值*/
  400. if (sumT.compareTo(BigDecimal.ZERO) != 0) {
  401. avgT = sumT.divide(new BigDecimal(prophaseWeatherDataList.size()), 3, RoundingMode.HALF_UP);
  402. }
  403. if (sumPa.compareTo(BigDecimal.ZERO) != 0) {
  404. avgPa = sumPa.divide(new BigDecimal(prophaseWeatherDataList.size()), 3, RoundingMode.HALF_UP);
  405. }
  406. if (sumAirDensity.compareTo(BigDecimal.ZERO) != 0) {
  407. avgAirDensity = sumAirDensity.divide(new BigDecimal(prophaseWeatherDataList.size()), 3, RoundingMode.HALF_UP);
  408. }
  409. map.put("time", timeList);
  410. map.put("t", tList);
  411. map.put("pa", paList);
  412. map.put("data", dataList);
  413. map.put("avgT", avgT);
  414. map.put("avgPa", avgPa);
  415. map.put("avgAirDensity", avgAirDensity);
  416. }
  417. return map;
  418. }
  419. /*
  420. * 时间段风功率密度曲线图 风况
  421. *
  422. * @param startTime 开始时间
  423. * @param endTime 结束时间
  424. * @param eqId 设备编号
  425. * @param height 层高
  426. * @return
  427. */
  428. public Map<String, Object> getWindPowerDensityAndAverageWindSpeed(Long startTime, Long endTime, String height, String equipmentId) {
  429. startTime = DateUtil.beginOfDay(new Date(startTime)).getTime();
  430. List<ProphaseWeatherData> prophaseWeatherDataList = prophaseWeatherDataMapper.selectAir(equipmentId, new Timestamp(startTime), new Timestamp(endTime));
  431. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectWsAveForHeight(equipmentId, new Timestamp(startTime), new Timestamp(endTime), height);
  432. SimpleDateFormat sdf = new SimpleDateFormat("HH");
  433. SimpleDateFormat sdfHour = new SimpleDateFormat("yyyy-MM-dd HH");
  434. //曲线图
  435. LinkedHashMap<String, ArrayList<BigDecimal>> wpdOneHourMap = new LinkedHashMap<>();
  436. LinkedHashMap<String, ArrayList<BigDecimal>> wsOneHourMap = new LinkedHashMap<>();
  437. //表格
  438. LinkedHashMap<String, ArrayList<BigDecimal>> wpdOneHourSdfMap = new LinkedHashMap<>();
  439. LinkedHashMap<String, ArrayList<BigDecimal>> wsOneHourSdfMap = new LinkedHashMap<>();
  440. Map<String, Object> map = new LinkedHashMap<>();
  441. BigDecimal sumWpd = BigDecimal.ZERO;
  442. BigDecimal sumWs = BigDecimal.ZERO;
  443. BigDecimal total = BigDecimal.ZERO;
  444. for (long i = startTime; i < endTime; i = i + 3600000) {
  445. long finalI = i;
  446. List<ProphaseWeatherData> prophaseWeatherData = prophaseWeatherDataList.stream().filter(p -> p.getTs().getTime() >= finalI && p.getTs().getTime() < finalI + 3600000 - 1).collect(Collectors.toList());
  447. List<ProphaseAnemometryData> prophaseAnemometryData = prophaseAnemometryDataList.stream().filter(p -> p.getTs().getTime() >= finalI && p.getTs().getTime() < finalI + 3600000 - 1).collect(Collectors.toList());
  448. BigDecimal tenMinuteWpdSum = BigDecimal.ZERO;
  449. BigDecimal tenMinuteWsSum = BigDecimal.ZERO;
  450. //计算小时风速和风功率密度的总值
  451. for (ProphaseWeatherData prophaseWeatherDatum : prophaseWeatherData) {
  452. List<ProphaseAnemometryData> anemometryData = prophaseAnemometryData.stream().filter(p -> p.getTs().getTime() == prophaseWeatherDatum.getTs().getTime()).collect(Collectors.toList());
  453. if (anemometryData.size() > 0) {
  454. tenMinuteWpdSum = tenMinuteWpdSum.add(BigDecimal.valueOf(0.5).multiply(CalculationUtil.power(BigDecimal.valueOf(anemometryData.get(0).getWsAve()), 3)).multiply(BigDecimal.valueOf(prophaseWeatherDatum.getAirDensity())));
  455. tenMinuteWsSum = tenMinuteWsSum.add(BigDecimal.valueOf(anemometryData.get(0).getWsAve()));
  456. }
  457. }
  458. BigDecimal oneHourWpd = BigDecimal.ZERO;
  459. BigDecimal oneHourWs = BigDecimal.ZERO;
  460. //计算小时平均值
  461. if (prophaseAnemometryData.size() > 0) {
  462. oneHourWpd = tenMinuteWpdSum.divide(BigDecimal.valueOf(prophaseAnemometryData.size()), 2, RoundingMode.HALF_UP);
  463. oneHourWs = tenMinuteWsSum.divide(BigDecimal.valueOf(prophaseAnemometryData.size()), 2, RoundingMode.HALF_UP);
  464. //计算风功率密度总和
  465. sumWpd = sumWpd.add(oneHourWpd);
  466. //计算风速总和
  467. sumWs = sumWs.add(oneHourWs);
  468. //计算数据个数
  469. total = total.add(BigDecimal.ONE);
  470. }
  471. //风功率密度曲线图
  472. this.getMapForData(i, oneHourWpd, sdf, wpdOneHourMap);
  473. //风速密度曲线图
  474. this.getMapForData(i, oneHourWs, sdf, wsOneHourMap);
  475. //风功率密度表格
  476. this.getMapForData(i, oneHourWpd, sdfHour, wpdOneHourSdfMap);
  477. //风速表格
  478. this.getMapForData(i, oneHourWs, sdfHour, wsOneHourSdfMap);
  479. }
  480. ArrayList<ArrayList> windPowerDensity = getListEntry(wpdOneHourMap);
  481. ArrayList<ArrayList> averageWindSpeed = getListEntry(wsOneHourMap);
  482. ArrayList<HashMap<String, Object>> wpdList = getMapEntry(wpdOneHourSdfMap);
  483. ArrayList<HashMap<String, Object>> awsList = getMapEntry(wsOneHourSdfMap);
  484. //风功率平均值
  485. BigDecimal aveWpd = sumWpd.divide(total, 2, RoundingMode.HALF_UP);
  486. //风速平均值
  487. BigDecimal aveWs = sumWs.divide(total, 2, RoundingMode.HALF_UP);
  488. map.put("awsList", awsList);
  489. map.put("wpdList", wpdList);
  490. map.put("WindPowerDensity", windPowerDensity);
  491. map.put("AverageWindSpeed", averageWindSpeed);
  492. map.put("avgWs", aveWs);
  493. map.put("avgWpd", aveWpd);
  494. return map;
  495. }
  496. public void getMapForData(Long time, BigDecimal data, SimpleDateFormat sdf, HashMap<String, ArrayList<BigDecimal>> dataMap) {
  497. if (dataMap.containsKey(sdf.format(new Date(time)))) {
  498. //判断是否为0 0为无效数据 防止getListEntry方法除0 问题
  499. if (data.compareTo(BigDecimal.ZERO) != 0) {
  500. dataMap.get(sdf.format(new Date(time))).add(data);
  501. }
  502. } else {
  503. dataMap.put(sdf.format(new Date(time)), new ArrayList<>());
  504. if (data.compareTo(BigDecimal.ZERO) != 0) {
  505. dataMap.get(sdf.format(new Date(time))).add(data);
  506. }
  507. }
  508. }
  509. public ArrayList<ArrayList> getListEntry(HashMap<String, ArrayList<BigDecimal>> dataMap) {
  510. ArrayList<ArrayList> arrayList = new ArrayList<>();
  511. for (Map.Entry<String, ArrayList<BigDecimal>> entry : dataMap.entrySet()) {
  512. ArrayList<Object> arrayList1 = new ArrayList<>();
  513. BigDecimal divide = BigDecimal.ZERO;
  514. //如果集合为空 value就为0
  515. if (entry.getValue().size() > 0) {
  516. divide = entry.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(entry.getValue().size()), 2, RoundingMode.HALF_UP);
  517. }
  518. arrayList1.add(entry.getKey() + ":00");
  519. arrayList1.add(divide);
  520. arrayList.add(arrayList1);
  521. }
  522. return arrayList;
  523. }
  524. public ArrayList<HashMap<String, Object>> getMapEntry(HashMap<String, ArrayList<BigDecimal>> dataMap) {
  525. ArrayList<HashMap<String, Object>> mapList = new ArrayList<>();
  526. for (Map.Entry<String, ArrayList<BigDecimal>> entry : dataMap.entrySet()) {
  527. HashMap<String, Object> hashMap = new HashMap<>();
  528. BigDecimal divide = BigDecimal.ZERO;
  529. //如果集合为空 value就为0
  530. if (entry.getValue().size() > 0) {
  531. divide = entry.getValue().stream().reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(entry.getValue().size()), 2, RoundingMode.HALF_UP);
  532. }
  533. hashMap.put("time", entry.getKey() + ":00");
  534. hashMap.put("value", divide);
  535. mapList.add(hashMap);
  536. }
  537. return mapList;
  538. }
  539. /**
  540. * 数据完整性
  541. *
  542. * @param equipmentNo 设备编号
  543. * @return
  544. */
  545. public List<Map> dataIntegrity(String equipmentNo) {
  546. List list = new ArrayList();
  547. try {
  548. long yesterday = new Date().getTime() - 1000 * 60 * 60 * 24;
  549. Date endTime = DateTimeUtil.getDayLastTime(yesterday);
  550. //获取该塔的数据起止时间
  551. List<StatisticsSituation> statisticsSituationList = statisticsSituationService.list();
  552. List<StatisticsSituation> collectStatisticsSituationList = statisticsSituationList.stream().filter(s -> s.getEquipmentId().equals(equipmentNo)).collect(Collectors.toList());
  553. String[] startTimeAndEndTime = collectStatisticsSituationList.get(0).getStartTimeAndEndTime().split(",");
  554. Date startTime = DateTimeUtil.beginOfMonth(new Date(Long.parseLong(startTimeAndEndTime[0])));
  555. List<Entity> entities = prophaseWeatherDataMapper.selectCount(equipmentNo);
  556. Map<Object, Object> formatMap = new HashMap<>();
  557. for (Entity entity : entities) {
  558. // td engine 取出的时间需要截取字段
  559. String wstart = entity.get("_wstart").toString().substring(0,10);
  560. formatMap.put(wstart,entity.get("count(*)"));
  561. }
  562. SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM");
  563. SimpleDateFormat dayFormatter = new SimpleDateFormat("dd");
  564. //前一天
  565. Date nowDate = new Date(DateTimeUtil.getMillisecondsSubDay() - 1000);
  566. //当月第一天时间
  567. Date mouthOneDayTime = DateTimeUtil.beginOfMonth(DateTimeUtil.getCurrentTimeForMinute());
  568. SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
  569. // 当天时间
  570. Date date = DateTimeUtil.getDayStartTime(new Date().getTime());
  571. // 循环月份的最终变量变量
  572. //int endMonthCount = 12;
  573. List<Long> interval = DateTimeUtil.getIntervalTimeByMonth(startTime, endTime);
  574. int endMonthCount = interval.size();
  575. //如果今天不是当月第一天,有今月得完整性
  576. if (date.compareTo(mouthOneDayTime) != 0) {
  577. //当月的完整性
  578. Map nowMouthMap = new HashMap();
  579. nowMouthMap.put("mouth", formatter.format(nowDate));
  580. for (Long i = mouthOneDayTime.getTime(); i <= nowDate.getTime(); i = i + 1000 * 60 * 60 * 24L) {
  581. if (null != formatMap.get(format.format(i))) {
  582. nowMouthMap.put(dayFormatter.format(new Date(i)), formatMap.get(format.format(i)));
  583. } else {
  584. nowMouthMap.put(dayFormatter.format(new Date(i)), 0);
  585. }
  586. }
  587. list.add(nowMouthMap);
  588. } else {
  589. endMonthCount = interval.size() + 1;
  590. }
  591. for (int i = 1; i < endMonthCount; i++) {
  592. //前i月的第一天0点
  593. Date mouthOneDay = DateTimeUtil.getDayStartTime(DateTimeUtil.mouthOneDay(i).getTime());
  594. //前i月的最后一天的23:59:59
  595. Date mouthLastDay = DateTimeUtil.getDayLastTime(DateTimeUtil.mouthLastDay(i).getTime());
  596. Map map1 = new HashMap();
  597. map1.put("mouth", formatter.format(mouthOneDay));
  598. //查询整月的数据
  599. for (Long j = mouthOneDay.getTime(); j <= mouthLastDay.getTime(); j = j + 1000 * 60 * 60 * 24L) {
  600. if (null != formatMap.get(format.format(j))) {
  601. map1.put(dayFormatter.format(new Date(j)), formatMap.get(format.format(j)));
  602. } else {
  603. map1.put(dayFormatter.format(new Date(j)), 0);
  604. }
  605. }
  606. list.add(map1);
  607. }
  608. } catch (Exception e) {
  609. e.printStackTrace();
  610. }
  611. return list;
  612. }
  613. /**
  614. * 获取风切变指数(风向玫瑰图)
  615. *
  616. * @param startTime
  617. * @param endTime
  618. * @param eqId
  619. * @param height
  620. */
  621. public List<Map<String, Object>> getWindShear(Long startTime, Long endTime, String eqId, String height) {
  622. List<Map<String, Object>> maps = windTowerDataParentTableService.selectDataByBetweenTimeAndEquipmetId(new Date(startTime), new Date(endTime), eqId);
  623. String[] heights = windTowerInfoService.getByEquipmentNo(eqId).get(0).getHeights().split(",");
  624. Integer heightMin = 100;
  625. String finalHeight = height;
  626. if (height.contains("A")) {
  627. finalHeight = height.substring(0, height.length() - 1);
  628. }
  629. // 找出最小层高
  630. for (String h : heights) {
  631. Integer tempHeight = null;
  632. // 若是此层高是第二同层高
  633. if (!h.contains("A")) {
  634. tempHeight = Integer.parseInt(h);
  635. } else {
  636. tempHeight = Integer.parseInt(h.substring(0, h.length() - 1));
  637. }
  638. if (tempHeight < heightMin) {
  639. heightMin = Integer.parseInt(h);
  640. }
  641. }
  642. BigDecimal zero = new BigDecimal(0);
  643. List<Map<String, Object>> list = new ArrayList<>();
  644. for (WindDirectionEnum value : WindDirectionEnum.values()) {
  645. Map<String, Object> map = new HashMap<>();
  646. List<Map<String, Object>> mapList = CalculationUtil.getForHeightAndWindDirectionEnum(maps, height, value);
  647. //获取平均风速
  648. BigDecimal avgWindSpeed = CalculationUtil.getAvgWind(CalculationUtil.getWsForHeight(mapList, height));
  649. BigDecimal avgWindSpeed10 = CalculationUtil.getAvgWind(CalculationUtil.getWsForHeight(mapList, heightMin.toString()));
  650. BigDecimal bigDecimal = new BigDecimal(-99);
  651. if (avgWindSpeed10.compareTo(BigDecimal.ZERO) != 0) {
  652. bigDecimal = CalculationUtil.caWindShear(avgWindSpeed, avgWindSpeed10, new BigDecimal(finalHeight), new BigDecimal(heightMin));
  653. }
  654. map.put(value.name(), bigDecimal.equals(new BigDecimal(-99)) ? zero : bigDecimal);
  655. list.add(map);
  656. }
  657. return list;
  658. }
  659. /**
  660. * 获取湍流(风向玫瑰图)
  661. *
  662. * @param startTime
  663. * @param endTime
  664. * @param eqId
  665. * @param height
  666. */
  667. public List<Map<String, Object>> getTurbulenceIntensity(Long startTime, Long endTime, String eqId, String height) {
  668. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectWdAveAndWdAveAndWsStaForHeight(eqId, new Timestamp(startTime), new Timestamp(endTime), height);
  669. BigDecimal zero = new BigDecimal(0);
  670. List<Map<String, Object>> list = new ArrayList<>();
  671. for (WindDirectionEnum value : WindDirectionEnum.values()) {
  672. Map<String, Object> map = new HashMap<>();
  673. List<ProphaseAnemometryData> heightAndWindDirectionEnum = CalculationUtil.getForHeightAndWindDirectionEnum(prophaseAnemometryDataList, value);
  674. //总风速
  675. double wsSum = heightAndWindDirectionEnum.stream().mapToDouble(ProphaseAnemometryData::getWsAve).sum();
  676. //总方差
  677. double wsSts = heightAndWindDirectionEnum.stream().mapToDouble(ProphaseAnemometryData::getWsSta).sum();
  678. BigDecimal wsAve = BigDecimal.ZERO;
  679. BigDecimal staAve = BigDecimal.ZERO;
  680. if (heightAndWindDirectionEnum.size() > 0) {
  681. //风速平均值
  682. wsAve = BigDecimal.valueOf(wsSum).divide(BigDecimal.valueOf(heightAndWindDirectionEnum.size()), 2, RoundingMode.HALF_UP);
  683. //方差平均值
  684. staAve = BigDecimal.valueOf(wsSts).divide(BigDecimal.valueOf(heightAndWindDirectionEnum.size()), 2, RoundingMode.HALF_UP);
  685. }
  686. BigDecimal bigDecimal = CalculationUtil.caTurbulenceIntensity(staAve, wsAve);
  687. map.put(value.name(), bigDecimal.equals(new BigDecimal(-99)) ? zero : bigDecimal);
  688. list.add(map);
  689. }
  690. return list;
  691. }
  692. /**
  693. * 获取风能密度(风向玫瑰图)
  694. *
  695. * @param startTime
  696. * @param endTime
  697. * @param eqId
  698. * @param height
  699. */
  700. public List<Map<String, Object>> getWindEnergyDensity(Long startTime, Long endTime, String eqId, String height) {
  701. //查询风速数据
  702. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectWdAveAndWdAveAndWsStaForHeight(eqId, new Timestamp(startTime), new Timestamp(endTime), height);
  703. //查询空气密度
  704. List<ProphaseWeatherData> prophaseWeatherDataList = prophaseWeatherDataMapper.selectAir(eqId, new Timestamp(startTime), new Timestamp(endTime));
  705. List<Map<String, Object>> list = new ArrayList<>();
  706. for (WindDirectionEnum value : WindDirectionEnum.values()) {
  707. Map<String, Object> map = new HashMap<>();
  708. List<ProphaseAnemometryData> heightAndWindDirectionEnum = CalculationUtil.getForHeightAndWindDirectionEnum(prophaseAnemometryDataList, value);
  709. BigDecimal wpdSum = BigDecimal.ZERO;
  710. for (ProphaseAnemometryData p : heightAndWindDirectionEnum) {
  711. List<ProphaseWeatherData> prophaseWeatherData = prophaseWeatherDataList.stream().filter(w -> w.getTs().getTime() == p.getTs().getTime()).collect(Collectors.toList());
  712. if(prophaseWeatherData.size() > 0 ){
  713. wpdSum = wpdSum.add(BigDecimal.valueOf(prophaseWeatherData.get(0).getAirDensity()).multiply(BigDecimal.valueOf(0.5)).multiply(CalculationUtil.power(BigDecimal.valueOf(p.getWsAve()), 3)));
  714. }
  715. }
  716. if(prophaseWeatherDataList.size() > 0 ){
  717. BigDecimal wpdAve = wpdSum.divide(BigDecimal.valueOf(prophaseWeatherDataList.size()),2,RoundingMode.HALF_UP);
  718. map.put(value.name(), wpdAve);
  719. list.add(map);
  720. }
  721. }
  722. return list;
  723. }
  724. /**
  725. * 风向玫瑰图
  726. *
  727. * @param startTime 开始时间
  728. * @param endTime 结束时间
  729. * @param equipmentId 设备编号
  730. * @param height 层高
  731. * @return
  732. * @throws Exception
  733. */
  734. public List queryCharts(Long startTime, Long endTime, String equipmentId, String height) {
  735. List<ProphaseAnemometryData> prophaseAnemometryDataList = prophaseAnemometryDataMapper.selectWdAveForHeight(equipmentId, new Timestamp(startTime), new Timestamp(endTime), height);
  736. List list = new ArrayList();
  737. BigDecimal total = BigDecimal.ZERO;
  738. for (WindDirectionEnum value : WindDirectionEnum.values()) {
  739. Map<String, Object> map = new HashMap<>();
  740. //根据设备属性风向获取数据
  741. List<ProphaseAnemometryData> forHeightAndWindDirectionEnum = CalculationUtil.getForHeightAndWindDirectionEnum(prophaseAnemometryDataList, value);
  742. total = total.add(BigDecimal.valueOf(forHeightAndWindDirectionEnum.size()));
  743. if (forHeightAndWindDirectionEnum.size() > 0) {
  744. map.put(value.name(), BigDecimal.valueOf(100).multiply(BigDecimal.valueOf(forHeightAndWindDirectionEnum.size())).divide(BigDecimal.valueOf(prophaseAnemometryDataList.size()), 2, RoundingMode.HALF_UP));
  745. } else {
  746. map.put(value.name(), BigDecimal.ZERO);
  747. }
  748. list.add(map);
  749. }
  750. return list;
  751. }
  752. }