Commit 0edb5c49af12d18a457d8fda67e96607ea9efca9

Authored by 黄 x
1 parent 1690d15c

feat: 调整规则节点添加,新增添加场景联动的规则节点

1 1 package org.thingsboard.server.controller.yunteng;
2 2
3   -import com.fasterxml.jackson.databind.node.ObjectNode;
  3 +import com.fasterxml.jackson.databind.JsonNode;
4 4 import io.swagger.annotations.Api;
5 5 import io.swagger.annotations.ApiOperation;
6 6 import io.swagger.annotations.ApiParam;
... ... @@ -26,7 +26,7 @@ import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidatio
26 26 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
27 27 import org.thingsboard.server.common.data.yunteng.dto.ConvertConfigDTO;
28 28 import org.thingsboard.server.common.data.yunteng.dto.ConvertConfigReqDTO;
29   -import org.thingsboard.server.common.data.yunteng.dto.ConvertJSReqDTO;
  29 +import org.thingsboard.server.common.data.yunteng.dto.ConvertReqDTO;
30 30 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
31 31 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
32 32 import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData;
... ... @@ -36,7 +36,6 @@ import org.thingsboard.server.dao.yunteng.service.YtRuleChainService;
36 36
37 37 import java.util.*;
38 38 import java.util.concurrent.ConcurrentMap;
39   -import java.util.concurrent.atomic.AtomicInteger;
40 39
41 40 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
42 41 import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.ORDER_TYPE;
... ... @@ -52,8 +51,6 @@ public class YtConvertDataToController extends BaseController {
52 51 @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
53 52 private boolean debugPerTenantEnabled;
54 53
55   - private final String connectionType = "Success";
56   -
57 54 @Autowired(required = false)
58 55 private ActorSystemContext actorContext;
59 56
... ... @@ -158,7 +155,7 @@ public class YtConvertDataToController extends BaseController {
158 155 @PostMapping("update/js")
159 156 @ApiOperation("启用或禁用转换脚本")
160 157 public RuleChainMetaData updateJs(
161   - @Validated(UpdateGroup.class) @RequestBody ConvertJSReqDTO convertJSReqDTO)
  158 + @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertJSReqDTO)
162 159 throws ThingsboardException {
163 160 int status = convertJSReqDTO.getStatus();
164 161 if (status == FastIotConstants.StateValue.ENABLE
... ... @@ -178,6 +175,30 @@ public class YtConvertDataToController extends BaseController {
178 175 return ruleChainMetaData;
179 176 }
180 177
  178 + @PostMapping("update/scene")
  179 + @ApiOperation("启用或禁用场景联动")
  180 + public RuleChainMetaData updateScene(
  181 + @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertReqDTO)
  182 + throws ThingsboardException {
  183 + //TODO 通过接口获取JsonNode
  184 + JsonNode configuration = convertReqDTO.getConfiguration();
  185 + int status = -1;
  186 + boolean noValue = configuration == null;
  187 + if (noValue && convertReqDTO.getStatus() == FastIotConstants.StateValue.DISABLE) {
  188 + status = FastIotConstants.StateValue.DISABLE;
  189 + }
  190 + if (!noValue) {
  191 + status = FastIotConstants.StateValue.ENABLE;
  192 + }
  193 + List<RuleNode> ruleNodes = new ArrayList<>();
  194 + RuleNode scene = new RuleNode();
  195 + scene.setName("Scene");
  196 + scene.setType("org.thingsboard.rule.engine.yunteng.scene.TbSceneReactNode");
  197 + scene.setConfiguration(configuration);
  198 + ruleNodes.add(scene);
  199 + return saveRuleChain(ruleNodes, status, FastIotConstants.SCENE_REACT);
  200 + }
  201 +
181 202 /**
182 203 * 保存规则链
183 204 *
... ... @@ -196,9 +217,9 @@ public class YtConvertDataToController extends BaseController {
196 217 ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChain.getId());
197 218 // 3. SETUP CONNECTION AND ADD OR DELETE RULE NODE
198 219 if (status == FastIotConstants.MagicNumber.ZERO) {
199   - needSaveRuleNode = deleteRuleNode(nodes, ruleChainMetaData, nodeType);
  220 + needSaveRuleNode = convertConfigService.deleteRuleNode(nodes, ruleChainMetaData, nodeType);
200 221 } else {
201   - addRuleNode(nodes, ruleChainMetaData, nodeType);
  222 + convertConfigService.addRuleNode(nodes, ruleChainMetaData, nodeType);
202 223 needSaveRuleNode = true;
203 224 }
204 225 // 4. SAVE METADATA
... ... @@ -226,174 +247,6 @@ public class YtConvertDataToController extends BaseController {
226 247 return savedRuleChainMetaData;
227 248 }
228 249
229   - private void addRuleNode(
230   - List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType) {
231   - if (nodeType.intValue() == FastIotConstants.CONVERT_DATA.intValue()) {
232   - addConvertConfigRuleNode(nodes, ruleChainMetaData);
233   - } else {
234   - // 1. Get Device Profile nodeIndex
235   - int firstNodeIndex = ruleChainMetaData.getFirstNodeIndex();
236   - // 2. Add Rule Node
237   - RuleNode ruleNode = nodes.get(0);
238   - int randomNum = new Random().nextInt(50);
239   - int layoutX = 202;
240   - int layoutY = 53;
241   - ObjectNode objectNode = JacksonUtil.newObjectNode();
242   - objectNode.put("description", "");
243   - objectNode.put("layoutX", layoutX + randomNum);
244   - objectNode.put("layoutY", layoutY + randomNum);
245   - ruleNode.setAdditionalInfo(objectNode);
246   - ruleChainMetaData.getNodes().add(ruleNode);
247   - int newFirstNodeIndex = ruleChainMetaData.getNodes().size() - 1;
248   - ruleChainMetaData.setFirstNodeIndex(newFirstNodeIndex);
249   - // 3. Add Connection
250   - NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
251   - nodeConnectionInfo.setFromIndex(newFirstNodeIndex);
252   - nodeConnectionInfo.setType(connectionType);
253   - nodeConnectionInfo.setToIndex(firstNodeIndex);
254   - ruleChainMetaData.getConnections().add(nodeConnectionInfo);
255   - }
256   - }
257   -
258   - private void addConvertConfigRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
259   - // 1. GET SAVE TIMESERIES‘S NODE INDEX
260   - int seriesIndex = 0;
261   - for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
262   - if (ruleNode.getType().equals("org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode")) {
263   - break;
264   - }
265   - seriesIndex++;
266   - }
267   - // 2. SETUP CONNECTION
268   - // 3. ADD RULE NODE
269   - int finalSeriesIndex = seriesIndex;
270   - int layoutX = 1140;
271   - int layoutY = 170;
272   - nodes.forEach(
273   - ruleNode -> {
274   - int randomNum = new Random().nextInt(50);
275   - NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
276   - nodeConnectionInfo.setFromIndex(finalSeriesIndex);
277   - nodeConnectionInfo.setType(connectionType);
278   - nodeConnectionInfo.setToIndex(ruleChainMetaData.getNodes().size());
279   - ObjectNode objectNode = JacksonUtil.newObjectNode();
280   - objectNode.put("description", "");
281   - objectNode.put("layoutX", layoutX + randomNum);
282   - objectNode.put("layoutY", layoutY + randomNum);
283   - ruleNode.setAdditionalInfo(objectNode);
284   - ruleChainMetaData.getConnections().add(nodeConnectionInfo);
285   - ruleChainMetaData.getNodes().add(ruleNode);
286   - });
287   - }
288   - /**
289   - * 删除规则节点
290   - *
291   - * @param nodes 要删除的规则节点
292   - * @param ruleChainMetaData 规则链元数据
293   - */
294   - private boolean deleteRuleNode(
295   - List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType) {
296   - boolean needDelete;
297   - if (nodeType.intValue() == FastIotConstants.CONVERT_DATA.intValue()) {
298   - needDelete = deleteConvertConfig(nodes, ruleChainMetaData);
299   - } else {
300   - needDelete = deleteConvertJS(nodes, ruleChainMetaData);
301   - }
302   - return needDelete;
303   - }
304   -
305   - private boolean deleteConvertConfig(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
306   - boolean needDelete = true;
307   - // refactoring RuleChainMetaData
308   - AtomicInteger matchNode = new AtomicInteger(0);
309   - nodes.forEach(
310   - deleteRuleNode -> {
311   - int deleteFlag = 0;
312   - List<RuleNode> normalRuleNode = new ArrayList<>();
313   - List<NodeConnectionInfo> nodeConnectionInfos = ruleChainMetaData.getConnections();
314   - for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
315   - if (deleteRuleNode.getName().equals(ruleNode.getName())
316   - && deleteRuleNode.getType().equals(ruleNode.getType())) {
317   - ruleChainMetaData.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex() - 1);
318   - List<NodeConnectionInfo> normalConnectionInfos = new ArrayList<>();
319   - for (NodeConnectionInfo nodeConnectionInfo : nodeConnectionInfos) {
320   - int fromIndex = nodeConnectionInfo.getFromIndex();
321   - int toIndex = nodeConnectionInfo.getToIndex();
322   - if (fromIndex != deleteFlag && toIndex != deleteFlag) {
323   - nodeConnectionInfo.setFromIndex(
324   - Math.max(fromIndex > deleteFlag ? fromIndex - 1 : fromIndex, 0));
325   - nodeConnectionInfo.setToIndex(
326   - Math.max(toIndex > deleteFlag ? toIndex - 1 : toIndex, 0));
327   - normalConnectionInfos.add(nodeConnectionInfo);
328   - }
329   - }
330   - ruleChainMetaData.setConnections(normalConnectionInfos);
331   - matchNode.getAndIncrement();
332   - } else {
333   - normalRuleNode.add(ruleNode);
334   - }
335   - deleteFlag++;
336   - }
337   - ruleChainMetaData.setNodes(normalRuleNode);
338   - });
339   - if (matchNode.get() == 0) {
340   - needDelete = false;
341   - }
342   - return needDelete;
343   - }
344   -
345   - private boolean deleteConvertJS(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
346   - boolean needDelete = false;
347   - // 1. Get firstNodeIndex
348   - int firstNodeIndex = ruleChainMetaData.getFirstNodeIndex();
349   - // 2. Get Delete Rule Node
350   - RuleNode deleteRuleNode = nodes.get(0);
351   - // 3. RuleChainMetaData Delete Rule Node
352   - int deleteFlag = 0;
353   - for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
354   - if (ruleNode.getName().equals(deleteRuleNode.getName())
355   - && ruleNode.getType().equals(deleteRuleNode.getType())) {
356   - needDelete = true;
357   - break;
358   - }
359   - deleteFlag++;
360   - }
361   - if (needDelete) {
362   - ruleChainMetaData.getNodes().remove(deleteFlag);
363   - // 4. Delete Connection
364   - List<NodeConnectionInfo> newConnections = new ArrayList<>();
365   - ruleChainMetaData
366   - .getConnections()
367   - .forEach(
368   - connectionInfo -> {
369   - int toIndex = connectionInfo.getToIndex();
370   - int fromIndex = connectionInfo.getFromIndex();
371   - if (firstNodeIndex != connectionInfo.getToIndex() && fromIndex != firstNodeIndex) {
372   - connectionInfo.setFromIndex(
373   - Math.max(fromIndex > firstNodeIndex ? fromIndex - 1 : fromIndex, 0));
374   - connectionInfo.setToIndex(
375   - Math.max(toIndex > firstNodeIndex ? toIndex - 1 : toIndex, 0));
376   - newConnections.add(connectionInfo);
377   - }
378   - });
379   -
380   - int deviceProfileNodeIndex = 0;
381   - ruleChainMetaData.setConnections(newConnections);
382   - // 5. Set firstNodeIndex
383   - for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
384   - if (ruleNode.getName().equals("Device Profile Node")
385   - && ruleNode
386   - .getType()
387   - .equals("org.thingsboard.rule.engine.profile.TbDeviceProfileNode")) {
388   - ruleChainMetaData.setFirstNodeIndex(deviceProfileNodeIndex);
389   - break;
390   - }
391   - deviceProfileNodeIndex++;
392   - }
393   - }
394   - return needDelete;
395   - }
396   -
397 250 private ResponseEntity<Boolean> delete(DeleteDTO deleteDTO, Integer nodeType)
398 251 throws ThingsboardException {
399 252 List<RuleNode> nodes =
... ...
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/ConvertReqDTO.java renamed from common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/ConvertJSReqDTO.java
1 1 package org.thingsboard.server.common.data.yunteng.dto;
2 2
  3 +import com.fasterxml.jackson.databind.JsonNode;
3 4 import io.swagger.annotations.ApiModelProperty;
4 5 import lombok.Data;
5 6 import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
6 7
7 8 import javax.validation.constraints.NotEmpty;
8 9 import javax.validation.constraints.NotNull;
9   -import java.util.List;
10 10
11 11 @Data
12   -public class ConvertJSReqDTO {
  12 +public class ConvertReqDTO {
13 13
14   - @ApiModelProperty(value = "转换脚本id",required = true)
  14 + @ApiModelProperty(value = "id",required = true)
15 15 @NotEmpty(message = "id不能为null",groups = UpdateGroup.class)
16 16 private String id;
17 17
18 18 @ApiModelProperty(value = "状态:0禁用 1启用",required = true)
19 19 @NotNull(message = "状态不能为空",groups = UpdateGroup.class)
20 20 private Integer status;
  21 +
  22 + private JsonNode configuration;
21 23 }
... ...
... ... @@ -2,11 +2,15 @@ package org.thingsboard.server.dao.yunteng.impl;
2 2
3 3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 4 import com.baomidou.mybatisplus.core.metadata.IPage;
  5 +import com.fasterxml.jackson.databind.node.ObjectNode;
5 6 import lombok.RequiredArgsConstructor;
6 7 import lombok.extern.slf4j.Slf4j;
7 8 import org.apache.commons.lang3.StringUtils;
8 9 import org.springframework.stereotype.Service;
9 10 import org.springframework.transaction.annotation.Transactional;
  11 +import org.thingsboard.common.util.JacksonUtil;
  12 +import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
  13 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
10 14 import org.thingsboard.server.common.data.rule.RuleNode;
11 15 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
12 16 import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException;
... ... @@ -22,6 +26,8 @@ import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
22 26 import java.util.ArrayList;
23 27 import java.util.List;
24 28 import java.util.Map;
  29 +import java.util.Random;
  30 +import java.util.concurrent.atomic.AtomicInteger;
25 31
26 32 @Slf4j
27 33 @Service
... ... @@ -29,6 +35,7 @@ import java.util.Map;
29 35 public class ConvertConfigServiceImpl
30 36 extends AbstractBaseService<ConvertConfigMapper, ConvertConfig>
31 37 implements ConvertConfigService {
  38 + private final String connectionType = "Success";
32 39
33 40 @Override
34 41 public YtPageData<ConvertConfigDTO> page(String tenantId, Map<String, Object> queryMap) {
... ... @@ -165,4 +172,264 @@ public class ConvertConfigServiceImpl
165 172 .size()
166 173 > FastIotConstants.MagicNumber.ZERO;
167 174 }
  175 + /**
  176 + * 删除规则节点
  177 + *
  178 + * @param nodes 要删除的规则节点
  179 + * @param ruleChainMetaData 规则链元数据
  180 + */
  181 + @Override
  182 + public boolean deleteRuleNode(
  183 + List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType) {
  184 + boolean needDelete;
  185 + if (nodeType.intValue() == FastIotConstants.CONVERT_DATA.intValue()) {
  186 + needDelete = deleteConvertConfig(nodes, ruleChainMetaData);
  187 + } else if (nodeType.intValue() == FastIotConstants.JAVA_SCRIPT.intValue()) {
  188 + needDelete = deleteConvertJS(nodes, ruleChainMetaData);
  189 + } else {
  190 + needDelete = deleteScene(nodes.get(0), ruleChainMetaData);
  191 + }
  192 + return needDelete;
  193 + }
  194 +
  195 + @Override
  196 + public void addRuleNode(
  197 + List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType) {
  198 + if (nodeType.intValue() == FastIotConstants.CONVERT_DATA.intValue()) {
  199 + addConvertConfigRuleNode(nodes, ruleChainMetaData);
  200 + } else if (nodeType.intValue() == FastIotConstants.JAVA_SCRIPT.intValue()) {
  201 + addConvertJSRuleNode(nodes, ruleChainMetaData);
  202 + } else {
  203 + addSceneRuleNode(nodes.get(0), ruleChainMetaData);
  204 + }
  205 + }
  206 +
  207 + private boolean deleteConvertJS(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
  208 + boolean needDelete = false;
  209 + // 1. Get firstNodeIndex
  210 + int firstNodeIndex = ruleChainMetaData.getFirstNodeIndex();
  211 + // 2. Get Delete Rule Node
  212 + RuleNode deleteRuleNode = nodes.get(0);
  213 + // 3. RuleChainMetaData Delete Rule Node
  214 + int deleteFlag = 0;
  215 + for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
  216 + if (ruleNode.getName().equals(deleteRuleNode.getName())
  217 + && ruleNode.getType().equals(deleteRuleNode.getType())) {
  218 + needDelete = true;
  219 + break;
  220 + }
  221 + deleteFlag++;
  222 + }
  223 + if (needDelete) {
  224 + ruleChainMetaData.getNodes().remove(deleteFlag);
  225 + // 4. Delete Connection
  226 + List<NodeConnectionInfo> newConnections = new ArrayList<>();
  227 + ruleChainMetaData
  228 + .getConnections()
  229 + .forEach(
  230 + connectionInfo -> {
  231 + int toIndex = connectionInfo.getToIndex();
  232 + int fromIndex = connectionInfo.getFromIndex();
  233 + if (firstNodeIndex != connectionInfo.getToIndex() && fromIndex != firstNodeIndex) {
  234 + connectionInfo.setFromIndex(
  235 + Math.max(fromIndex > firstNodeIndex ? fromIndex - 1 : fromIndex, 0));
  236 + connectionInfo.setToIndex(
  237 + Math.max(toIndex > firstNodeIndex ? toIndex - 1 : toIndex, 0));
  238 + newConnections.add(connectionInfo);
  239 + }
  240 + });
  241 +
  242 + int deviceProfileNodeIndex = 0;
  243 + ruleChainMetaData.setConnections(newConnections);
  244 + // 5. Set firstNodeIndex
  245 + for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
  246 + if (ruleNode.getName().equals("Device Profile Node")
  247 + && ruleNode
  248 + .getType()
  249 + .equals("org.thingsboard.rule.engine.profile.TbDeviceProfileNode")) {
  250 + ruleChainMetaData.setFirstNodeIndex(deviceProfileNodeIndex);
  251 + break;
  252 + }
  253 + deviceProfileNodeIndex++;
  254 + }
  255 + }
  256 + return needDelete;
  257 + }
  258 +
  259 + private boolean deleteConvertConfig(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
  260 + boolean needDelete = true;
  261 + // refactoring RuleChainMetaData
  262 + AtomicInteger matchNode = new AtomicInteger(0);
  263 + nodes.forEach(
  264 + deleteRuleNode -> {
  265 + int deleteFlag = 0;
  266 + List<RuleNode> normalRuleNode = new ArrayList<>();
  267 + List<NodeConnectionInfo> nodeConnectionInfos = ruleChainMetaData.getConnections();
  268 + for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
  269 + if (deleteRuleNode.getName().equals(ruleNode.getName())
  270 + && deleteRuleNode.getType().equals(ruleNode.getType())) {
  271 + ruleChainMetaData.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex() - 1);
  272 + List<NodeConnectionInfo> normalConnectionInfos = new ArrayList<>();
  273 + for (NodeConnectionInfo nodeConnectionInfo : nodeConnectionInfos) {
  274 + int fromIndex = nodeConnectionInfo.getFromIndex();
  275 + int toIndex = nodeConnectionInfo.getToIndex();
  276 + if (fromIndex != deleteFlag && toIndex != deleteFlag) {
  277 + nodeConnectionInfo.setFromIndex(
  278 + Math.max(fromIndex > deleteFlag ? fromIndex - 1 : fromIndex, 0));
  279 + nodeConnectionInfo.setToIndex(
  280 + Math.max(toIndex > deleteFlag ? toIndex - 1 : toIndex, 0));
  281 + normalConnectionInfos.add(nodeConnectionInfo);
  282 + }
  283 + }
  284 + ruleChainMetaData.setConnections(normalConnectionInfos);
  285 + matchNode.getAndIncrement();
  286 + } else {
  287 + normalRuleNode.add(ruleNode);
  288 + }
  289 + deleteFlag++;
  290 + }
  291 + ruleChainMetaData.setNodes(normalRuleNode);
  292 + });
  293 + if (matchNode.get() == 0) {
  294 + needDelete = false;
  295 + }
  296 + return needDelete;
  297 + }
  298 +
  299 + private boolean deleteScene(RuleNode node, RuleChainMetaData ruleChainMetaData) {
  300 + int deleteIndex = 0;
  301 + boolean needDelete = false;
  302 + for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
  303 + if (ruleNode.getName().equals(node.getName()) && ruleNode.getType().equals(node.getType())) {
  304 + needDelete = true;
  305 + break;
  306 + }
  307 + deleteIndex++;
  308 + }
  309 + if (needDelete) {
  310 + // Delete Rule Node
  311 + ruleChainMetaData.getNodes().remove(deleteIndex);
  312 + List<NodeConnectionInfo> newConnections = new ArrayList<>();
  313 + int finalDeleteIndex = deleteIndex;
  314 + // refactor connection
  315 + ruleChainMetaData
  316 + .getConnections()
  317 + .forEach(
  318 + nodeConnectionInfo -> {
  319 + int fromIndex = nodeConnectionInfo.getFromIndex();
  320 + int toIndex = nodeConnectionInfo.getToIndex();
  321 + if (finalDeleteIndex != nodeConnectionInfo.getToIndex()
  322 + && nodeConnectionInfo.getFromIndex() != finalDeleteIndex) {
  323 + nodeConnectionInfo.setFromIndex(
  324 + Math.max(fromIndex > finalDeleteIndex ? fromIndex - 1 : fromIndex, 0));
  325 + nodeConnectionInfo.setToIndex(
  326 + Math.max(toIndex > finalDeleteIndex ? toIndex - 1 : toIndex, 0));
  327 + newConnections.add(nodeConnectionInfo);
  328 + }
  329 + });
  330 + ruleChainMetaData.setConnections(newConnections);
  331 + ruleChainMetaData.setFirstNodeIndex(ruleChainMetaData.getFirstNodeIndex() - 1);
  332 + }
  333 + return needDelete;
  334 + }
  335 +
  336 + private void addConvertConfigRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
  337 + // 1. GET SAVE TIMESERIES‘S NODE INDEX
  338 + int seriesIndex = 0;
  339 + for (RuleNode ruleNode : ruleChainMetaData.getNodes()) {
  340 + if (ruleNode.getType().equals("org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode")) {
  341 + break;
  342 + }
  343 + seriesIndex++;
  344 + }
  345 + // 2. SETUP CONNECTION
  346 + // 3. ADD RULE NODE
  347 + int finalSeriesIndex = seriesIndex;
  348 + int layoutX = 1140;
  349 + int layoutY = 170;
  350 + nodes.forEach(
  351 + ruleNode -> {
  352 + NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
  353 + nodeConnectionInfo.setFromIndex(finalSeriesIndex);
  354 + nodeConnectionInfo.setType(connectionType);
  355 + nodeConnectionInfo.setToIndex(ruleChainMetaData.getNodes().size());
  356 + ObjectNode objectNode = setAdditionalInfo(layoutX, layoutY);
  357 + ruleNode.setAdditionalInfo(objectNode);
  358 + ruleChainMetaData.getConnections().add(nodeConnectionInfo);
  359 + ruleChainMetaData.getNodes().add(ruleNode);
  360 + });
  361 + }
  362 +
  363 + private void addConvertJSRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
  364 + // 1. Get Device Profile nodeIndex
  365 + int firstNodeIndex = ruleChainMetaData.getFirstNodeIndex();
  366 + // 2. Add Rule Node
  367 + RuleNode ruleNode = nodes.get(0);
  368 + int layoutX = 202;
  369 + int layoutY = 53;
  370 + ObjectNode objectNode = setAdditionalInfo(layoutX, layoutY);
  371 + ruleNode.setAdditionalInfo(objectNode);
  372 + ruleChainMetaData.getNodes().add(ruleNode);
  373 + int newFirstNodeIndex = ruleChainMetaData.getNodes().size() - 1;
  374 + ruleChainMetaData.setFirstNodeIndex(newFirstNodeIndex);
  375 + // 3. Add Connection
  376 + NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
  377 + nodeConnectionInfo.setFromIndex(newFirstNodeIndex);
  378 + nodeConnectionInfo.setType(connectionType);
  379 + nodeConnectionInfo.setToIndex(firstNodeIndex);
  380 + ruleChainMetaData.getConnections().add(nodeConnectionInfo);
  381 + }
  382 +
  383 + private void addSceneRuleNode(RuleNode ruleNode, RuleChainMetaData ruleChainMetaData) {
  384 + boolean existScene = false;
  385 + // check scene exist
  386 + for (RuleNode node : ruleChainMetaData.getNodes()) {
  387 + if (ruleNode.getName().equals(node.getName()) && ruleNode.getType().equals(node.getType())) {
  388 + node.setConfiguration(ruleNode.getConfiguration());
  389 + existScene = true;
  390 + break;
  391 + }
  392 + }
  393 + if (!existScene) {
  394 + // get Save Timeseries Save Client Attributes
  395 + AtomicInteger ruleNodeIndex = new AtomicInteger();
  396 + int layoutX = 1128;
  397 + int layoutY = 132;
  398 + ObjectNode objectNode = setAdditionalInfo(layoutX, layoutY);
  399 + ruleNode.setAdditionalInfo(objectNode);
  400 + ruleChainMetaData.getNodes().add(ruleNode);
  401 + ruleChainMetaData
  402 + .getNodes()
  403 + .forEach(
  404 + node -> {
  405 + if (node.getType()
  406 + .equals("org.thingsboard.rule.engine.telemetry.TbMsgTimeseriesNode")
  407 + || node.getType()
  408 + .equals("org.thingsboard.rule.engine.telemetry.TbMsgAttributesNode")) {
  409 + NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
  410 + nodeConnectionInfo.setFromIndex(ruleNodeIndex.get());
  411 + nodeConnectionInfo.setToIndex(ruleChainMetaData.getNodes().size() - 1);
  412 + nodeConnectionInfo.setType(connectionType);
  413 + ruleChainMetaData.getConnections().add(nodeConnectionInfo);
  414 + }
  415 + if (node.getType().equals("org.thingsboard.rule.engine.rpc.TbSendRPCRequestNode")) {
  416 + NodeConnectionInfo nodeConnectionInfo = new NodeConnectionInfo();
  417 + nodeConnectionInfo.setFromIndex(ruleChainMetaData.getNodes().size() - 1);
  418 + nodeConnectionInfo.setToIndex(ruleNodeIndex.get());
  419 + nodeConnectionInfo.setType("RPC Request");
  420 + ruleChainMetaData.getConnections().add(nodeConnectionInfo);
  421 + }
  422 + ruleNodeIndex.getAndIncrement();
  423 + });
  424 + }
  425 + }
  426 +
  427 + private ObjectNode setAdditionalInfo(int layoutX, int layoutY) {
  428 + int randomNum = new Random().nextInt(50);
  429 + ObjectNode objectNode = JacksonUtil.newObjectNode();
  430 + objectNode.put("description", "");
  431 + objectNode.put("layoutX", layoutX + randomNum);
  432 + objectNode.put("layoutY", layoutY + randomNum);
  433 + return objectNode;
  434 + }
168 435 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.service;
2 2
  3 +import org.thingsboard.server.common.data.rule.RuleChainMetaData;
3 4 import org.thingsboard.server.common.data.rule.RuleNode;
4 5 import org.thingsboard.server.common.data.yunteng.dto.ConvertConfigDTO;
5 6 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
... ... @@ -54,4 +55,9 @@ public interface ConvertConfigService extends BaseService<ConvertConfig> {
54 55 * @return true已启用 false未启用
55 56 */
56 57 boolean checkConvertJSStatusEnable(String tenantId);
  58 +
  59 + boolean deleteRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType);
  60 +
  61 + void addRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType);
  62 +
57 63 }
... ...
... ... @@ -25,7 +25,8 @@ public class TbSceneReactNodeConfig implements NodeConfiguration<TbSceneReactNod
25 25 @Override
26 26 public TbSceneReactNodeConfig defaultConfiguration() {
27 27 TbSceneReactNodeConfig config = new TbSceneReactNodeConfig();
28   - config.setScenes(new HashMap<>());
  28 + Map<String, List<String>> sceneMap = new HashMap<>();
  29 + config.setScenes(sceneMap);
29 30 return config;
30 31 }
31 32 }
... ...