fix:规则引擎

V0.5.x
xiwa 2023-06-18 14:34:59 +08:00
parent 983f29c4ea
commit 1ef0ac88a0
13 changed files with 112 additions and 142 deletions

View File

@ -0,0 +1,21 @@
package cc.iotkit.model.rule;
import lombok.Data;
/**
*
*
* @author sjg
*/
@Data
public class FilterConfig {
/**
*
*/
private String type;
/**
*
*/
protected String config;
}

View File

@ -14,6 +14,7 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Data @Data
@ -33,9 +34,9 @@ public class RuleInfo implements Owned<String> {
private String type; private String type;
private List<Listener> listeners; private List<FilterConfig> listeners;
private List<Filter> filters; private List<FilterConfig> filters;
private List<RuleAction> actions; private List<RuleAction> actions;
@ -47,16 +48,15 @@ public class RuleInfo implements Owned<String> {
private Long createAt; private Long createAt;
@Data public List<FilterConfig> getListeners() {
public static class Listener { return listeners == null ? new ArrayList<>() : listeners;
private String type;
protected String config;
} }
@Data public List<FilterConfig> getFilters() {
public static class Filter { return filters == null ? new ArrayList<>() : filters;
private String type;
protected String config;
} }
public List<RuleAction> getActions() {
return actions == null ? new ArrayList<>() : actions;
}
} }

View File

@ -44,13 +44,11 @@ public class TbRuleInfo {
@ApiModelProperty(value = "监听器") @ApiModelProperty(value = "监听器")
@AutoMapping(ignore = true) @AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true) @ReverseAutoMapping(ignore = true)
private String listeners; private String listeners;
@Column(columnDefinition = "text") @Column(columnDefinition = "text")
@AutoMapping(ignore = true) @AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true) @ReverseAutoMapping(ignore = true)
@ApiModelProperty(value = "过滤器") @ApiModelProperty(value = "过滤器")
private String filters; private String filters;
@ -58,7 +56,6 @@ public class TbRuleInfo {
@ApiModelProperty(value = "动作") @ApiModelProperty(value = "动作")
@AutoMapping(ignore = true) @AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true) @ReverseAutoMapping(ignore = true)
private String actions; private String actions;
@ApiModelProperty(value = "用户id") @ApiModelProperty(value = "用户id")

View File

