|
|
@@ -0,0 +1,643 @@
|
|
|
+package com.usky.rule.service.impl;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
|
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.usky.common.core.bean.CommonPage;
|
|
|
+import com.usky.common.mybatis.core.AbstractCrudService;
|
|
|
+import com.usky.common.security.utils.SecurityUtils;
|
|
|
+import com.usky.rule.cache.DeviceTriggerIncludeMinuteCache;
|
|
|
+import com.usky.rule.config.CronTaskManager;
|
|
|
+import com.usky.rule.domain.*;
|
|
|
+import com.usky.rule.enums.ActionTypeEnum;
|
|
|
+import com.usky.rule.enums.ConstraintTypeEnum;
|
|
|
+import com.usky.rule.enums.TriggerTypeEnum;
|
|
|
+import com.usky.rule.exception.BizException;
|
|
|
+import com.usky.rule.mapper.RuleEngineCronMapper;
|
|
|
+import com.usky.rule.mapper.RuleEngineDeviceMapper;
|
|
|
+import com.usky.rule.mapper.RuleEngineLogMapper;
|
|
|
+import com.usky.rule.mapper.RuleEngineMapper;
|
|
|
+import com.usky.rule.service.*;
|
|
|
+import com.usky.rule.util.CronUtil;
|
|
|
+import com.usky.rule.util.JsonUtil;
|
|
|
+import com.usky.rule.vo.*;
|
|
|
+import com.usky.rule.vo.action.DeviceControlAction;
|
|
|
+import com.usky.rule.vo.action.RuleEngineAction;
|
|
|
+import com.usky.rule.vo.constraint.CronConstraint;
|
|
|
+import com.usky.rule.vo.constraint.DeviceConstraint;
|
|
|
+import com.usky.rule.vo.trigger.CronTrigger;
|
|
|
+import com.usky.rule.vo.trigger.DeviceTrigger;
|
|
|
+import com.usky.rule.vo.trigger.SpaceTrigger;
|
|
|
+import com.usky.rule.vo.visualization.SimpleVO;
|
|
|
+import feign.Util;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.context.annotation.Lazy;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.PostConstruct;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class RuleEngineServiceImpl extends AbstractCrudService<RuleEngineMapper, RuleEngine> implements RuleEngineService {
|
|
|
+ private final RuleEngineCronService ruleEngineCronService;
|
|
|
+ private final RuleEngineDeviceService ruleEngineDeviceService;
|
|
|
+ private static final Map<String, Class<?>> triggerMap = new HashMap();
|
|
|
+ private static final Map<String, Class<?>> constraintMap = new HashMap();
|
|
|
+ private static final Map<String, Class<?>> actionMap = new HashMap();
|
|
|
+ @Autowired
|
|
|
+ private RuleEngineLogService ruleEngineLogService;
|
|
|
+ @Autowired
|
|
|
+ private RuleEngineCronMapper ruleEngineCronMapper;
|
|
|
+ @Autowired
|
|
|
+ private RuleEngineDeviceMapper ruleEngineDeviceMapper;
|
|
|
+ @Autowired
|
|
|
+ private DeviceTriggerIncludeMinuteCache deviceTriggerIncludeMinuteCache;
|
|
|
+ @Autowired
|
|
|
+ private CronTaskManager cronTaskManager;
|
|
|
+ @Lazy
|
|
|
+ @Autowired
|
|
|
+ private RuleEngineDetailService ruleEngineDetailService;
|
|
|
+ @Autowired
|
|
|
+ private BaseSpaceService baseSpaceService;
|
|
|
+
|
|
|
+ public RuleEngineServiceImpl(RuleEngineCronService ruleEngineCronService, RuleEngineDeviceService ruleEngineDeviceService) {
|
|
|
+ this.ruleEngineCronService = ruleEngineCronService;
|
|
|
+ this.ruleEngineDeviceService = ruleEngineDeviceService;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ @PostConstruct
|
|
|
+ public void init() {
|
|
|
+
|
|
|
+ triggerMap.put(TriggerTypeEnum.CRON.getType(), CronTrigger.class);
|
|
|
+ triggerMap.put(TriggerTypeEnum.DEVICE.getType(), DeviceTrigger.class);
|
|
|
+ triggerMap.put(TriggerTypeEnum.SPACE.getType(), SpaceTrigger.class);
|
|
|
+ constraintMap.put(ConstraintTypeEnum.CRON.getType(), CronConstraint.class);
|
|
|
+ constraintMap.put(ConstraintTypeEnum.DEVICE.getType(), DeviceConstraint.class);
|
|
|
+// actionMap.put(ActionTypeEnum.ALARM_EVENT.getType(), AlarmEventAction.class);
|
|
|
+// actionMap.put(ActionTypeEnum.WORK_ORDER.getType(), WorkOrderAction.class);
|
|
|
+ actionMap.put(ActionTypeEnum.DEVICE_CONTROL.getType(), DeviceControlAction.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void add(RuleEngine ruleEngine) {
|
|
|
+ if (ruleEngine.getStatus() == null) {
|
|
|
+ ruleEngine.setStatus(0);
|
|
|
+ }
|
|
|
+ ruleEngine.setCreatedBy(SecurityUtils.getUsername());
|
|
|
+ ruleEngine.setTenantId(SecurityUtils.getTenantId());
|
|
|
+ getBaseMapper().insert(ruleEngine);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void update(RuleEngine ruleEngine) {
|
|
|
+ ruleEngine.setUpdatedBy(SecurityUtils.getUsername());
|
|
|
+ getBaseMapper().updateById(ruleEngine);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除规则(参考 leo RuleEngineDetailServiceImpl.remove):
|
|
|
+ * 1. 校验 id 非空
|
|
|
+ * 2. 清理该规则下的 cron 任务数据(对应 leo cronTaskManager.deleteAllJobsInJobGroup)
|
|
|
+ * 3. 清理该规则关联的设备绑定(对应 leo historyRecordCache.deleteConditions 的关联数据)
|
|
|
+ * 4. 删除规则主表
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void remove(Long id) {
|
|
|
+ if (id == null) {
|
|
|
+ throw new IllegalArgumentException("id不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ deviceTriggerIncludeMinuteCache.deleteConditions(id);
|
|
|
+ cronTaskManager.deleteAllJobsInJobGroup(id);
|
|
|
+ ruleEngineCronMapper.deleteByRuleEngineId(id);
|
|
|
+ ruleEngineDeviceMapper.deleteByRuleEngineId(id);
|
|
|
+ getBaseMapper().deleteById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RuleEngine getById(Long id) {
|
|
|
+ return getBaseMapper().selectById(id, SecurityUtils.getTenantId());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public CommonPage<RuleEngine> pageList(RuleEnginePageRequest request) {
|
|
|
+ List<Long> ids = new ArrayList();
|
|
|
+ if (request.getSpaceId() != null) {
|
|
|
+ ids.add(request.getSpaceId());
|
|
|
+ ids.addAll(getBaseMapper().recursiveAllChildrenNodeIds(request.getSpaceId()));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ IPage<RuleEngine> page = new Page<>(request.getPageNum(), request.getPageSize());
|
|
|
+ LambdaQueryWrapper<RuleEngine> queryWrapper = Wrappers.lambdaQuery();
|
|
|
+ queryWrapper.in(CollectionUtils.isNotEmpty(ids), RuleEngine::getSpaceId, ids)
|
|
|
+ .like(StringUtils.isNotBlank(request.getName()),RuleEngine::getName, request.getName())
|
|
|
+ .eq(request.getStatus() != null,RuleEngine::getStatus,request.getStatus())
|
|
|
+ .eq(RuleEngine::getTenantId,SecurityUtils.getTenantId())
|
|
|
+ .orderByDesc(RuleEngine::getId);
|
|
|
+ page = this.page(page, queryWrapper);
|
|
|
+
|
|
|
+ List<Long> spaceIds = page.getRecords().stream().map(RuleEngine::getSpaceId).distinct().collect(Collectors.toList());
|
|
|
+ List<BaseSpace> spaceList = baseSpaceService.listByIds(spaceIds);
|
|
|
+ Map<Long, BaseSpace> spaceMap = (Map)spaceList.stream().collect(Collectors.toMap(BaseSpace::getId, (s) -> s));
|
|
|
+ page.getRecords().forEach((r) -> r.setSpaceName(((BaseSpace)spaceMap.get(r.getSpaceId())).getName()));
|
|
|
+
|
|
|
+ return new CommonPage<>(page.getRecords(), page.getTotal(), request.getPageSize(), request.getPageNum());
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<RuleEngine> list(RuleEnginePageRequest request) {
|
|
|
+ List<Long> ids = new ArrayList();
|
|
|
+ if (request.getSpaceId() != null) {
|
|
|
+ ids.add(request.getSpaceId());
|
|
|
+ ids.addAll(getBaseMapper().recursiveAllChildrenNodeIds(request.getSpaceId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ LambdaQueryWrapper<RuleEngine> queryWrapper = Wrappers.lambdaQuery();
|
|
|
+ queryWrapper.in(CollectionUtils.isNotEmpty(ids), RuleEngine::getSpaceId, ids)
|
|
|
+ .like(StringUtils.isNotBlank(request.getName()),RuleEngine::getName, request.getName())
|
|
|
+ .eq(request.getStatus() != null,RuleEngine::getStatus,request.getStatus())
|
|
|
+ .eq(RuleEngine::getTenantId,SecurityUtils.getTenantId());
|
|
|
+ List<RuleEngine> ruleEngines = this.list(queryWrapper);
|
|
|
+ return ruleEngines;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateStatus(Long id, Integer status) {
|
|
|
+ LambdaQueryWrapper<RuleEngine> wrapper = Wrappers.lambdaQuery();
|
|
|
+ wrapper.eq(RuleEngine::getId, id)
|
|
|
+ .eq(RuleEngine::getTenantId,SecurityUtils.getTenantId());
|
|
|
+ RuleEngine engine = (RuleEngine)this.getOne(wrapper);
|
|
|
+ RuleEngineDTO engineDTO = new RuleEngineDTO();
|
|
|
+ engineDTO.setId(id);
|
|
|
+ engineDTO.setStatus(engine.getStatus() == 1 ? 0 : 1);
|
|
|
+ engineDTO.setProjectId(engine.getProjectId());
|
|
|
+ engineDTO.setName(engine.getName());
|
|
|
+ engineDTO.setDetail(engine.getDetail());
|
|
|
+ getBaseMapper().updateStatus(id, status);
|
|
|
+
|
|
|
+ ruleEngineDetailService.update(engineDTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<RuleEngine> listEnabledByProjectId(Long projectId) {
|
|
|
+ Integer tenantId = null;
|
|
|
+ try {
|
|
|
+ tenantId = SecurityUtils.getTenantId();
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ return getBaseMapper().selectEnabledByProjectId(projectId, tenantId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void ruleEngineConfig(RuleEngineDTO dto) {
|
|
|
+ if (dto.getId() == null) {
|
|
|
+ throw new BizException("id不能为空");
|
|
|
+ }
|
|
|
+ RuleEngine rule = this.getById(dto.getId());
|
|
|
+ if (rule != null) {
|
|
|
+ String detail = dto.getDetail();
|
|
|
+
|
|
|
+ RuleEngineDetail ruleEngineDetail;
|
|
|
+ rule.setDetail(detail);
|
|
|
+ rule.setUpdateTime(LocalDateTime.now());
|
|
|
+ try {
|
|
|
+ ruleEngineDetail = JsonUtil.toObject(detail, RuleEngineDetail.class);
|
|
|
+ } catch (Exception var13) {
|
|
|
+ throw new BizException("json格式有误");
|
|
|
+ }
|
|
|
+
|
|
|
+ this.verifyJson(ruleEngineDetail);
|
|
|
+ this.updateById(rule);
|
|
|
+
|
|
|
+ Long ruleEngineId = rule.getId();
|
|
|
+ Integer tenantId = rule.getTenantId();
|
|
|
+
|
|
|
+ ruleEngineCronMapper.deleteByRuleEngineId(ruleEngineId);
|
|
|
+ List<RuleEngineDetail.CommonVO> triggers = ruleEngineDetail.getTriggers();
|
|
|
+ List<CronTrigger> cronTriggers = this.getCronTriggers(triggers);
|
|
|
+ if (cronTriggers != null && !cronTriggers.isEmpty()) {
|
|
|
+ cronTriggers.forEach((c) -> {
|
|
|
+ RuleEngineCron cron = new RuleEngineCron();
|
|
|
+ cron.setRuleEngineId(ruleEngineId);
|
|
|
+ cron.setCron(c.getCron().trim());
|
|
|
+ cron.setCreatedBy(rule.getCreatedBy());
|
|
|
+ cron.setUpdatedBy(rule.getUpdatedBy());
|
|
|
+ cron.setTenantId(tenantId);
|
|
|
+ ruleEngineCronMapper.insert(cron);
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ ruleEngineDeviceMapper.deleteByRuleEngineId(ruleEngineId);
|
|
|
+ List<DeviceTrigger> deviceTriggers = this.getDeviceTriggers(triggers);
|
|
|
+ if (deviceTriggers != null && !deviceTriggers.isEmpty()) {
|
|
|
+ deviceTriggers.forEach((c) -> {
|
|
|
+ List<SimpleVO> devices = c.getDevices();
|
|
|
+ List<Condition> conditionsList = c.getConditions();
|
|
|
+ devices.forEach((d) -> conditionsList.forEach((conditions) -> {
|
|
|
+ RuleEngineDevice dev = new RuleEngineDevice();
|
|
|
+ dev.setRuleEngineId(ruleEngineId);
|
|
|
+ dev.setDeviceId(d.getId());
|
|
|
+ dev.setIdentifier(conditions.getIdentifier());
|
|
|
+ dev.setProductId(c.getProductId());
|
|
|
+ dev.setCreatedBy(rule.getCreatedBy());
|
|
|
+ dev.setUpdatedBy(rule.getUpdatedBy());
|
|
|
+ dev.setTenantId(tenantId);
|
|
|
+ ruleEngineDeviceMapper.insert(dev);
|
|
|
+ }));
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ RuleEngineDTO engineDTO = new RuleEngineDTO();
|
|
|
+ engineDTO.setId(rule.getId());
|
|
|
+ engineDTO.setProjectId(rule.getProjectId());
|
|
|
+ engineDTO.setName(rule.getName());
|
|
|
+ engineDTO.setStatus(rule.getStatus());
|
|
|
+ engineDTO.setDetail(rule.getDetail());
|
|
|
+ ruleEngineDetailService.update(engineDTO);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void verifyJson(RuleEngineDetail ruleEngineDetail) {
|
|
|
+ List<RuleEngineDetail.CommonVO> triggers = ruleEngineDetail.getTriggers();
|
|
|
+ if (CollectionUtils.isNotEmpty(triggers)) {
|
|
|
+ for(RuleEngineDetail.CommonVO vo : triggers) {
|
|
|
+ this.triggerVerify(vo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<RuleEngineDetail.CommonVO> constraints = ruleEngineDetail.getConstraints();
|
|
|
+ if (CollectionUtils.isNotEmpty(constraints)) {
|
|
|
+ for(RuleEngineDetail.CommonVO vo : constraints) {
|
|
|
+ this.constraintVerify(vo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<RuleEngineDetail.CommonVO> actions = ruleEngineDetail.getActions();
|
|
|
+ if (CollectionUtils.isNotEmpty(actions)) {
|
|
|
+ for(RuleEngineDetail.CommonVO vo : actions) {
|
|
|
+ this.actionVerify(vo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private void triggerVerify(RuleEngineDetail.CommonVO vo) {
|
|
|
+ String type = vo.getType();
|
|
|
+ String detail = vo.getDetail();
|
|
|
+ if (Util.isBlank(detail)) {
|
|
|
+ throw new BizException("触发条件不能为空");
|
|
|
+ } else {
|
|
|
+ if (TriggerTypeEnum.DEVICE.getType().equals(type)) {
|
|
|
+ DeviceTrigger deviceTrigger = (DeviceTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, DeviceTrigger.class);
|
|
|
+ if (deviceTrigger.getProductId() == null) {
|
|
|
+ throw new BizException("触发条件-产品不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Util.isBlank(deviceTrigger.getMethod())) {
|
|
|
+ throw new BizException("触发条件-触发方式不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean flag = deviceTrigger.getMethod().equals("consumption");
|
|
|
+ this.conditionsVerify(deviceTrigger.getConditions(), flag, "触发条件-");
|
|
|
+ if (CollectionUtils.isEmpty(deviceTrigger.getDevices())) {
|
|
|
+ throw new BizException("触发条件-设备不能为空");
|
|
|
+ }
|
|
|
+ } else if (TriggerTypeEnum.CRON.getType().equals(type)) {
|
|
|
+ CronTrigger cronTrigger = (CronTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, CronTrigger.class);
|
|
|
+ if (Util.isBlank(cronTrigger.getCron())) {
|
|
|
+ throw new BizException("触发条件-表达式不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!CronUtil.isCronMatched(cronTrigger.getCron())) {
|
|
|
+ throw new BizException("触发条件-表达式格式不正确");
|
|
|
+ }
|
|
|
+ } else if (TriggerTypeEnum.SPACE.getType().equals(type)) {
|
|
|
+ SpaceTrigger spaceTrigger = (SpaceTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, SpaceTrigger.class);
|
|
|
+ if (Util.isBlank(spaceTrigger.getMethod())) {
|
|
|
+ throw new BizException("触发条件-触发方式不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(spaceTrigger.getSpaces())) {
|
|
|
+ throw new BizException("触发条件-空间不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Condition> conditions = spaceTrigger.getConditions();
|
|
|
+ if (CollectionUtils.isEmpty(spaceTrigger.getConditions())) {
|
|
|
+ throw new BizException("触发条件-触发方式不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ for(int i = 0; i < conditions.size(); ++i) {
|
|
|
+ Condition condition = (Condition)conditions.get(i);
|
|
|
+ if (Util.isBlank(condition.getItemCode())) {
|
|
|
+ throw new BizException("触发条件-能源分项不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ TimeRange timeRange = condition.getTimeRange();
|
|
|
+ if (timeRange.getStart() == null || timeRange.getEnd() == null) {
|
|
|
+ throw new BizException("触发条件-开始或结束时间不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ Expression expression = condition.getExpression();
|
|
|
+ if (expression == null) {
|
|
|
+ throw new BizException("触发条件-限制条件不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i > 0 && Util.isBlank(condition.getOperator())) {
|
|
|
+ throw new BizException("触发条件-逻辑符不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void constraintVerify(RuleEngineDetail.CommonVO vo) {
|
|
|
+ String type = vo.getType();
|
|
|
+ String detail = vo.getDetail();
|
|
|
+ if (Util.isBlank(detail)) {
|
|
|
+ throw new BizException("约束条件不能为空");
|
|
|
+ } else {
|
|
|
+ if (type.equals(ConstraintTypeEnum.CRON.getType())) {
|
|
|
+ CronConstraint cronConstraint = (CronConstraint)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, CronConstraint.class);
|
|
|
+ if (Util.isBlank(cronConstraint.getCron())) {
|
|
|
+ throw new BizException("约束条件-表达式不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!CronUtil.isCronMatched(cronConstraint.getCron())) {
|
|
|
+ throw new BizException("约束条件-表达式格式不正确");
|
|
|
+ }
|
|
|
+ } else if (type.equals(ConstraintTypeEnum.DEVICE.getType())) {
|
|
|
+ DeviceConstraint deviceConstraint = (DeviceConstraint)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, DeviceConstraint.class);
|
|
|
+ if (deviceConstraint.getProductId() == null) {
|
|
|
+ throw new BizException("约束条件-产品不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(deviceConstraint.getDevices())) {
|
|
|
+ throw new BizException("约束条件-设备不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ this.conditionsVerify(deviceConstraint.getConditions(), false, "约束条件-");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void actionVerify(RuleEngineDetail.CommonVO vo) {
|
|
|
+ String type = vo.getType();
|
|
|
+ String detail = vo.getDetail();
|
|
|
+ if (Util.isBlank(detail)) {
|
|
|
+ throw new BizException("执行动作不能为空");
|
|
|
+ } else {
|
|
|
+ if (ActionTypeEnum.DEVICE_CONTROL.getType().equals(type)) {
|
|
|
+ DeviceControlAction deviceControlAction = (DeviceControlAction)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, detail, DeviceControlAction.class);
|
|
|
+ if (deviceControlAction.getProductId() == null) {
|
|
|
+ throw new BizException("执行动作-产品不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<DeviceControlAction.Functions> functionsList = deviceControlAction.getFunctions();
|
|
|
+ if (CollectionUtils.isEmpty(functionsList)) {
|
|
|
+ throw new BizException("执行动作-动作不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ for(DeviceControlAction.Functions functions : functionsList) {
|
|
|
+ if (functions.getDelaySeconds() == null) {
|
|
|
+ throw new BizException("执行动作-延时时间不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (functions.getDelaySeconds() < 1) {
|
|
|
+ throw new BizException("执行动作-延时时间不能低于1秒");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<SimpleVO> devices = deviceControlAction.getDevices();
|
|
|
+ if (CollectionUtils.isEmpty(devices)) {
|
|
|
+ throw new BizException("执行动作-设备不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void conditionsVerify(List<Condition> conditionList, boolean flag, String name) {
|
|
|
+ if (CollectionUtils.isEmpty(conditionList)) {
|
|
|
+ throw new BizException(name + "功能点及条件不能为空");
|
|
|
+ } else {
|
|
|
+ for(int i = 0; i < conditionList.size(); ++i) {
|
|
|
+ Condition condition = (Condition)conditionList.get(i);
|
|
|
+ if (i > 0 && Util.isBlank(condition.getOperator())) {
|
|
|
+ throw new BizException(name + "逻辑符不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (Util.isBlank(condition.getIdentifier())) {
|
|
|
+ throw new BizException(name + "功能点不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (flag) {
|
|
|
+ TimeRange timeRange = condition.getTimeRange();
|
|
|
+ if (timeRange.getStart() == null || timeRange.getEnd() == null) {
|
|
|
+ throw new BizException(name + "开始或结束时间不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Expression expression = condition.getExpression();
|
|
|
+ if (Util.isBlank(expression.getX()) && Util.isBlank(expression.getY()) && Util.isBlank(expression.getM())) {
|
|
|
+ throw new BizException(name + "限制条件不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public RuleEngineConfigDTO getEngineConfig(Long ruleEngineId) {
|
|
|
+ RuleEngine rule = getBaseMapper().selectById(ruleEngineId, SecurityUtils.getTenantId());
|
|
|
+ if (rule == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ RuleEngineConfigDTO dto = new RuleEngineConfigDTO();
|
|
|
+ dto.setRule(rule);
|
|
|
+ List<String> cronExprs = ruleEngineCronMapper.selectByRuleEngineId(ruleEngineId).stream()
|
|
|
+ .map(RuleEngineCron::getCron).collect(Collectors.toList());
|
|
|
+ dto.setCronExprs(cronExprs);
|
|
|
+ List<RuleEngineConfigDTO.RuleEngineDeviceItem> devices = new ArrayList<>();
|
|
|
+ for (RuleEngineDevice dev : ruleEngineDeviceMapper.selectByRuleEngineId(ruleEngineId)) {
|
|
|
+ RuleEngineConfigDTO.RuleEngineDeviceItem item = new RuleEngineConfigDTO.RuleEngineDeviceItem();
|
|
|
+ item.setDeviceId(dev.getDeviceId());
|
|
|
+ item.setIdentifier(dev.getIdentifier());
|
|
|
+ item.setProductId(dev.getProductId());
|
|
|
+ devices.add(item);
|
|
|
+ }
|
|
|
+ dto.setDevices(devices);
|
|
|
+ return dto;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void manualTrigger(Long ruleEngineId) {
|
|
|
+ RuleEngine rule = getBaseMapper().selectById(ruleEngineId, SecurityUtils.getTenantId());
|
|
|
+ if (rule == null) {
|
|
|
+ throw new IllegalArgumentException("规则不存在: " + ruleEngineId);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!ruleEngineDetailService.manualPerformDeviceControl(ruleEngineId)){
|
|
|
+ throw new BizException("触发未成功");
|
|
|
+ }
|
|
|
+ RuleEngineLog logRow = new RuleEngineLog();
|
|
|
+ logRow.setProjectId(rule.getProjectId());
|
|
|
+ logRow.setRuleEngineId(rule.getId());
|
|
|
+ logRow.setRuleEngineName(rule.getName());
|
|
|
+ logRow.setAutoTrigger(0);
|
|
|
+ logRow.setTriggerType("manual");
|
|
|
+ logRow.setAction(null);
|
|
|
+ logRow.setDetail(rule.getDetail());
|
|
|
+ logRow.setContent("手动触发");
|
|
|
+ logRow.setTime(new Date());
|
|
|
+ logRow.setTenantId(rule.getTenantId());
|
|
|
+ ruleEngineLogService.add(logRow);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void triggerByCron(Long ruleEngineId) {
|
|
|
+ RuleEngine rule = getBaseMapper().selectById(ruleEngineId, SecurityUtils.getTenantId());
|
|
|
+ if (rule == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ RuleEngineLog logRow = new RuleEngineLog();
|
|
|
+ logRow.setProjectId(rule.getProjectId());
|
|
|
+ logRow.setRuleEngineId(rule.getId());
|
|
|
+ logRow.setRuleEngineName(rule.getName());
|
|
|
+ logRow.setAutoTrigger(1);
|
|
|
+ logRow.setTriggerType("cron");
|
|
|
+ logRow.setAction(null);
|
|
|
+ logRow.setDetail(rule.getDetail());
|
|
|
+ logRow.setContent("定时触发");
|
|
|
+ logRow.setTime(new Date());
|
|
|
+ logRow.setTenantId(rule.getTenantId());
|
|
|
+ ruleEngineLogService.add(logRow);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public List<CronTrigger> getCronTriggers(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<CronTrigger> cronTriggerList = new ArrayList();
|
|
|
+ Class<?> clazz = (Class)triggerMap.get(TriggerTypeEnum.CRON.getType());
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (TriggerTypeEnum.CRON.getType().equals(commonVO.getType())) {
|
|
|
+ cronTriggerList.add((CronTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), clazz));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return cronTriggerList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<DeviceTrigger> getDeviceTriggers(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<DeviceTrigger> deviceTriggerList = new ArrayList();
|
|
|
+ Class<?> clazz = (Class)triggerMap.get(TriggerTypeEnum.DEVICE.getType());
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (TriggerTypeEnum.DEVICE.getType().equals(commonVO.getType())) {
|
|
|
+ deviceTriggerList.add((DeviceTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), clazz));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return deviceTriggerList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<SpaceTrigger> getSpaceTriggers(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<SpaceTrigger> deviceTriggerList = new ArrayList();
|
|
|
+ Class<?> clazz = (Class)triggerMap.get(TriggerTypeEnum.SPACE.getType());
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (TriggerTypeEnum.SPACE.getType().equals(commonVO.getType())) {
|
|
|
+ deviceTriggerList.add((SpaceTrigger)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), clazz));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return deviceTriggerList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<CronConstraint> getCronConstraints(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<CronConstraint> cronConstraintList = new ArrayList();
|
|
|
+ Class<?> clazz = (Class)constraintMap.get(ConstraintTypeEnum.CRON.getType());
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (TriggerTypeEnum.CRON.getType().equals(commonVO.getType())) {
|
|
|
+ cronConstraintList.add((CronConstraint)JsonUtil.toObject(commonVO.getDetail(), clazz));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return cronConstraintList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<DeviceConstraint> getDeviceConstraints(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<DeviceConstraint> deviceConstraintList = new ArrayList();
|
|
|
+ Class<?> clazz = (Class)constraintMap.get(ConstraintTypeEnum.DEVICE.getType());
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (ConstraintTypeEnum.DEVICE.getType().equals(commonVO.getType())) {
|
|
|
+ deviceConstraintList.add((DeviceConstraint)JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), clazz));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return deviceConstraintList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<RuleEngineAction> getActions(List<RuleEngineDetail.CommonVO> commonVOList) {
|
|
|
+ if (commonVOList != null && !commonVOList.isEmpty()) {
|
|
|
+ List<RuleEngineAction> actionList = new ArrayList();
|
|
|
+ commonVOList.forEach((commonVO) -> {
|
|
|
+ if (ActionTypeEnum.ALARM_EVENT.getType().equals(commonVO.getType())) {
|
|
|
+// actionList.add(JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), AlarmEventAction.class));
|
|
|
+ } else if (ActionTypeEnum.WORK_ORDER.getType().equals(commonVO.getType())) {
|
|
|
+// actionList.add(JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), WorkOrderAction.class));
|
|
|
+ } else if (ActionTypeEnum.DEVICE_CONTROL.getType().equals(commonVO.getType())) {
|
|
|
+ actionList.add(JsonUtil.toObject(JsonUtil.IGNORE_UNKNOWN_PROPERTIES_JSON_MAPPER, commonVO.getDetail(), DeviceControlAction.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ });
|
|
|
+ return actionList;
|
|
|
+ } else {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getName(Long ruleEngineId) {
|
|
|
+ RuleEngine ruleEngine = getBaseMapper().selectById(ruleEngineId, SecurityUtils.getTenantId());
|
|
|
+ return ruleEngine == null ? "" : ruleEngine.getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getDetail(Long ruleEngineId) {
|
|
|
+ RuleEngine ruleEngine = getBaseMapper().selectById(ruleEngineId, SecurityUtils.getTenantId());
|
|
|
+ return ruleEngine == null ? "" : ruleEngine.getDetail();
|
|
|
+ }
|
|
|
+}
|