ConsumptionJob.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package com.usky.rule.jobs;
  2. import com.usky.common.security.utils.SecurityUtils;
  3. import com.usky.demo.RemoteTsdbProxyService;
  4. import com.usky.demo.domain.HistorysInnerRequestVO;
  5. import com.usky.demo.domain.HistorysInnerResultVO;
  6. import com.usky.demo.domain.MetricVO;
  7. import com.usky.rule.domain.RuleEngine;
  8. import com.usky.rule.vo.Result;
  9. import com.usky.rule.util.JsonUtil;
  10. import com.usky.rule.enums.TimeTypeEnum;
  11. import com.usky.rule.enums.TriggerTypeEnum;
  12. import com.usky.rule.enums.TriggerValueTypeEnum;
  13. import com.usky.rule.vo.DataPointVO;
  14. import com.usky.rule.vo.Condition;
  15. import com.usky.rule.vo.Expression;
  16. import com.usky.rule.vo.RuleEngineDetail;
  17. import com.usky.rule.vo.TimeRange;
  18. import com.usky.rule.vo.action.RuleEngineAction;
  19. import com.usky.rule.vo.constraint.DeviceConstraint;
  20. import com.usky.rule.vo.log.RuleEngineDetailLog;
  21. import com.usky.rule.vo.trigger.DeviceTrigger;
  22. import com.usky.rule.vo.visualization.SimpleVO;
  23. import com.usky.rule.subscribe.TriggerDeviceUtil;
  24. import com.usky.rule.util.RuleEngineUtil;
  25. //import com.usky.rule.DeviceService;
  26. import com.usky.rule.service.RuleEngineService;
  27. import java.math.BigDecimal;
  28. import java.time.LocalDateTime;
  29. import java.time.temporal.ChronoUnit;
  30. import java.util.*;
  31. import javax.annotation.Resource;
  32. import org.cache2k.Cache;
  33. import org.cache2k.CacheEntry;
  34. import org.quartz.DisallowConcurrentExecution;
  35. import org.quartz.Job;
  36. import org.quartz.JobExecutionContext;
  37. import org.quartz.JobExecutionException;
  38. import org.springframework.beans.factory.annotation.Autowired;
  39. import org.springframework.util.Assert;
  40. import org.springframework.util.CollectionUtils;
  41. @DisallowConcurrentExecution
  42. public class ConsumptionJob implements Job {
  43. @Resource
  44. private Cache<Long, List<DeviceTrigger>> consumptionTriggerCache;
  45. @Resource
  46. private TriggerDeviceUtil triggerDeviceUtil;
  47. @Resource
  48. private RuleEngineUtil ruleEngineUtil;
  49. @Autowired
  50. private RemoteTsdbProxyService remoteTsdbProxyService;
  51. @Resource
  52. private RuleEngineService ruleEngineService;
  53. public ConsumptionJob() {
  54. }
  55. public void execute(JobExecutionContext context) throws JobExecutionException {
  56. LocalDateTime[] times = new LocalDateTime[2];
  57. LocalDateTime now = LocalDateTime.now();
  58. for(CacheEntry<Long, List<DeviceTrigger>> entry : this.consumptionTriggerCache.entries()) {
  59. Long engineId = (Long)entry.getKey();
  60. RuleEngine ruleEngine = (RuleEngine)this.ruleEngineService.getById(engineId);
  61. Long spaceId = ruleEngine.getSpaceId();
  62. RuleEngineDetail ruleEngineDetail = (RuleEngineDetail)JsonUtil.toObject(ruleEngine.getDetail(), RuleEngineDetail.class);
  63. List<RuleEngineAction> actions = this.ruleEngineService.getActions(ruleEngineDetail.getActions());
  64. if (!actions.isEmpty()) {
  65. RuleEngineDetailLog ruleEngineDetailLog = new RuleEngineDetailLog();
  66. boolean spaceTriggerAction = false;
  67. label77:
  68. for(DeviceTrigger trigger : entry.getValue()) {
  69. if (!CollectionUtils.isEmpty(trigger.getDevices())) {
  70. label75:
  71. for(SimpleVO device : trigger.getDevices()) {
  72. List<Condition> meetTriggerConditionList = new ArrayList();
  73. List<Condition> triggerConditions = trigger.getConditions();
  74. StringBuilder boolConstraintExp = new StringBuilder();
  75. Map<String, String> valueMap = new HashMap();
  76. boolConstraintExp.append("(");
  77. for(int i = 0; i < triggerConditions.size(); ++i) {
  78. Condition triggerCondition = (Condition)triggerConditions.get(i);
  79. String identifier = triggerCondition.getIdentifier();
  80. Expression expression = triggerCondition.getExpression();
  81. TimeRange timeRange = triggerCondition.getTimeRange();
  82. String valueCondition = triggerCondition.getCondition();
  83. String operator = triggerCondition.getOperator();
  84. if (i != 0 && preAssertFalse(boolConstraintExp, operator)) {
  85. continue label75;
  86. }
  87. initStartTimeAndEndTime(now, times, timeRange);
  88. HistorysInnerRequestVO requestVO = new HistorysInnerRequestVO();
  89. requestVO.setDeviceuuid(Collections.singletonList(device.getDeviceUuid()));
  90. requestVO.setMetrics(Collections.singletonList(identifier));
  91. requestVO.setStartTime(times[0].toString());
  92. requestVO.setEndTime(times[1].toString());
  93. List<HistorysInnerResultVO> result = remoteTsdbProxyService.queryHistoryDeviceData(requestVO);
  94. List<DataPointVO> dataPointVOList = findDataPointsForMetric(result, device.getDeviceUuid(), identifier);
  95. if (dataPointVOList.isEmpty()) {
  96. boolConstraintExp.append(false);
  97. } else {
  98. DataPointVO first = dataPointVOList.get(0);
  99. DataPointVO last = dataPointVOList.get(dataPointVOList.size() - 1);
  100. if (first.getValue() == null || last.getValue() == null) {
  101. boolConstraintExp.append(false);
  102. } else {
  103. BigDecimal currValue = last.getValue().subtract(first.getValue());
  104. boolean meetCondition = TriggerDeviceUtil.isMeetConsumptionCondition(currValue, valueCondition, expression.getX());
  105. if (meetCondition) {
  106. meetTriggerConditionList.add(triggerCondition);
  107. valueMap.put(identifier, currValue.toString());
  108. }
  109. boolConstraintExp.append(meetCondition);
  110. }
  111. }
  112. }
  113. spaceTriggerAction = TriggerDeviceUtil.getBooleanExpressionValue(boolConstraintExp + ")");
  114. if (spaceTriggerAction) {
  115. this.triggerDeviceUtil.setTriggerLog(now, ruleEngineDetailLog, device.getId(), device.getName(), TriggerValueTypeEnum.CONSUMPTION.getValue(), TriggerTypeEnum.DEVICE, meetTriggerConditionList, valueMap);
  116. break label77;
  117. }
  118. }
  119. }
  120. }
  121. if (spaceTriggerAction) {
  122. List<DeviceConstraint> deviceConstraints = this.ruleEngineService.getDeviceConstraints(ruleEngineDetail.getConstraints());
  123. boolean constraintAction = this.triggerDeviceUtil.meetConstraintAction(deviceConstraints, ruleEngineDetailLog);
  124. if (constraintAction) {
  125. this.ruleEngineUtil.performMultipleDevicesControl(engineId, true, TriggerTypeEnum.DEVICE.getType(), ruleEngine.getProjectId(), spaceId, actions, ruleEngineDetailLog);
  126. }
  127. }
  128. }
  129. }
  130. }
  131. public static void initStartTimeAndEndTime(LocalDateTime now, LocalDateTime[] times, TimeRange timeRange) {
  132. Integer start = timeRange.getStart();
  133. Integer end = timeRange.getEnd();
  134. Assert.notNull(start, "start不能为空");
  135. Assert.notNull(end, "end不能为空");
  136. Assert.isTrue(end - start > 0, "结束时间必须大于起始时间");
  137. LocalDateTime startTime = null;
  138. LocalDateTime endTime = null;
  139. switch (TimeTypeEnum.get(timeRange.getType())) {
  140. case HOUR:
  141. endTime = now.truncatedTo(ChronoUnit.HOURS);
  142. int hour = endTime.getHour();
  143. if (hour < start) {
  144. startTime = endTime.minusDays(1L).withHour(start);
  145. } else {
  146. startTime = endTime.withHour(start);
  147. }
  148. break;
  149. case DAY:
  150. case WEEK:
  151. endTime = now.truncatedTo(ChronoUnit.DAYS);
  152. int day = endTime.getDayOfMonth();
  153. if (day < start) {
  154. startTime = endTime.minusMonths(1L).withDayOfMonth(start);
  155. } else {
  156. startTime = endTime.withDayOfMonth(start);
  157. }
  158. }
  159. times[0] = startTime;
  160. times[1] = endTime;
  161. }
  162. public static boolean preAssertFalse(StringBuilder boolConstraintExp, String operator) {
  163. if (TriggerDeviceUtil.checkOperator(operator)) {
  164. throw new RuntimeException("operator的值必须是 && or ||");
  165. } else {
  166. boolConstraintExp.append(" ").append(operator).append(" ");
  167. return !TriggerDeviceUtil.getBooleanExpressionValue(boolConstraintExp + "true)");
  168. }
  169. }
  170. private static List<DataPointVO> findDataPointsForMetric(List<HistorysInnerResultVO> historyList, String deviceUuid, String metricIdentifier) {
  171. if (CollectionUtils.isEmpty(historyList)) {
  172. return Collections.emptyList();
  173. }
  174. HistorysInnerResultVO row = null;
  175. for (HistorysInnerResultVO vo : historyList) {
  176. if (vo != null && deviceUuid != null && deviceUuid.equals(vo.getDeviceuuid())) {
  177. row = vo;
  178. break;
  179. }
  180. }
  181. if (row == null) {
  182. row = historyList.get(0);
  183. }
  184. List<MetricVO> metrics = row.getMetrics();
  185. if (CollectionUtils.isEmpty(metrics)) {
  186. return Collections.emptyList();
  187. }
  188. for (MetricVO m : metrics) {
  189. if (m != null && metricIdentifier != null && metricIdentifier.equals(m.getMetric())) {
  190. return metricItemsToDataPoints(m.getMetricItems());
  191. }
  192. }
  193. return Collections.emptyList();
  194. }
  195. private static List<DataPointVO> metricItemsToDataPoints(List<Map<String, Object>> metricItems) {
  196. if (CollectionUtils.isEmpty(metricItems)) {
  197. return Collections.emptyList();
  198. }
  199. List<DataPointVO> out = new ArrayList<>(metricItems.size());
  200. for (Map<String, Object> item : metricItems) {
  201. if (item == null) {
  202. continue;
  203. }
  204. Object ts = item.get("timestamp");
  205. Object val = item.get("value");
  206. if (ts == null || val == null) {
  207. continue;
  208. }
  209. BigDecimal num = toBigDecimal(val);
  210. if (num == null) {
  211. continue;
  212. }
  213. out.add(new DataPointVO(ts.toString(), num));
  214. }
  215. return out;
  216. }
  217. private static BigDecimal toBigDecimal(Object val) {
  218. if (val instanceof BigDecimal) {
  219. return (BigDecimal) val;
  220. }
  221. if (val instanceof Number) {
  222. return BigDecimal.valueOf(((Number) val).doubleValue());
  223. }
  224. try {
  225. return new BigDecimal(val.toString().trim());
  226. } catch (Exception e) {
  227. return null;
  228. }
  229. }
  230. }