@ -9,12 +9,15 @@
*/ */
package cc.iotkit.data.service; package cc.iotkit.data.service;
import cc.iotkit.common.utils.JsonUtils;
import cc.iotkit.common.utils.MapstructUtils; import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.data.dao.IJPACommData; import cc.iotkit.data.dao.IJPACommData;
import cc.iotkit.data.manager.IRuleInfoData; import cc.iotkit.data.manager.IRuleInfoData;
import cc.iotkit.data.dao.RuleInfoRepository; import cc.iotkit.data.dao.RuleInfoRepository;
import cc.iotkit.data.model.TbRuleInfo; import cc.iotkit.data.model.TbRuleInfo;
import cc.iotkit.common.api.Paging; import cc.iotkit.common.api.Paging;
import cc.iotkit.model.rule.FilterConfig;
import cc.iotkit.model.rule.RuleAction;
import cc.iotkit.model.rule.RuleInfo; import cc.iotkit.model.rule.RuleInfo;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -24,9 +27,11 @@ import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
@Primary @Primary
@Service @Service
@ -52,15 +57,16 @@ public class RuleInfoDataImpl implements IRuleInfoData, IJPACommData<RuleInfo, S
@Override @Override
public List<RuleInfo> findByUidAndType(String uid, String type) { public List<RuleInfo> findByUidAndType(String uid, String type) {
return MapstructUtils.convert(ruleInfoRepository.findByUidAndType(uid, type), RuleInfo.class); return fromTb(ruleInfoRepository.findByUidAndType(uid, type));
} }
@Override @Override
public Paging<RuleInfo> findByUidAndType(String uid, String type, int page, int size) { public Paging<RuleInfo> findByUidAndType(String uid, String type, int page, int size) {
Page<TbRuleInfo> paged = ruleInfoRepository.findByUidAndType(uid, type, Page<TbRuleInfo> paged = ruleInfoRepository.findByUidAndType(uid, type,
Pageable.ofSize(size).withPage(page - 1)); Pageable.ofSize(size).withPage(page - 1));
return new Paging<>(paged.getTotalElements(), return new Paging<>(paged.getTotalElements(),
MapstructUtils.convert(paged.getContent(), RuleInfo.class)); fromTb(paged.getContent()));
} }
@Override @Override
@ -68,20 +74,19 @@ public class RuleInfoDataImpl implements IRuleInfoData, IJPACommData<RuleInfo, S
Page<TbRuleInfo> paged = ruleInfoRepository.findByType(type, Page<TbRuleInfo> paged = ruleInfoRepository.findByType(type,
Pageable.ofSize(size).withPage(page - 1)); Pageable.ofSize(size).withPage(page - 1));
return new Paging<>(paged.getTotalElements(), return new Paging<>(paged.getTotalElements(),
MapstructUtils.convert(paged.getContent(), RuleInfo.class)); fromTb(paged.getContent()));
} }
@Override @Override
public List<RuleInfo> findByUid(String uid) { public List<RuleInfo> findByUid(String uid) {
return MapstructUtils.convert(ruleInfoRepository.findByUid(uid), RuleInfo.class); return fromTb(ruleInfoRepository.findByUid(uid));
} }
@Override @Override
public Paging<RuleInfo> findByUid(String uid, int page, int size) { public Paging<RuleInfo> findByUid(String uid, int page, int size) {
Page<TbRuleInfo> paged = ruleInfoRepository.findByUid(uid, Page<TbRuleInfo> paged = ruleInfoRepository.findByUid(uid,
Pageable.ofSize(size).withPage(page - 1)); Pageable.ofSize(size).withPage(page - 1));
return new Paging<>(paged.getTotalElements(), return new Paging<>(paged.getTotalElements(), fromTb(paged.getContent()));
MapstructUtils.convert(paged.getContent(), RuleInfo.class));
} }
@Override @Override
@ -92,7 +97,7 @@ public class RuleInfoDataImpl implements IRuleInfoData, IJPACommData<RuleInfo, S
@Override @Override
public RuleInfo findById(String s) { public RuleInfo findById(String s) {
return MapstructUtils.convert(ruleInfoRepository.findById(s).orElse(null), RuleInfo.class); return from(ruleInfoRepository.findById(s).orElse(null));
} }
@Override @Override
@ -106,9 +111,39 @@ public class RuleInfoDataImpl implements IRuleInfoData, IJPACommData<RuleInfo, S
data.setId(UUID.randomUUID().toString()); data.setId(UUID.randomUUID().toString());
data.setCreateAt(System.currentTimeMillis()); data.setCreateAt(System.currentTimeMillis());
} }
ruleInfoRepository.save(MapstructUtils.convert(data, TbRuleInfo.class)); ruleInfoRepository.save(from(data));
return data; return data;
} }
private static RuleInfo from(TbRuleInfo tb) {
RuleInfo convert = MapstructUtils.convert(tb, RuleInfo.class);
assert convert != null;
convert.setActions(JsonUtils.parseArray(tb.getActions(), RuleAction.class));
convert.setFilters(JsonUtils.parseArray(tb.getFilters(), FilterConfig.class));
convert.setListeners(JsonUtils.parseArray(tb.getListeners(), FilterConfig.class));
return convert;
}
private static TbRuleInfo from(RuleInfo rule) {
TbRuleInfo convert = MapstructUtils.convert(rule, TbRuleInfo.class);
assert convert != null;
convert.setActions(JsonUtils.toJsonString(rule.getActions()));
convert.setFilters(JsonUtils.toJsonString(rule.getFilters()));
convert.setListeners(JsonUtils.toJsonString(rule.getListeners()));
return convert;
}
private static List<RuleInfo> fromTb(List<TbRuleInfo> list) {
if (list == null) {
return new ArrayList<>();
}
return list.stream().map(RuleInfoDataImpl::from).collect(Collectors.toList());
}
private static List<TbRuleInfo> fromBo(List<RuleInfo> list) {
if (list == null) {
return new ArrayList<>();
}
return list.stream().map(RuleInfoDataImpl::from).collect(Collectors.toList());
}
} }

View File

