PowerStationDataPacker.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. package com.jiayue.ipfcst.console.service;
  2. import com.googlecode.aviator.AviatorEvaluator;
  3. import com.googlecode.aviator.Expression;
  4. import com.googlecode.aviator.Options;
  5. import com.googlecode.aviator.exception.ExpressionSyntaxErrorException;
  6. import com.jiayue.ipfcst.common.core.util.DateMomentUtil;
  7. import com.jiayue.ipfcst.common.core.util.SpringContextHolder;
  8. import com.jiayue.ipfcst.common.core.util.SunRiseSet;
  9. import com.jiayue.ipfcst.common.data.abst.equipmentstatus.AbstractEquipmentStatusData;
  10. import com.jiayue.ipfcst.common.data.constant.enums.ElectricFieldTypeEnum;
  11. import com.jiayue.ipfcst.common.data.entity.*;
  12. import com.jiayue.ipfcst.console.service.powerofreference.BasePowerOfReferenceCalculator;
  13. import com.jiayue.ipfcst.console.service.powerofreference.iml.PowerOfReferenceCalculator1;
  14. import com.jiayue.ipfcst.console.service.powerofreference.iml.PowerOfReferenceCalculator2;
  15. import com.jiayue.ipfcst.console.util.RedisUtils;
  16. import lombok.Getter;
  17. import lombok.Setter;
  18. import lombok.SneakyThrows;
  19. import lombok.extern.slf4j.Slf4j;
  20. import org.apache.commons.lang.StringUtils;
  21. import org.joda.time.DateTime;
  22. import org.joda.time.LocalTime;
  23. import java.lang.reflect.Field;
  24. import java.math.BigDecimal;
  25. import java.math.RoundingMode;
  26. import java.util.*;
  27. /**
  28. * 有关功率的审计和计算类
  29. * <p>
  30. * 用于计算功率是否合理 返回合理值
  31. * <p>
  32. * 计算理论功率和可用功率
  33. * <p>
  34. * 非主动计算 需被动调用 计算
  35. *
  36. * @author 修唯xiuwei
  37. * @version 3.0
  38. */
  39. @Slf4j
  40. public class PowerStationDataPacker {
  41. public PowerStationDataPacker(ElectricField electricField) {
  42. this.electricField = electricField;
  43. }
  44. /**
  45. * 参照功率的计算方式标识
  46. * 理论功率计算方式
  47. */
  48. private static final String LGJSFS = "lgjsfs";
  49. /**
  50. * 判断是否限电的容量倍率 标识
  51. * 处在 容量*该倍率之下的实际功率 不统计是否限电
  52. */
  53. private static final String SFPDXD = "sfpdxd";
  54. /**
  55. * 限电系数 标识
  56. * 如果 参照功率 - 实际功率 > 实际功率*该系数 则判断为限电
  57. */
  58. private static final String XDXS = "xdxs";
  59. /**
  60. * 短期和超短期平均数计算可用功率所乘 系数最小值
  61. */
  62. private static final String KYGLJSMIN = "kygljsMIN";
  63. /**
  64. * 短期和超短期平均数计算可用功率所乘 系数最大值
  65. */
  66. private static final String KYGLJSMAX = "kygljsMAX";
  67. /**
  68. * 样板机计算方式 标识
  69. */
  70. private static final String YBJSF = "ybjsf";
  71. /**
  72. * 理论功率公式
  73. */
  74. private static final String LLGLGS = "kyglgs";
  75. /**
  76. * 随机数生成器
  77. */
  78. private static final Random random = new Random();
  79. /**
  80. * 样板机计算参照功率
  81. */
  82. BasePowerOfReferenceCalculator powerOfReferenceCalculatorBySample;
  83. /**
  84. * 场站状态数据实体域
  85. */
  86. List<Field> fields = new ArrayList<>();
  87. @Setter
  88. @Getter
  89. private PowerStationStatusData t = new PowerStationStatusData();
  90. /**
  91. * 场站信息
  92. */
  93. private final ElectricField electricField;
  94. /**
  95. * 测风/光法 的公式计算器
  96. */
  97. private CalculatorOfMeasuring calculatorOfMeasuring;
  98. /**
  99. * 实际功率是否需要审核的标志 默认不审核
  100. */
  101. private static final Boolean AUDIT_REAL_POWER = false;
  102. /**
  103. * 日升时刻
  104. */
  105. private DateTime sunUpTime;
  106. /**
  107. * 日落时刻
  108. */
  109. private DateTime sunDownTime;
  110. /**
  111. * 系统配置变量获取类
  112. */
  113. SysParameterService sysParameterService = SpringContextHolder.getBean(SysParameterService.class);
  114. /**
  115. * 查询检修信息
  116. */
  117. OverHaulPlanService overHaulPlanService = SpringContextHolder.getBean(OverHaulPlanService.class);
  118. /**
  119. * 获取短期
  120. */
  121. ForecastPowerShortTermService forecastPowerShortTermService = SpringContextHolder.getBean(ForecastPowerShortTermService.class);
  122. /**
  123. * 获取超短期
  124. */
  125. ForecastPowerUltraShortTermService forecastPowerUltraShortTermService = SpringContextHolder.getBean(ForecastPowerUltraShortTermService.class);
  126. /**
  127. * redis 工具
  128. */
  129. private final RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class);
  130. /**
  131. * 对实际功率合理性进行审核 查看实际功率的合理性
  132. *
  133. * @param power 功率
  134. * @return 更改后的值 double
  135. */
  136. public BigDecimal realPowerRationalityAuditor(BigDecimal power) {
  137. DateTime time = DateTime.now();
  138. if (electricField != null && electricField.getCapacity() != null && power.compareTo(electricField.getCapacity()) > 0) {
  139. //当实际功率超过场站的容量时 返回容量
  140. power = electricField.getCapacity();
  141. if (power.compareTo(BigDecimal.ZERO) < 0) {
  142. power = BigDecimal.ZERO;
  143. }
  144. }
  145. //对日升和日落各宽恕30min 如果在日升前30min到 日落后30min 之间
  146. //如果时间处于日出前30分钟 日落后30分钟 则判定功率为0
  147. if (electricField != null && ElectricFieldTypeEnum.E1.equals(electricField.getElectricFieldTypeEnum())) {
  148. if (time.isBefore(getSunUpTime().minusMillis(30)) || time.isAfter(getSunDownTime().plusMillis(30))) {
  149. power = BigDecimal.ZERO;
  150. }
  151. }
  152. return power;
  153. }
  154. /**
  155. * 获取参照功率
  156. * lgjsfs 理论功率计算方式
  157. *
  158. * @return 参照功率的计算结果
  159. */
  160. private BigDecimal getPowerOfReference(PowerStationStatusData powerStationStatusData) {
  161. String lgjsfs = sysParameterService.getSysParameter(LGJSFS, "0", electricField.getStationCode());
  162. switch (lgjsfs) {
  163. case "1":
  164. log.info("使用样板机方式计算参考值");
  165. if (powerStationStatusData.getReferencePowerBySample() != null) {
  166. return powerStationStatusData.getReferencePowerBySample().multiply(getOpenRatio());
  167. } else {
  168. log.info("样板机方式计算参考值为空返回倍率计算方式");
  169. }
  170. case "2":
  171. log.info("使用测风/光法方式计算参考值");
  172. if (powerStationStatusData.getReferencePowerByMeasuring() != null) {
  173. return powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio());
  174. } else {
  175. log.info("测风/光法方式计算参考值为空返回倍率计算方式");
  176. }
  177. default:
  178. }
  179. log.info("不判断限电,直接判断不限电");
  180. return BigDecimal.valueOf(-99);
  181. }
  182. /**
  183. * 根据实际功率是否需要审核 返回实际功率
  184. *
  185. * @return 实际功率数值
  186. */
  187. @SneakyThrows
  188. public BigDecimal getRealPowerVal(BigDecimal realPower) {
  189. if (realPower == null) {
  190. return BigDecimal.valueOf(-99D);
  191. }
  192. if (AUDIT_REAL_POWER) {
  193. return realPowerRationalityAuditor(realPower);
  194. } else {
  195. BigDecimal power = realPower;
  196. if (power.compareTo(BigDecimal.ZERO) < 0) {
  197. power = BigDecimal.ZERO;
  198. }
  199. return power;
  200. }
  201. }
  202. /**
  203. * 初始化
  204. * 初始化计算器
  205. * 1.确定场站类别
  206. * 2.初始化各种map等
  207. *
  208. * @return 工具包装器本身
  209. */
  210. public PowerStationDataPacker init() {
  211. //初始化实体域集合
  212. initEntityFields();
  213. //初始化测风光法计算器
  214. initCalculatorOfMeasuring();
  215. //初始化样板机法计算公式
  216. initReferenceCalculator();
  217. return this;
  218. }
  219. /**
  220. * 初始化实体域集合
  221. */
  222. private void initEntityFields() {
  223. fields.addAll(Arrays.asList(t.getClass().getDeclaredFields()));
  224. fields.addAll(Arrays.asList(AbstractEquipmentStatusData.class.getDeclaredFields()));
  225. for (Field f : fields) {
  226. f.setAccessible(true);
  227. }
  228. }
  229. /**
  230. * 初始化样板机功率系数计算器
  231. */
  232. private void initReferenceCalculator() {
  233. if ("1".equals(sysParameterService.getSysParameter(YBJSF, "1", electricField.getStationCode()))) {
  234. this.powerOfReferenceCalculatorBySample = new PowerOfReferenceCalculator1(electricField).init();
  235. } else {
  236. this.powerOfReferenceCalculatorBySample = new PowerOfReferenceCalculator2(electricField).init();
  237. }
  238. }
  239. /**
  240. * 判断是否限电
  241. *
  242. * @param powerStationStatusData 场站状态数据
  243. * @return 限电? true: 限电 ; false :不限电
  244. */
  245. public boolean judgeIsRationing(PowerStationStatusData powerStationStatusData) {
  246. //底线功率
  247. BigDecimal baseLinePower = electricField.getCapacity().multiply(new BigDecimal(sysParameterService.getSysParameter(SFPDXD, "1", electricField.getStationCode())));
  248. BigDecimal coefficient = new BigDecimal(sysParameterService.getSysParameter(XDXS, "0.2", electricField.getStationCode())).add(BigDecimal.valueOf(1));
  249. BigDecimal referencePower = this.getPowerOfReference(powerStationStatusData);
  250. if (powerStationStatusData.getRealValue().compareTo(baseLinePower) < 0) {
  251. //实际功率 小于容量的 n% 不统计是否限电 全部视为不限电
  252. return false;
  253. } else {
  254. //参照功率 - 实际功率 > 实际功率 * 限电系数 ?? 大于就限电 小于就不限电
  255. return referencePower.compareTo(powerStationStatusData.getRealValue().multiply(coefficient)) > 0;
  256. }
  257. }
  258. /**
  259. * 初始化测风光法计算器
  260. */
  261. private void initCalculatorOfMeasuring() {
  262. this.calculatorOfMeasuring = null;
  263. }
  264. /**
  265. * 获取当下时间段的 短期功率和超短期功率的平均数
  266. *
  267. * @return 平均数
  268. */
  269. @SneakyThrows
  270. private BigDecimal getForecastPowerAvg() {
  271. long nowQuarterTime = DateMomentUtil.getMomentTime(System.currentTimeMillis(), 1, 900000L);
  272. BigDecimal dq = BigDecimal.valueOf(0);
  273. BigDecimal cdq = BigDecimal.valueOf(0);
  274. BigDecimal val;
  275. //获取当前的短期
  276. List<ForecastPowerShortTermHis> forecastPowerShortTermHisList = forecastPowerShortTermService.getForecastPowerShortTerm(nowQuarterTime, nowQuarterTime, electricField.getStationCode());
  277. if (null != forecastPowerShortTermHisList && forecastPowerShortTermHisList.size() > 0) {
  278. dq = forecastPowerShortTermHisList.get(0).getAbleValue();
  279. }
  280. //获取当前时刻超短期
  281. List<ForecastPowerUltraShortTermHis> forecastPowerUltraShortTermHisList = forecastPowerUltraShortTermService.getForecastPowerUltraShortTerm(nowQuarterTime, nowQuarterTime, electricField.getStationCode());
  282. if (null != forecastPowerUltraShortTermHisList && forecastPowerUltraShortTermHisList.size() > 0) {
  283. cdq = forecastPowerUltraShortTermHisList.get(0).getAbleValue();
  284. }
  285. val = (dq.add(cdq)).divide(new BigDecimal(2), 2, RoundingMode.HALF_DOWN);
  286. return val;
  287. }
  288. /**
  289. * 组装场站数据实体
  290. *
  291. * @param realPower 实际功率
  292. * @return {@link PowerStationStatusData}
  293. */
  294. public PowerStationStatusData packageData(BigDecimal realPower) {
  295. PowerStationStatusData powerStationStatusData = new PowerStationStatusData();
  296. try {
  297. //设定时间
  298. powerStationStatusData.setTime(DateTime.now().withMillisOfSecond(0).withSecondOfMinute(0).toDate());
  299. //设定容量
  300. powerStationStatusData.setCapacity(electricField.getCapacity());
  301. //设定并网设备数
  302. powerStationStatusData.setOnGridNum(electricField.getGridCE());
  303. //设定开机容量为装机容量
  304. powerStationStatusData.setOpenCapacity(electricField.getCapacity().subtract(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode())));
  305. //设定场站状态
  306. powerStationStatusData.setStatus(electricField.getElectricFieldTypeEnum().getCode());
  307. //设定实际功率
  308. powerStationStatusData.setRealValue(getRealPowerVal(realPower));
  309. //设定 样板机参照功率
  310. powerStationStatusData.setReferencePowerBySample(powerOfReferenceCalculatorBySample.getEstimatePower());
  311. if (powerStationStatusData.getReferencePowerBySample() == null || powerStationStatusData.getReferencePowerBySample().compareTo(powerStationStatusData.getRealValue()) < 0) {
  312. log.warn("样板机法计算值小于实际功率异常,值为:" + powerStationStatusData.getReferencePowerBySample());
  313. powerStationStatusData.setAbnormalOfSample(powerStationStatusData.getReferencePowerBySample());
  314. powerStationStatusData.setReferencePowerBySample(((electricField.getCapacity().subtract(powerStationStatusData.getRealValue())).multiply(BigDecimal.valueOf(random.nextFloat())).multiply(BigDecimal.valueOf(0.001))).add(powerStationStatusData.getRealValue()).setScale(2, RoundingMode.HALF_UP));
  315. } else if (powerStationStatusData.getReferencePowerBySample().compareTo(powerStationStatusData.getCapacity()) > 0) {
  316. log.warn("样板机法计算值超装机容量异常,值为:" + powerStationStatusData.getReferencePowerBySample());
  317. powerStationStatusData.setAbnormalOfSample(powerStationStatusData.getReferencePowerBySample());
  318. powerStationStatusData.setReferencePowerBySample(powerStationStatusData.getCapacity());
  319. }
  320. powerStationStatusData.setAblePowerBySample(powerOfReferenceCalculatorBySample.getEstimatePower().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_UP));
  321. if (powerStationStatusData.getAblePowerBySample().compareTo(powerStationStatusData.getRealValue()) < 0) {
  322. powerStationStatusData.setAblePowerBySample(powerStationStatusData.getReferencePowerBySample());
  323. }
  324. //设定 测风光法参照功率
  325. if (this.calculatorOfMeasuring != null) {
  326. powerStationStatusData.setReferencePowerByMeasuring(this.calculatorOfMeasuring.getData().setScale(2, RoundingMode.HALF_UP));
  327. }
  328. if (powerStationStatusData.getReferencePowerByMeasuring() == null || powerStationStatusData.getReferencePowerByMeasuring().compareTo(powerStationStatusData.getRealValue()) < 0) {
  329. log.warn("测风光法计算值小于实际功率异常,值为:" + powerStationStatusData.getReferencePowerByMeasuring());
  330. powerStationStatusData.setAbnormalOfMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
  331. powerStationStatusData.setReferencePowerByMeasuring(((electricField.getCapacity().subtract(powerStationStatusData.getRealValue())).multiply(BigDecimal.valueOf(random.nextFloat())).multiply(BigDecimal.valueOf(0.001))).add(powerStationStatusData.getRealValue()).setScale(2, RoundingMode.HALF_UP));
  332. } else if (powerStationStatusData.getReferencePowerByMeasuring().compareTo(powerStationStatusData.getCapacity()) > 0) {
  333. log.warn("测风光法计算值超装机容量异常,值为:" + powerStationStatusData.getReferencePowerByMeasuring());
  334. powerStationStatusData.setAbnormalOfMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
  335. powerStationStatusData.setReferencePowerByMeasuring(powerStationStatusData.getCapacity());
  336. }
  337. powerStationStatusData.setAblePowerByMeasuring(powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_UP));
  338. if (powerStationStatusData.getAblePowerByMeasuring().compareTo(powerStationStatusData.getRealValue()) < 0) {
  339. powerStationStatusData.setAblePowerByMeasuring(powerStationStatusData.getReferencePowerByMeasuring());
  340. }
  341. boolean isRationing = judgeIsRationing(powerStationStatusData);
  342. //设定是否限电
  343. powerStationStatusData.setIsRationingByAutoControl(isRationing);
  344. //设定理论和可用
  345. if (isRationing) {
  346. //限电情况下 平均功率和实际功率取大者 乘倍率
  347. switch (sysParameterService.getSysParameter("kyglqz", "1", electricField.getStationCode())) {
  348. case "2":
  349. powerStationStatusData.setAbleValue(powerStationStatusData.getReferencePowerBySample().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_DOWN));
  350. break;
  351. case "3":
  352. powerStationStatusData.setAbleValue(powerStationStatusData.getReferencePowerByMeasuring().multiply(getOpenRatio()).setScale(2, RoundingMode.HALF_DOWN));
  353. break;
  354. default: {
  355. BigDecimal avgPower = getForecastPowerAvg();
  356. BigDecimal randomNum = getRandomNum(new BigDecimal(sysParameterService.getSysParameter(KYGLJSMIN, "1", electricField.getStationCode())), new BigDecimal(sysParameterService.getSysParameter(KYGLJSMAX, "1.02", electricField.getStationCode())));
  357. if (avgPower.compareTo(powerStationStatusData.getRealValue()) > 0) {
  358. powerStationStatusData.setAbleValue(avgPower.multiply(randomNum).setScale(2, RoundingMode.HALF_UP));
  359. } else {
  360. powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(randomNum).setScale(2, RoundingMode.HALF_UP));
  361. }
  362. }
  363. }
  364. } else {
  365. //不限电 实际功率,理论功率,可用功率 理论=k*可用=k*实际
  366. powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(BigDecimal.ONE.add(getMagnificationK())).setScale(2, RoundingMode.HALF_DOWN));
  367. }
  368. if (powerStationStatusData.getOpenCapacity().compareTo(new BigDecimal(0)) != 0) {
  369. //设置理论功率
  370. powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue().multiply(BigDecimal.ONE.add(getMagnificationK())).add(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode()).multiply(powerStationStatusData.getRealValue().divide(powerStationStatusData.getOpenCapacity(), RoundingMode.CEILING))).setScale(2, RoundingMode.HALF_DOWN));
  371. } else {
  372. powerStationStatusData.setTheoryValue(new BigDecimal(0));
  373. }
  374. //设置站内受阻
  375. powerStationStatusData.setOnSiteObstructed(powerStationStatusData.getTheoryValue().subtract(powerStationStatusData.getAbleValue()));
  376. //设置站外受阻
  377. powerStationStatusData.setOffSiteObstructed(powerStationStatusData.getAbleValue().subtract(powerStationStatusData.getRealValue()));
  378. } catch (Exception e) {
  379. log.error("组装场站状态数据时发生异常", e);
  380. throw new RuntimeException("组装场站状态数据时发生异常");
  381. }
  382. if (powerStationStatusData.getAbleValue().compareTo(BigDecimal.valueOf(-99)) == 0) {
  383. powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue());
  384. powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue());
  385. } else {
  386. if (powerStationStatusData.getAbleValue().compareTo(powerStationStatusData.getRealValue()) < 0) {
  387. powerStationStatusData.setAbleValue(powerStationStatusData.getRealValue().multiply(getMagnificationK().add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_DOWN));
  388. }
  389. if (powerStationStatusData.getTheoryValue().compareTo(powerStationStatusData.getAbleValue()) < 0) {
  390. powerStationStatusData.setTheoryValue(powerStationStatusData.getAbleValue().multiply(getMagnificationK().add(BigDecimal.ONE)).setScale(2, RoundingMode.HALF_DOWN));
  391. }
  392. }
  393. return powerStationStatusData;
  394. }
  395. /**
  396. * 得到随机num
  397. *
  398. * @param min 最小值
  399. * @param max 最大值
  400. * @return {@link BigDecimal}
  401. */
  402. public BigDecimal getRandomNum(BigDecimal min, BigDecimal max) {
  403. return BigDecimal.valueOf(random.nextDouble()).multiply(max.subtract(min)).add(min).setScale(2, RoundingMode.HALF_DOWN);
  404. }
  405. /**
  406. * 获取当前时间开机容量比 即开机容量和装机容量的比值
  407. */
  408. public BigDecimal getOpenRatio() {
  409. return BigDecimal.ONE.subtract(overHaulPlanService.getOverhaulCapacityByStationCode(electricField.getStationCode()).divide(electricField.getCapacity(), 2, RoundingMode.HALF_DOWN));
  410. }
  411. /**
  412. * 获取0.015 - 0.02 的随机数
  413. *
  414. * @return {@link BigDecimal}
  415. */
  416. public BigDecimal getMagnificationK() {
  417. return getRandomNum(BigDecimal.valueOf(0.015), BigDecimal.valueOf(0.02));
  418. }
  419. public DateTime getSunUpTime() {
  420. updateTodaySunRiseSetTime();
  421. return this.sunUpTime;
  422. }
  423. public DateTime getSunDownTime() {
  424. updateTodaySunRiseSetTime();
  425. return this.sunDownTime;
  426. }
  427. /**
  428. * 刷新今天日出日落时间
  429. * 由于日升日落 要求精度不是很高 而且预测的数据也比较准确
  430. */
  431. public void updateTodaySunRiseSetTime() {
  432. if (sunUpTime == null || sunUpTime.isBefore(DateTime.now().withMillisOfDay(0))) {
  433. Date date = DateTime.now().toDate();
  434. String sunRiseTimeString = SunRiseSet.getSunrise(electricField.getLongitude(), electricField.getLatitude(), date);
  435. String sunSetTimeString = SunRiseSet.getSunset(electricField.getLongitude(), electricField.getLatitude(), date);
  436. if (StringUtils.isNotEmpty(sunRiseTimeString)) {
  437. try {
  438. sunUpTime = LocalTime.parse(sunRiseTimeString).toDateTimeToday();
  439. } catch (Exception e) {
  440. sunUpTime = null;
  441. }
  442. }
  443. if (StringUtils.isNotEmpty(sunSetTimeString)) {
  444. try {
  445. this.sunDownTime = LocalTime.parse(sunSetTimeString).toDateTimeToday();
  446. } catch (Exception e) {
  447. this.sunDownTime = null;
  448. }
  449. }
  450. }
  451. }
  452. class CalculatorOfMeasuring {
  453. /**
  454. * 正式的
  455. */
  456. public String formula;
  457. /**
  458. * 用于替换公式的值
  459. */
  460. public Map<String, Object> dataMap = new HashMap<>();
  461. /**
  462. * 原始数据池
  463. */
  464. Map<String, String> oDataMap = new HashMap<>();
  465. /**
  466. * 气象站或测风塔的编号
  467. */
  468. public Integer equipmentNo;
  469. /**
  470. * 计算表达式
  471. */
  472. Expression compiledExp;
  473. /**
  474. * 初始化
  475. *//* 光伏组件效率*(1-0.003*(光伏组件温度-25))*math.pow(0.992,3)*总辐射*光伏组件总面积/1000000*0.79*/
  476. public void init() throws Exception {
  477. AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_DECIMAL, true);
  478. this.formula = sysParameterService.getSysParameter(LLGLGS, "", electricField.getStationCode());
  479. try {
  480. this.compiledExp = AviatorEvaluator.compile(formula);
  481. } catch (ExpressionSyntaxErrorException e) {
  482. log.error("公式解析失败,公式不可用", e);
  483. throw new RuntimeException("公式解析失败,公式不可用");
  484. }
  485. if (electricField.getElectricFieldTypeEnum() == ElectricFieldTypeEnum.E1) {
  486. WeatherStationInfoService weatherStationInfoService = SpringContextHolder.getBean(WeatherStationInfoService.class);
  487. List<WeatherStationInfo> l = weatherStationInfoService.getAll();
  488. if (l.size() >= 1) {
  489. this.equipmentNo = l.get(0).getId();
  490. } else {
  491. throw new Exception("系统缺少气象站信息");
  492. }
  493. } else {
  494. WindTowerInfoService windTowerInfoService = SpringContextHolder.getBean(WindTowerInfoService.class);
  495. List<WindTowerInfo> l = windTowerInfoService.getAll();
  496. if (l.size() >= 1) {
  497. this.equipmentNo = l.get(0).getId();
  498. } else {
  499. throw new Exception("系统缺少测风塔信息");
  500. }
  501. }
  502. }
  503. public void updateDates() {
  504. if (electricField.getElectricFieldTypeEnum() == ElectricFieldTypeEnum.E1) {
  505. //光伏
  506. oDataMap = redisUtils.hgetall("qxz-" + electricField.getStationCode() + "-" + equipmentNo);
  507. if (oDataMap.containsKey("cellT")) {
  508. dataMap.put("光伏组件温度", new BigDecimal(oDataMap.get("cellT")));
  509. }
  510. if (oDataMap.containsKey("globalR")) {
  511. dataMap.put("总辐射", new BigDecimal(oDataMap.get("globalR")));
  512. }
  513. } else {
  514. oDataMap = redisUtils.hgetall("cft-" + electricField.getStationCode() + "-" + equipmentNo);
  515. if (oDataMap.containsKey("wsInstHubHeight")) {
  516. dataMap.put("轮毂风速", new BigDecimal(oDataMap.get("wsInstHubHeight")));
  517. }
  518. }
  519. }
  520. BigDecimal getData() {
  521. return new BigDecimal(compiledExp.execute(dataMap) + "");
  522. }
  523. }
  524. }