@ -49,7 +49,7 @@ public class RuleEngineController {
return ruleEngineService.selectPageList(request); return ruleEngineService.selectPageList(request);
} }
@ApiOperation("规则编辑") @ApiOperation("保存规则")
@PostMapping("/edit") @PostMapping("/edit")
public boolean saveRule(@RequestBody @Validated Request<RuleInfoBo> ruleInfoBo) { public boolean saveRule(@RequestBody @Validated Request<RuleInfoBo> ruleInfoBo) {
return ruleEngineService.saveRule(ruleInfoBo.getData()); return ruleEngineService.saveRule(ruleInfoBo.getData());
@ -99,7 +99,7 @@ public class RuleEngineController {
return ruleEngineService.selectTaskPageList(request); return ruleEngineService.selectTaskPageList(request);
} }
@ApiOperation("定时任务编辑") @ApiOperation("保存定时任务")
@PostMapping("/task/save") @PostMapping("/task/save")
public boolean saveTask(@Validated @RequestBody Request<TaskInfoBo> taskInfo) { public boolean saveTask(@Validated @RequestBody Request<TaskInfoBo> taskInfo) {
return ruleEngineService.saveTask(taskInfo.getData()); return ruleEngineService.saveTask(taskInfo.getData());

View File

@ -1,30 +1,18 @@
package cc.iotkit.manager.dto.bo.ruleinfo; package cc.iotkit.manager.dto.bo.ruleinfo;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.model.rule.FilterConfig;
import cc.iotkit.model.rule.RuleAction;
import cc.iotkit.model.rule.RuleInfo; import cc.iotkit.model.rule.RuleInfo;
import com.fasterxml.jackson.annotation.JsonInclude; import io.github.linpeilie.annotations.AutoMapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.ReverseAutoMapping;
import org.springframework.format.annotation.DateTimeFormat;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import java.io.Serializable;
import java.util.Date;
import java.math.BigDecimal;
import cc.iotkit.common.api.BaseDto;
import cc.iotkit.common.validate.AddGroup;
import cc.iotkit.common.validate.EditGroup;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.util.List;
@ApiModel(value = "RuleInfoBo") @ApiModel(value = "RuleInfoBo")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -37,10 +25,7 @@ public class RuleInfoBo extends BaseDto {
private String id; private String id;
@ApiModelProperty(value = "动作") @ApiModelProperty(value = "动作")
@Size(max = 65535, message = "动作长度不正确") private List<RuleAction> actions;
@AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true)
private String actions;
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
private Long createAt; private Long createAt;
@ -50,16 +35,10 @@ public class RuleInfoBo extends BaseDto {
private String desc; private String desc;
@ApiModelProperty(value = "过滤器") @ApiModelProperty(value = "过滤器")
@Size(max = 65535, message = "过滤器长度不正确") private List<FilterConfig> filters;
@AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true)
private String filters;
@ApiModelProperty(value = "监听器") @ApiModelProperty(value = "监听器")
@Size(max = 65535, message = "监听器长度不正确") private List<FilterConfig> listeners;
@AutoMapping(ignore = true)
@ReverseAutoMapping(ignore = true)
private String listeners;
@ApiModelProperty(value = "规则名称") @ApiModelProperty(value = "规则名称")
@Size(max = 255, message = "规则名称长度不正确") @Size(max = 255, message = "规则名称长度不正确")

View File

@ -1,5 +1,7 @@
package cc.iotkit.manager.dto.vo.ruleinfo; package cc.iotkit.manager.dto.vo.ruleinfo;
import cc.iotkit.model.rule.FilterConfig;
import cc.iotkit.model.rule.RuleAction;
import cc.iotkit.model.rule.RuleInfo; import cc.iotkit.model.rule.RuleInfo;
import io.github.linpeilie.annotations.AutoMapping; import io.github.linpeilie.annotations.AutoMapping;
import io.github.linpeilie.annotations.ReverseAutoMapping; import io.github.linpeilie.annotations.ReverseAutoMapping;
@ -11,6 +13,7 @@ import lombok.ToString;
import java.util.Date; import java.util.Date;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
@ -33,9 +36,7 @@ public class RuleInfoVo implements Serializable {
@ApiModelProperty(value = "动作") @ApiModelProperty(value = "动作")
@ExcelProperty(value = "动作") @ExcelProperty(value = "动作")
@AutoMapping(ignore = true) private List<RuleAction> actions;
@ReverseAutoMapping(ignore = true)
private String actions;
@ApiModelProperty(value = "创建时间") @ApiModelProperty(value = "创建时间")
@ExcelProperty(value = "创建时间") @ExcelProperty(value = "创建时间")
@ -47,15 +48,11 @@ public class RuleInfoVo implements Serializable {
@ApiModelProperty(value = "过滤器") @ApiModelProperty(value = "过滤器")
@ExcelProperty(value = "过滤器") @ExcelProperty(value = "过滤器")
@AutoMapping(ignore = true) private List<FilterConfig> filters;
@ReverseAutoMapping(ignore = true)
private String filters;
@ApiModelProperty(value = "监听器") @ApiModelProperty(value = "监听器")
@ExcelProperty(value = "监听器") @ExcelProperty(value = "监听器")
@AutoMapping(ignore = true) private List<FilterConfig> listeners;
@ReverseAutoMapping(ignore = true)
private String listeners;
@ApiModelProperty(value = "规则名称") @ApiModelProperty(value = "规则名称")
@ExcelProperty(value = "规则名称") @ExcelProperty(value = "规则名称")

View File

@ -83,7 +83,7 @@ public class RuleEngineServiceImpl implements IRuleEngineService {
@Override @Override
public boolean saveRule(RuleInfoBo ruleInfoBo) { public boolean saveRule(RuleInfoBo ruleInfoBo) {
RuleInfo rule = MapstructUtils.convert(ruleInfoBo, RuleInfo.class); RuleInfo rule = ruleInfoBo.to(RuleInfo.class);
if (StringUtils.isBlank(rule.getId())) { if (StringUtils.isBlank(rule.getId())) {
rule.setId(UUID.randomUUID().toString()); rule.setId(UUID.randomUUID().toString());
rule.setState(RuleInfo.STATE_STOPPED); rule.setState(RuleInfo.STATE_STOPPED);
@ -154,7 +154,7 @@ public class RuleEngineServiceImpl implements IRuleEngineService {
@Override @Override
public Paging<RuleLogVo> selectRuleLogPageList(PageRequest<RuleLogBo> request) { public Paging<RuleLogVo> selectRuleLogPageList(PageRequest<RuleLogBo> request) {
RuleLog ruleLog = request.getData().to(RuleLog.class); RuleLog ruleLog = request.getData().to(RuleLog.class);
return ruleLogData.findByRuleId(ruleLog.getRuleId(), request.getPageNum(), request.getPageSize()).to(RuleLogVo.class); return ruleLogData.findByRuleId(ruleLog.getRuleId(), request.getPageNum(), request.getPageSize()).to(RuleLogVo.class);
} }

View File

@ -11,9 +11,11 @@ package cc.iotkit.ruleengine.rule;
import cc.iotkit.common.api.PageRequest; import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.utils.JsonUtils; import cc.iotkit.common.utils.JsonUtils;
import cc.iotkit.common.utils.StringUtils;
import cc.iotkit.data.manager.IDeviceInfoData; import cc.iotkit.data.manager.IDeviceInfoData;
import cc.iotkit.data.manager.IRuleInfoData; import cc.iotkit.data.manager.IRuleInfoData;
import cc.iotkit.common.api.Paging; import cc.iotkit.common.api.Paging;
import cc.iotkit.model.rule.FilterConfig;
import cc.iotkit.model.rule.RuleAction; import cc.iotkit.model.rule.RuleAction;
import cc.iotkit.model.rule.RuleInfo; import cc.iotkit.model.rule.RuleInfo;
import cc.iotkit.ruleengine.action.*; import cc.iotkit.ruleengine.action.*;
@ -76,11 +78,11 @@ public class RuleManager {
int idx = 1; int idx = 1;
while (true) { while (true) {
PageRequest<RuleInfo> pageRequest = new PageRequest<>(); PageRequest<RuleInfo> pageRequest = new PageRequest<>();
pageRequest.setPageNum(idx+=1); pageRequest.setPageNum(idx += 1);
pageRequest.setPageSize(100); pageRequest.setPageSize(100);
Paging<RuleInfo> all = ruleInfoData.findAll(pageRequest); Paging<RuleInfo> all = ruleInfoData.findAll(pageRequest);
List<RuleInfo> rules = all.getRows(); List<RuleInfo> rules = all.getRows();
if(CollectionUtil.isEmpty(rules)){ if (CollectionUtil.isEmpty(rules)) {
return; return;
} }
rules.forEach(rule -> { rules.forEach(rule -> {
@ -120,15 +122,26 @@ public class RuleManager {
private Rule parseRule(RuleInfo ruleInfo) { private Rule parseRule(RuleInfo ruleInfo) {
List<Listener<?>> listeners = new ArrayList<>(); List<Listener<?>> listeners = new ArrayList<>();
for (RuleInfo.Listener listener : ruleInfo.getListeners()) { for (FilterConfig listener : ruleInfo.getListeners()) {
if (StringUtils.isBlank(listener.getConfig())) {
continue;
}
listeners.add(parseListener(listener.getType(), listener.getConfig())); listeners.add(parseListener(listener.getType(), listener.getConfig()));
} }
List<Filter<?>> filters = new ArrayList<>(); List<Filter<?>> filters = new ArrayList<>();
for (RuleInfo.Filter filter : ruleInfo.getFilters()) { for (FilterConfig filter : ruleInfo.getFilters()) {
if (StringUtils.isBlank(filter.getConfig())) {
continue;
}
filters.add(parseFilter(filter.getType(), filter.getConfig())); filters.add(parseFilter(filter.getType(), filter.getConfig()));
} }
List<Action<?>> actions = new ArrayList<>(); List<Action<?>> actions = new ArrayList<>();
for (RuleAction action : ruleInfo.getActions()) { for (RuleAction action : ruleInfo.getActions()) {
if (StringUtils.isBlank(action.getConfig())) {
continue;
}
actions.add(parseAction(ruleInfo.getId(), action.getType(), action.getConfig())); actions.add(parseAction(ruleInfo.getId(), action.getType(), action.getConfig()));
} }

View File

@ -52,31 +52,8 @@
<configuration> <configuration>
<source>${java.version}</source> <source>${java.version}</source>
<target>${java.version}</target> <target>${java.version}</target>
<encoding>utf8</encoding>
</configuration> </configuration>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<archive>
<manifest>
<mainClass>cc.iotkit.test.mqtt.performance.ReportTest</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>

View File

@ -1,48 +0,0 @@
/*
* +----------------------------------------------------------------------
* | Copyright (c) 2021-2022 All rights reserved.
* +----------------------------------------------------------------------
* | Licensed
* +----------------------------------------------------------------------
* | Author: xw2sy@163.com
* +----------------------------------------------------------------------
*/
package cc.iotkit.test.mqtt;
import cc.iotkit.test.mqtt.config.Mqtt;
import cc.iotkit.test.mqtt.service.Gateway;
import java.io.IOException;
public class Simulator {
public static void main(String[] args) throws IOException {
if (args.length == 0) {
Mqtt.brokerHost = "127.0.0.1";
// Mqtt.brokerHost = "120.76.96.206";
} else {
Mqtt.brokerHost = args[0];
}
new Thread(() -> {
Gateway gateway = new Gateway("hbtgIA0SuVw9lxjB", "AA:BB:CC:DD:22");
gateway.addSubDevice("Rf4QSjbm65X45753", "ABC12300002", "S01");
// gateway.addSubDevice("Rf4QSjbm65X45753", "ABC12300003", "S01");
// gateway.addSubDevice("hdX3PCMcFrCYpesJ", "ABD12300001", "F01");
// gateway.addSubDevice("hdX3PCMcFrCYpesJ", "ABD12300002", "F01");
// gateway.addSubDevice("hdX3PCMcFrCYpesJ", "ABD12300002", "F01");
gateway.start();
//
// Gateway gateway2 = new Gateway("N523nWsCiG3CAn6X", "AA:BB:CC:EE:01");
// //插座
// gateway2.addSubDevice("cGCrkK7Ex4FESAwe", "ABE12300001", "S1");
// gateway2.addSubDevice("cGCrkK7Ex4FESAwe", "ABE12300002", "S1");
// gateway2.addSubDevice("6kYp6jszrDns2yh4", "ABE12400001", "S1");
// gateway2.addSubDevice("", "ABE12500001", "M1");
// gateway2.start();
}).start();
System.in.read();
}
}

View File

@ -33,7 +33,7 @@ public class ConnectionTest {
Mqtt.brokerHost = args[0]; Mqtt.brokerHost = args[0];
} }
int total = 100; int total = 10;
if (args.length > 1) { if (args.length > 1) {
total = Integer.parseInt(args[1]); total = Integer.parseInt(args[1]);
} }

View File

@ -14,11 +14,10 @@
</description> </description>
<modules> <modules>
<!-- <module>iot-test-mqtt</module>--> <module>iot-test-mqtt</module>
<module>iot-virtual-device</module> <module>iot-virtual-device</module>
</modules> </modules>
<artifactId>iot-test-tool</artifactId> <artifactId>iot-test-tool</artifactId>
</project> </project>