Commit bc9115b519c9cd85be3bd54d9da730bfd19778ca

Authored by xp.Huang
1 parent 7d980b63

fix: 场景联动、数据流转、规则链转换脚本加上规则链筛选

Showing 41 changed files with 568 additions and 160 deletions
@@ -64,10 +64,15 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData; @@ -64,10 +64,15 @@ import org.thingsboard.server.common.data.rule.RuleChainMetaData;
64 import org.thingsboard.server.common.data.rule.RuleChainOutputLabelsUsage; 64 import org.thingsboard.server.common.data.rule.RuleChainOutputLabelsUsage;
65 import org.thingsboard.server.common.data.rule.RuleChainType; 65 import org.thingsboard.server.common.data.rule.RuleChainType;
66 import org.thingsboard.server.common.data.script.ScriptLanguage; 66 import org.thingsboard.server.common.data.script.ScriptLanguage;
  67 +import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
  68 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  69 +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
67 import org.thingsboard.server.common.msg.TbMsg; 70 import org.thingsboard.server.common.msg.TbMsg;
68 import org.thingsboard.server.common.msg.TbMsgDataType; 71 import org.thingsboard.server.common.msg.TbMsgDataType;
69 import org.thingsboard.server.common.msg.TbMsgMetaData; 72 import org.thingsboard.server.common.msg.TbMsgMetaData;
70 import org.thingsboard.server.dao.event.EventService; 73 import org.thingsboard.server.dao.event.EventService;
  74 +import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
  75 +import org.thingsboard.server.dao.yunteng.service.TkDeviceProfileService;
71 import org.thingsboard.server.queue.util.TbCoreComponent; 76 import org.thingsboard.server.queue.util.TbCoreComponent;
72 import org.thingsboard.server.service.rule.TbRuleChainService; 77 import org.thingsboard.server.service.rule.TbRuleChainService;
73 import org.thingsboard.server.service.script.RuleNodeJsScriptEngine; 78 import org.thingsboard.server.service.script.RuleNodeJsScriptEngine;
@@ -152,6 +157,12 @@ public class RuleChainController extends BaseController { @@ -152,6 +157,12 @@ public class RuleChainController extends BaseController {
152 @Autowired(required = false) 157 @Autowired(required = false)
153 private ActorSystemContext actorContext; 158 private ActorSystemContext actorContext;
154 159
  160 + @Autowired
  161 + private TkDeviceProfileService tkDeviceProfileService;
  162 +
  163 + @Autowired
  164 + private ConvertConfigService convertConfigService;
  165 +
155 @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}") 166 @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
156 private boolean debugPerTenantEnabled; 167 private boolean debugPerTenantEnabled;
157 168
@@ -325,7 +336,15 @@ public class RuleChainController extends BaseController { @@ -325,7 +336,15 @@ public class RuleChainController extends BaseController {
325 checkParameter(RULE_CHAIN_ID, strRuleChainId); 336 checkParameter(RULE_CHAIN_ID, strRuleChainId);
326 RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId)); 337 RuleChainId ruleChainId = new RuleChainId(toUUID(strRuleChainId));
327 RuleChain ruleChain = checkRuleChain(ruleChainId, Operation.DELETE); 338 RuleChain ruleChain = checkRuleChain(ruleChainId, Operation.DELETE);
  339 + //判断规则链是否被产品在使用 thingskit
  340 + String tenantId = getCurrentUser().getCurrentTenantId();
  341 + List<String> deviceProfileNames = tkDeviceProfileService.checkRuleChainIdUsedByDeviceProfiles(tenantId,ruleChainId.getId());
  342 + if(null !=deviceProfileNames && !deviceProfileNames.isEmpty()){
  343 + throw new TkDataValidationException(String.format(ErrorMessage.RULE_CHAIN_USED_BY_DEVICE_PROFILE.getMessage(),deviceProfileNames.get(0)));
  344 + }
328 tbRuleChainService.delete(ruleChain, getCurrentUser()); 345 tbRuleChainService.delete(ruleChain, getCurrentUser());
  346 + //删除规则链转换脚本
  347 + convertConfigService.deleteConvertConfigByRuleChainId(tenantId, ruleChainId.getId().toString(),0);
329 } 348 }
330 349
331 @ApiOperation(value = "Get latest input message (getLatestRuleNodeDebugInput)", 350 @ApiOperation(value = "Get latest input message (getLatestRuleNodeDebugInput)",
@@ -9,6 +9,8 @@ import io.swagger.annotations.ApiOperation; @@ -9,6 +9,8 @@ import io.swagger.annotations.ApiOperation;
9 import io.swagger.annotations.ApiParam; 9 import io.swagger.annotations.ApiParam;
10 import java.util.*; 10 import java.util.*;
11 import java.util.concurrent.ConcurrentMap; 11 import java.util.concurrent.ConcurrentMap;
  12 +import java.util.stream.Collectors;
  13 +
12 import lombok.RequiredArgsConstructor; 14 import lombok.RequiredArgsConstructor;
13 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
14 import org.springframework.beans.factory.annotation.Value; 16 import org.springframework.beans.factory.annotation.Value;
@@ -20,10 +22,9 @@ import org.thingsboard.common.util.JacksonUtil; @@ -20,10 +22,9 @@ import org.thingsboard.common.util.JacksonUtil;
20 import org.thingsboard.server.actors.ActorSystemContext; 22 import org.thingsboard.server.actors.ActorSystemContext;
21 import org.thingsboard.server.actors.tenant.DebugTbRateLimits; 23 import org.thingsboard.server.actors.tenant.DebugTbRateLimits;
22 import org.thingsboard.server.common.data.StringUtils; 24 import org.thingsboard.server.common.data.StringUtils;
23 -import org.thingsboard.server.common.data.audit.ActionType;  
24 import org.thingsboard.server.common.data.exception.ThingsboardException; 25 import org.thingsboard.server.common.data.exception.ThingsboardException;
  26 +import org.thingsboard.server.common.data.id.RuleChainId;
25 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
26 -import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;  
27 import org.thingsboard.server.common.data.rule.*; 28 import org.thingsboard.server.common.data.rule.*;
28 import org.thingsboard.server.common.data.yunteng.common.DeleteGroup; 29 import org.thingsboard.server.common.data.yunteng.common.DeleteGroup;
29 import org.thingsboard.server.common.data.yunteng.common.UpdateGroup; 30 import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
@@ -34,12 +35,12 @@ import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; @@ -34,12 +35,12 @@ import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
34 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO; 35 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
35 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigReqDTO; 36 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigReqDTO;
36 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertReqDTO; 37 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertReqDTO;
  38 +import org.thingsboard.server.common.data.yunteng.dto.scene.SceneLinkageDTO;
37 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; 39 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
38 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 40 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
39 import org.thingsboard.server.controller.BaseController; 41 import org.thingsboard.server.controller.BaseController;
40 import org.thingsboard.server.dao.yunteng.service.ConvertConfigService; 42 import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
41 import org.thingsboard.server.dao.yunteng.service.SceneLinkageService; 43 import org.thingsboard.server.dao.yunteng.service.SceneLinkageService;
42 -import org.thingsboard.server.dao.yunteng.service.TkRuleChainService;  
43 import org.thingsboard.server.queue.util.TbCoreComponent; 44 import org.thingsboard.server.queue.util.TbCoreComponent;
44 import org.thingsboard.server.service.rule.TbRuleChainService; 45 import org.thingsboard.server.service.rule.TbRuleChainService;
45 import org.thingsboard.server.service.security.permission.Operation; 46 import org.thingsboard.server.service.security.permission.Operation;
@@ -51,7 +52,6 @@ import org.thingsboard.server.service.security.permission.Operation; @@ -51,7 +52,6 @@ import org.thingsboard.server.service.security.permission.Operation;
51 @Api(tags = {"数据流转控制器"}) 52 @Api(tags = {"数据流转控制器"})
52 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')") 53 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN')")
53 public class TkConvertDataToController extends BaseController { 54 public class TkConvertDataToController extends BaseController {
54 - private final TkRuleChainService tkRuleChainService;  
55 private final ConvertConfigService convertConfigService; 55 private final ConvertConfigService convertConfigService;
56 private final SceneLinkageService sceneLinkageService; 56 private final SceneLinkageService sceneLinkageService;
57 57
@@ -75,7 +75,8 @@ public class TkConvertDataToController extends BaseController { @@ -75,7 +75,8 @@ public class TkConvertDataToController extends BaseController {
75 @RequestParam(value = ORDER_FILED, required = false) String orderBy, 75 @RequestParam(value = ORDER_FILED, required = false) String orderBy,
76 @RequestParam(value = "startTime", required = false) Long startTime, 76 @RequestParam(value = "startTime", required = false) Long startTime,
77 @RequestParam(value = "endTime", required = false) Long endTime, 77 @RequestParam(value = "endTime", required = false) Long endTime,
78 - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) 78 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType,
  79 + @RequestParam(value = "ruleChainId",required = false) String ruleChainId)
79 throws ThingsboardException { 80 throws ThingsboardException {
80 81
81 HashMap<String, Object> queryMap = new HashMap<>(); 82 HashMap<String, Object> queryMap = new HashMap<>();
@@ -85,6 +86,7 @@ public class TkConvertDataToController extends BaseController { @@ -85,6 +86,7 @@ public class TkConvertDataToController extends BaseController {
85 queryMap.put("nodeType", nodeType); 86 queryMap.put("nodeType", nodeType);
86 queryMap.put("name", name); 87 queryMap.put("name", name);
87 queryMap.put("status", status); 88 queryMap.put("status", status);
  89 + queryMap.put("ruleChainId",ruleChainId);
88 checkTimeAndPut(queryMap, startTime, endTime); 90 checkTimeAndPut(queryMap, startTime, endTime);
89 if (orderType != null) { 91 if (orderType != null) {
90 queryMap.put(ORDER_TYPE, orderType.name()); 92 queryMap.put(ORDER_TYPE, orderType.name());
@@ -156,8 +158,8 @@ public class TkConvertDataToController extends BaseController { @@ -156,8 +158,8 @@ public class TkConvertDataToController extends BaseController {
156 } 158 }
157 159
158 @PostMapping("update/config") 160 @PostMapping("update/config")
159 - @ApiOperation("启用或禁用配置")  
160 - public RuleChainMetaData updateConfig( 161 + @ApiOperation("启用或禁用数据流转")
  162 + public ResponseEntity<Boolean> updateConfig(
161 @Validated(UpdateGroup.class) @RequestBody ConvertConfigReqDTO convertConfigReqDTO) 163 @Validated(UpdateGroup.class) @RequestBody ConvertConfigReqDTO convertConfigReqDTO)
162 throws Exception { 164 throws Exception {
163 if (convertConfigService.checkConvertConfigStatusExist( 165 if (convertConfigService.checkConvertConfigStatusExist(
@@ -171,47 +173,53 @@ public class TkConvertDataToController extends BaseController { @@ -171,47 +173,53 @@ public class TkConvertDataToController extends BaseController {
171 List<RuleNode> nodes = 173 List<RuleNode> nodes =
172 convertConfigService.getRuleNodesByConvertConfigIds( 174 convertConfigService.getRuleNodesByConvertConfigIds(
173 ids, null, FastIotConstants.CONVERT_DATA); 175 ids, null, FastIotConstants.CONVERT_DATA);
174 - RuleChainMetaData ruleChainMetaData = new RuleChainMetaData();  
175 if (null != nodes && nodes.size() > 0) { 176 if (null != nodes && nodes.size() > 0) {
176 - ruleChainMetaData = saveRuleChain(nodes, status, FastIotConstants.CONVERT_DATA,null); 177 + classificationSaveRuleChain(nodes,status,FastIotConstants.CONVERT_DATA,null);
177 } 178 }
178 - convertConfigService.updateConvertStatusByIds(  
179 - ids, status, getCurrentUser().getCurrentTenantId());  
180 - return ruleChainMetaData; 179 + return ResponseEntity.ok(convertConfigService.updateConvertStatusByIds(
  180 + ids, status, getCurrentUser().getCurrentTenantId()));
181 } 181 }
182 182
183 @PostMapping("update/js") 183 @PostMapping("update/js")
184 @ApiOperation("启用或禁用转换脚本") 184 @ApiOperation("启用或禁用转换脚本")
185 - public RuleChainMetaData updateJs( 185 + public ResponseEntity<Boolean> updateJs(
186 @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertJSReqDTO) 186 @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertJSReqDTO)
187 throws Exception { 187 throws Exception {
188 int status = convertJSReqDTO.getStatus(); 188 int status = convertJSReqDTO.getStatus();
  189 + ConvertConfigDTO checkConfig = convertConfigService.findConvertConfigDTOById(getCurrentUser().getCurrentTenantId(),
  190 + convertJSReqDTO.getId());
  191 + if(null == checkConfig){
  192 + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_CUSTOMER.getMessage());
  193 + }
189 if (status == FastIotConstants.StateValue.ENABLE 194 if (status == FastIotConstants.StateValue.ENABLE
190 - && convertConfigService.checkConvertJSStatusEnable(getCurrentUser().getCurrentTenantId())) { 195 + && convertConfigService.checkConvertJSStatusEnable(getCurrentUser().getCurrentTenantId(),checkConfig.getRuleChainId())) {
191 throw new TkDataValidationException(ErrorMessage.CONVERT_JS_IS_ALONE.getMessage()); 196 throw new TkDataValidationException(ErrorMessage.CONVERT_JS_IS_ALONE.getMessage());
192 } 197 }
193 List<String> ids = new ArrayList<>(); 198 List<String> ids = new ArrayList<>();
194 - ids.add(convertJSReqDTO.getId()); 199 + ids.add(checkConfig.getId());
195 List<RuleNode> nodes = 200 List<RuleNode> nodes =
196 convertConfigService.getRuleNodesByConvertConfigIds( 201 convertConfigService.getRuleNodesByConvertConfigIds(
197 ids, null, FastIotConstants.JAVA_SCRIPT); 202 ids, null, FastIotConstants.JAVA_SCRIPT);
198 -  
199 - RuleChainMetaData ruleChainMetaData =  
200 - saveRuleChain(nodes, status, FastIotConstants.JAVA_SCRIPT,null);  
201 - convertConfigService.updateConvertStatusByIds(  
202 - ids, status, getCurrentUser().getCurrentTenantId());  
203 - return ruleChainMetaData; 203 + RuleChainId ruleChainId = StringUtils.isEmpty(checkConfig.getRuleChainId())?null:new RuleChainId(UUID.fromString(checkConfig.getRuleChainId()));
  204 + saveRuleChain(ruleChainId,nodes, status, FastIotConstants.JAVA_SCRIPT,null);
  205 + return ResponseEntity.ok(
  206 + convertConfigService.updateConvertStatusByIds(
  207 + ids, status, getCurrentUser().getCurrentTenantId()));
204 } 208 }
205 209
206 @PostMapping("update/scene") 210 @PostMapping("update/scene")
207 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") 211 @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
208 @ApiOperation("启用或禁用场景联动") 212 @ApiOperation("启用或禁用场景联动")
209 - public RuleChainMetaData updateScene( 213 + public ResponseEntity<Boolean> updateScene(
210 @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertReqDTO) 214 @Validated(UpdateGroup.class) @RequestBody ConvertReqDTO convertReqDTO)
211 throws Exception { 215 throws Exception {
212 - int status = -1;  
213 - String sceneId = convertReqDTO.getId();  
214 String currentTenant = getCurrentUser().getCurrentTenantId(); 216 String currentTenant = getCurrentUser().getCurrentTenantId();
  217 + SceneLinkageDTO querySceneLink = sceneLinkageService.selectById(currentTenant, convertReqDTO.getId());
  218 + if(null == querySceneLink){
  219 + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage());
  220 + }
  221 + int status = -1;
  222 + String sceneId = querySceneLink.getId();
215 Integer sceneStatus = convertReqDTO.getStatus(); 223 Integer sceneStatus = convertReqDTO.getStatus();
216 JsonNode configuration = 224 JsonNode configuration =
217 sceneLinkageService.getRuleNodeConfig( 225 sceneLinkageService.getRuleNodeConfig(
@@ -255,9 +263,10 @@ public class TkConvertDataToController extends BaseController { @@ -255,9 +263,10 @@ public class TkConvertDataToController extends BaseController {
255 objectNode.remove(otherKey); 263 objectNode.remove(otherKey);
256 scene.setConfiguration(objectNode); 264 scene.setConfiguration(objectNode);
257 } 265 }
258 - RuleChainMetaData result = saveRuleChain(ruleNodes, status, FastIotConstants.SCENE_REACT,nodeConnectionName); 266 + RuleChainId ruleChainId = StringUtils.isEmpty(querySceneLink.getRuleChainId())?null:new RuleChainId(UUID.fromString(querySceneLink.getRuleChainId()));
  267 + saveRuleChain(ruleChainId,ruleNodes, status, FastIotConstants.SCENE_REACT,nodeConnectionName);
259 sceneLinkageService.updateSceneStatus(sceneId, sceneStatus, currentTenant); 268 sceneLinkageService.updateSceneStatus(sceneId, sceneStatus, currentTenant);
260 - return result; 269 + return ResponseEntity.ok(true);
261 } 270 }
262 271
263 /** 272 /**
@@ -265,33 +274,17 @@ public class TkConvertDataToController extends BaseController { @@ -265,33 +274,17 @@ public class TkConvertDataToController extends BaseController {
265 * 274 *
266 * @param nodes 规则节点 275 * @param nodes 规则节点
267 * @param status 0禁用 1启用 276 * @param status 0禁用 1启用
  277 + * @param nodeType
  278 + * @param nodeConnectionName
268 * @return 规则节点数据 279 * @return 规则节点数据
269 */ 280 */
270 - private RuleChainMetaData saveRuleChain(List<RuleNode> nodes, Integer status, Integer nodeType, 281 + private void saveRuleChain(RuleChainId ruleChainId,List<RuleNode> nodes, Integer status, Integer nodeType,
271 String nodeConnectionName) 282 String nodeConnectionName)
272 throws Exception { 283 throws Exception {
273 - boolean needSaveRuleNode;  
274 TenantId tenantId = getTenantId(); 284 TenantId tenantId = getTenantId();
275 - // 1. GET DEFAULT RULE CHAIN  
276 - RuleChain ruleChain = tkRuleChainService.getRootTenantRuleChain(getTenantId());  
277 - // 2. GET RULE CHAIN METADATA  
278 - RuleChainMetaData ruleChainMetaData =  
279 - ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChain.getId());  
280 - // 3. SETUP CONNECTION AND ADD OR DELETE RULE NODE  
281 - if (status == FastIotConstants.MagicNumber.ZERO) {  
282 - needSaveRuleNode =  
283 - convertConfigService.deleteRuleNode(  
284 - nodes, ruleChainMetaData, nodeType, getCurrentUser().getCurrentTenantId());  
285 - } else {  
286 - convertConfigService.addRuleNode(  
287 - nodes, ruleChainMetaData, nodeType, getCurrentUser().getCurrentTenantId());  
288 - //添加节点连接信息  
289 - addConnectionInfo(nodeConnectionName,nodeType,ruleChainMetaData);  
290 - needSaveRuleNode = true;  
291 - }  
292 - // 4. SAVE METADATA  
293 - RuleChainMetaData savedRuleChainMetaData = null;  
294 - if (needSaveRuleNode) { 285 + RuleChain ruleChain;
  286 + RuleChainMetaData savedRuleChainMetaData = convertConfigService.getTenantRuleChainMetaData(tenantId,ruleChainId,nodes,status,nodeType,nodeConnectionName);
  287 + if (null !=savedRuleChainMetaData && savedRuleChainMetaData.isNeedSaveRuleNode()) {
295 if (debugPerTenantEnabled) { 288 if (debugPerTenantEnabled) {
296 ConcurrentMap<TenantId, DebugTbRateLimits> debugPerTenantLimits = 289 ConcurrentMap<TenantId, DebugTbRateLimits> debugPerTenantLimits =
297 actorContext.getDebugPerTenantLimits(); 290 actorContext.getDebugPerTenantLimits();
@@ -300,42 +293,32 @@ public class TkConvertDataToController extends BaseController { @@ -300,42 +293,32 @@ public class TkConvertDataToController extends BaseController {
300 debugPerTenantLimits.remove(tenantId, debugTbRateLimits); 293 debugPerTenantLimits.remove(tenantId, debugTbRateLimits);
301 } 294 }
302 } 295 }
303 - ruleChain = checkRuleChain(ruleChainMetaData.getRuleChainId(), Operation.WRITE);  
304 - savedRuleChainMetaData = tbRuleChainService.saveRuleChainMetaData(tenantId, ruleChain, ruleChainMetaData, true, getCurrentUser()); 296 + ruleChain = checkRuleChain(savedRuleChainMetaData.getRuleChainId(), Operation.WRITE);
  297 + tbRuleChainService.saveRuleChainMetaData(tenantId, ruleChain, savedRuleChainMetaData, true, getCurrentUser());
305 } 298 }
306 - return savedRuleChainMetaData;  
307 } 299 }
308 300
309 - private ResponseEntity<Boolean> delete(DeleteDTO deleteDTO, Integer nodeType)  
310 - throws Exception { 301 + private ResponseEntity<Boolean> delete(DeleteDTO deleteDTO, Integer nodeType){
311 List<RuleNode> nodes = 302 List<RuleNode> nodes =
312 convertConfigService.getRuleNodesByConvertConfigIds( 303 convertConfigService.getRuleNodesByConvertConfigIds(
313 new ArrayList<>(deleteDTO.getIds()), FastIotConstants.StateValue.ENABLE, nodeType); 304 new ArrayList<>(deleteDTO.getIds()), FastIotConstants.StateValue.ENABLE, nodeType);
314 - if (nodes != null && nodes.size() > FastIotConstants.MagicNumber.ZERO) {  
315 - saveRuleChain(nodes, 0, nodeType,null);  
316 - } 305 + classificationSaveRuleChain(nodes,0,nodeType,null);
317 return ResponseEntity.ok(convertConfigService.deleteConvertConfig(deleteDTO, nodeType)); 306 return ResponseEntity.ok(convertConfigService.deleteConvertConfig(deleteDTO, nodeType));
318 } 307 }
319 - private void addConnectionInfo(String nodeConnectionName,Integer nodeType,RuleChainMetaData ruleChainMetaData){  
320 - if(null != nodeConnectionName && nodeType == FastIotConstants.SCENE_REACT){  
321 - int i = 0;  
322 - //查找事件节点下标  
323 - int formIndex = 0;  
324 - int toIndex = 0;  
325 - for(RuleNode ruleNode : ruleChainMetaData.getNodes()){  
326 - if(ruleNode.getType().equals(nodeConnectionName)){  
327 - formIndex = i;  
328 - }  
329 - if(ruleNode.getType().equals(FastIotConstants.TkNodeClassName.GET_ORIGINATOR_FIELDS_NODE)){  
330 - toIndex = i;  
331 - }  
332 - i++; 308 +
  309 + private void classificationSaveRuleChain(List<RuleNode> nodes,Integer saveStatus,Integer nodeType,String nodeConnectionName){
  310 + if (nodes != null && nodes.size() > FastIotConstants.MagicNumber.ZERO) {
  311 + //将规则节点按规则链分类
  312 + Map<RuleChainId,List<RuleNode>> classification = nodes.stream().collect(Collectors.groupingBy(RuleNode::getRuleChainId));
  313 + if(classification !=null && !classification.isEmpty()){
  314 + classification.keySet().forEach(key->{
  315 + try {
  316 + saveRuleChain(key,nodes, saveStatus, nodeType,nodeConnectionName);
  317 + } catch (Exception e) {
  318 + throw new RuntimeException(e);
  319 + }
  320 + });
333 } 321 }
334 - NodeConnectionInfo newConnectionInfo = new NodeConnectionInfo();  
335 - newConnectionInfo.setFromIndex(formIndex);  
336 - newConnectionInfo.setToIndex(toIndex);  
337 - newConnectionInfo.setType("SUCCESS");  
338 - ruleChainMetaData.getConnections().add(newConnectionInfo);  
339 } 322 }
340 } 323 }
341 } 324 }
@@ -106,16 +106,16 @@ public class TkDeviceProfileController extends BaseController { @@ -106,16 +106,16 @@ public class TkDeviceProfileController extends BaseController {
106 } 106 }
107 107
108 @GetMapping("/me/list") 108 @GetMapping("/me/list")
109 - @ApiOperation("选项列表")  
110 - @PreAuthorize("@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{})") 109 + @ApiOperation("产品列表")
  110 + @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
111 public ResponseEntity listDeviceProfile( 111 public ResponseEntity listDeviceProfile(
112 @ApiParam(value = "设备类型") @RequestParam(value = "deviceType", required = false) 112 @ApiParam(value = "设备类型") @RequestParam(value = "deviceType", required = false)
113 - DeviceTypeEnum deviceType,DeviceTransportType transportType,Boolean isSceneLinkage) 113 + DeviceTypeEnum deviceType,DeviceTransportType transportType,Boolean isSceneLinkage,String ruleChainId)
114 throws ThingsboardException { 114 throws ThingsboardException {
115 List<DeviceProfileDTO> results; 115 List<DeviceProfileDTO> results;
116 TenantId tenantId = getCurrentUser().getTenantId(); 116 TenantId tenantId = getCurrentUser().getTenantId();
117 if (getCurrentUser().isTenantAdmin()) { 117 if (getCurrentUser().isTenantAdmin()) {
118 - results = tkDeviceProfileService.findDeviceProfile(tenantId, null,deviceType,transportType,isSceneLinkage); 118 + results = tkDeviceProfileService.findDeviceProfile(tenantId, null,deviceType,transportType,isSceneLinkage,ruleChainId);
119 } else { 119 } else {
120 List<TkDeviceProfileEntity> listEntity = 120 List<TkDeviceProfileEntity> listEntity =
121 tkDeviceProfileService.findCustomerDeviceProfiles( 121 tkDeviceProfileService.findCustomerDeviceProfiles(
@@ -94,7 +94,8 @@ public class TkSceneLinkageController extends BaseController { @@ -94,7 +94,8 @@ public class TkSceneLinkageController extends BaseController {
94 @RequestParam(value = "name", required = false) String name, 94 @RequestParam(value = "name", required = false) String name,
95 @RequestParam(value = "status", required = false) Integer status, 95 @RequestParam(value = "status", required = false) Integer status,
96 @RequestParam(value = "organizationId", required = false) String organizationId, 96 @RequestParam(value = "organizationId", required = false) String organizationId,
97 - @RequestParam(value = "triggers", required = false) List<TriggerDTO> triggers) 97 + @RequestParam(value = "triggers", required = false) List<TriggerDTO> triggers,
  98 + @RequestParam(value = "ruleChainId",required = false) String ruleChainId)
98 throws ThingsboardException { 99 throws ThingsboardException {
99 HashMap<String, Object> queryMap = new HashMap<>(); 100 HashMap<String, Object> queryMap = new HashMap<>();
100 queryMap.put(PAGE_SIZE, pageSize); 101 queryMap.put(PAGE_SIZE, pageSize);
@@ -103,6 +104,7 @@ public class TkSceneLinkageController extends BaseController { @@ -103,6 +104,7 @@ public class TkSceneLinkageController extends BaseController {
103 queryMap.put("status", status); 104 queryMap.put("status", status);
104 queryMap.put("organizationId", organizationId); 105 queryMap.put("organizationId", organizationId);
105 queryMap.put("triggers", triggers); 106 queryMap.put("triggers", triggers);
  107 + queryMap.put("ruleChainId",ruleChainId);
106 queryMap.put("currentUser",getCurrentUser().getCurrentUserId()); 108 queryMap.put("currentUser",getCurrentUser().getCurrentUserId());
107 //如果是普通租户在最外层默认放入组织id 109 //如果是普通租户在最外层默认放入组织id
108 if(getCurrentUser().isPtCommonTenant()){ 110 if(getCurrentUser().isPtCommonTenant()){
@@ -238,7 +238,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService { @@ -238,7 +238,7 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
238 if (TkEdgeProcessorFactory.isTkProcessorExist(type.getEntityType())) { 238 if (TkEdgeProcessorFactory.isTkProcessorExist(type.getEntityType())) {
239 TkEdgeProcessorFactory.getTkProcessor(type.getEntityType()).processEntityNotification(tenantId, edgeNotificationMsg); 239 TkEdgeProcessorFactory.getTkProcessor(type.getEntityType()).processEntityNotification(tenantId, edgeNotificationMsg);
240 } else { 240 } else {
241 - log.error("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type); 241 + log.warn("[{}] Edge event type [{}] is not designed to be pushed to edge", tenantId, type);
242 } 242 }
243 } catch (Exception e) { 243 } catch (Exception e) {
244 callBackFailure(tenantId, edgeNotificationMsg, callback, e); 244 callBackFailure(tenantId, edgeNotificationMsg, callback, e);
@@ -69,6 +69,9 @@ public class RpcCommandTask { @@ -69,6 +69,9 @@ public class RpcCommandTask {
69 if (null != tkTaskCenterDTO) { 69 if (null != tkTaskCenterDTO) {
70 TargetTypeEnum targetType = tkTaskCenterDTO.getTargetType(); 70 TargetTypeEnum targetType = tkTaskCenterDTO.getTargetType();
71 TargetContentDTO targetContent = tkTaskCenterDTO.getExecuteTarget(); 71 TargetContentDTO targetContent = tkTaskCenterDTO.getExecuteTarget();
  72 + if(null == targetContent){
  73 + return;
  74 + }
72 JsonNode cmdJsonNode = tkTaskCenterDTO.getExecuteContent().getPushContent(); 75 JsonNode cmdJsonNode = tkTaskCenterDTO.getExecuteContent().getPushContent();
73 SecurityUser securityUser = new SecurityUser(); 76 SecurityUser securityUser = new SecurityUser();
74 String taskCenterId = tkTaskCenterDTO.getId(); 77 String taskCenterId = tkTaskCenterDTO.getId();
@@ -45,6 +45,9 @@ public class RuleChainMetaData { @@ -45,6 +45,9 @@ public class RuleChainMetaData {
45 @ApiModelProperty(position = 5, required = true, value = "List of JSON objects that represent connections between rule nodes and other rule chains.") 45 @ApiModelProperty(position = 5, required = true, value = "List of JSON objects that represent connections between rule nodes and other rule chains.")
46 private List<RuleChainConnectionInfo> ruleChainConnections; 46 private List<RuleChainConnectionInfo> ruleChainConnections;
47 47
  48 + //thingskit
  49 + private boolean needSaveRuleNode;
  50 +
48 public void addConnectionInfo(int fromIndex, int toIndex, String type) { 51 public void addConnectionInfo(int fromIndex, int toIndex, String type) {
49 NodeConnectionInfo connectionInfo = new NodeConnectionInfo(); 52 NodeConnectionInfo connectionInfo = new NodeConnectionInfo();
50 connectionInfo.setFromIndex(fromIndex); 53 connectionInfo.setFromIndex(fromIndex);
@@ -43,7 +43,7 @@ public enum ErrorMessage { @@ -43,7 +43,7 @@ public enum ErrorMessage {
43 DEVICE_NOT_EXISTENCE_IN_TENANT(400021,"当前租户下不存在该设备"), 43 DEVICE_NOT_EXISTENCE_IN_TENANT(400021,"当前租户下不存在该设备"),
44 DEVICE_RELATION_IS_ABSENT(400022,"设备关联关系已不存在"), 44 DEVICE_RELATION_IS_ABSENT(400022,"设备关联关系已不存在"),
45 DATA_IS_DELETED(400023,"数据已经删除"), 45 DATA_IS_DELETED(400023,"数据已经删除"),
46 - CONVERT_JS_IS_ALONE(400024,"转换脚本只能启用一个"), 46 + CONVERT_JS_IS_ALONE(400024,"同一个规则链转换脚本只能启用一个"),
47 PHONE_OR_EMAIL_HAS_REGISTER(400025,"手机或邮箱已被使用"), 47 PHONE_OR_EMAIL_HAS_REGISTER(400025,"手机或邮箱已被使用"),
48 CONTACT_ALREADY_ASSOCIATED(400026,"当前联系人已与告警配置【%s】关联"), 48 CONTACT_ALREADY_ASSOCIATED(400026,"当前联系人已与告警配置【%s】关联"),
49 MSG_CODE_NOT_MATCHED(400027,"验证码不正确"), 49 MSG_CODE_NOT_MATCHED(400027,"验证码不正确"),
@@ -142,6 +142,10 @@ public enum ErrorMessage { @@ -142,6 +142,10 @@ public enum ErrorMessage {
142 CUSTOMER_USER_UPDATE_ERROR(400117,"已分配设备给该客户,请取消分配后重试"), 142 CUSTOMER_USER_UPDATE_ERROR(400117,"已分配设备给该客户,请取消分配后重试"),
143 SCRIPT_EVAL_FAILED(400118,"租户【%s】启动脚本【%s】失败,失败原因【%s】"), 143 SCRIPT_EVAL_FAILED(400118,"租户【%s】启动脚本【%s】失败,失败原因【%s】"),
144 SCENE_REACT_IS_EDGE(400119,"场景联动来自于边端请勿操作"), 144 SCENE_REACT_IS_EDGE(400119,"场景联动来自于边端请勿操作"),
  145 + RULE_CHAIN_USED_BY_DEVICE_PROFILE(400120,"该规则链正在被【%s】产品使用,不能被删除!!"),
  146 + NODE_NAME_ALREADY_EXISTS(400121,"同类型的节点名称已被使用"),
  147 + CHOICE_DEVICE_PROFILE_RULE_CHAIN_IS_USED_FOR_CONVERT(400122,"选中的产品【%s】正在被数据流转【%s】使用,不能更换规则链!!"),
  148 + CHOICE_DEVICE_PROFILE_RULE_CHAIN_IS_USED_FOR_SCENE(400123,"选中的产品【%s】正在被场景联动【%s】使用,不能更换规则链!!"),
145 HAVE_NO_PERMISSION(500002,"没有修改权限"), 149 HAVE_NO_PERMISSION(500002,"没有修改权限"),
146 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置"); 150 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置");
147 151
@@ -25,6 +25,12 @@ public class ConvertConfigDTO extends TenantDTO { @@ -25,6 +25,12 @@ public class ConvertConfigDTO extends TenantDTO {
25 @NotNull(message = "配置参数不能为空或者空字符串") 25 @NotNull(message = "配置参数不能为空或者空字符串")
26 private JsonNode configuration; 26 private JsonNode configuration;
27 27
  28 + @ApiModelProperty(value = "规则链ID")
  29 + private String ruleChainId;
  30 +
  31 + @ApiModelProperty(value = "规则链名称")
  32 + private String ruleChainName;
  33 +
28 @ApiModelProperty(value = "附加信息") 34 @ApiModelProperty(value = "附加信息")
29 private JsonNode additionalInfo; 35 private JsonNode additionalInfo;
30 36
@@ -49,6 +49,9 @@ public class DoActionDTO extends TenantDTO { @@ -49,6 +49,9 @@ public class DoActionDTO extends TenantDTO {
49 @ApiModelProperty(value = "场景联动id") 49 @ApiModelProperty(value = "场景联动id")
50 private String sceneLinkageId; 50 private String sceneLinkageId;
51 51
  52 + @ApiModelProperty(value = "场景联动名称")
  53 + private String sceneLinkageName;
  54 +
52 @ApiModelProperty(value = "输出目标为告警才进行配置") 55 @ApiModelProperty(value = "输出目标为告警才进行配置")
53 private String alarmProfileId; 56 private String alarmProfileId;
54 } 57 }
@@ -38,4 +38,7 @@ public class DoConditionDTO extends TenantDTO { @@ -38,4 +38,7 @@ public class DoConditionDTO extends TenantDTO {
38 @ApiModelProperty(value = "场景联动id") 38 @ApiModelProperty(value = "场景联动id")
39 private String sceneLinkageId; 39 private String sceneLinkageId;
40 40
  41 + @ApiModelProperty(value = "场景联动名称")
  42 + private String sceneLinkageName;
  43 +
41 } 44 }
@@ -44,4 +44,13 @@ public class SceneLinkageDTO extends TenantDTO implements HasName { @@ -44,4 +44,13 @@ public class SceneLinkageDTO extends TenantDTO implements HasName {
44 44
45 @ApiModelProperty(value = "创建用户") 45 @ApiModelProperty(value = "创建用户")
46 private String creatorName; 46 private String creatorName;
  47 +
  48 + @NotEmpty(
  49 + message = "规则链ID不能为空或者空字符串",
  50 + groups = {AddGroup.class})
  51 + @ApiModelProperty(value = "规则链ID", required = true)
  52 + private String ruleChainId;
  53 +
  54 + @ApiModelProperty(value = "规则链名称")
  55 + private String ruleChainName;
47 } 56 }
  1 +package org.thingsboard.server.common.data.yunteng.dto.scene;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.io.Serializable;
  6 +import java.util.List;
  7 +
  8 +@Data
  9 +public class SceneLinkageDeviceProfileDTO implements Serializable {
  10 + private String sceneId;
  11 + private String sceneName;
  12 + private List<String> deviceProfileIds;
  13 +
  14 + public SceneLinkageDeviceProfileDTO(String sceneId, String sceneName, List<String> deviceProfileIds) {
  15 + this.sceneId = sceneId;
  16 + this.sceneName = sceneName;
  17 + this.deviceProfileIds = deviceProfileIds;
  18 + }
  19 +}
@@ -43,6 +43,9 @@ public class TriggerDTO extends TenantDTO { @@ -43,6 +43,9 @@ public class TriggerDTO extends TenantDTO {
43 @ApiModelProperty(value = "场景联动id") 43 @ApiModelProperty(value = "场景联动id")
44 private String sceneLinkageId; 44 private String sceneLinkageId;
45 45
  46 + @ApiModelProperty(value = "场景联动名称")
  47 + private String sceneLinkageName;
  48 +
46 public AlarmRule getTriggerCondition() { 49 public AlarmRule getTriggerCondition() {
47 return JacksonUtil.convertValue(triggerCondition,AlarmRule.class); 50 return JacksonUtil.convertValue(triggerCondition,AlarmRule.class);
48 } 51 }
@@ -197,7 +197,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten @@ -197,7 +197,7 @@ public class TenantServiceImpl extends AbstractCachedEntityService<TenantId, Ten
197 publishEvictEvent(new TenantEvictEvent(savedTenant.getId(), create)); 197 publishEvictEvent(new TenantEvictEvent(savedTenant.getId(), create));
198 eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(savedTenant.getId()).entityId(savedTenant.getId()).created(create).build()); 198 eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(savedTenant.getId()).entityId(savedTenant.getId()).created(create).build());
199 if (tenant.getId() == null) { 199 if (tenant.getId() == null) {
200 - DeviceProfile deviceProfile = deviceProfileService.createDefaultDeviceProfile(savedTenant.getId()); 200 + deviceProfileService.createDefaultDeviceProfile(savedTenant.getId());
201 assetProfileService.createDefaultAssetProfile(savedTenant.getId()); 201 assetProfileService.createDefaultAssetProfile(savedTenant.getId());
202 //Thingskit function 202 //Thingskit function
203 deviceProfileService.createDeviceProfile(savedTenant.getId(),"默认MQTT网关设备", DeviceTypeEnum.GATEWAY); 203 deviceProfileService.createDeviceProfile(savedTenant.getId(),"默认MQTT网关设备", DeviceTypeEnum.GATEWAY);
@@ -18,6 +18,7 @@ public class ConvertConfig extends TenantBaseEntity { @@ -18,6 +18,7 @@ public class ConvertConfig extends TenantBaseEntity {
18 private String name; 18 private String name;
19 private String type; 19 private String type;
20 20
  21 + private String ruleChainId;
21 @TableField(typeHandler = EnumTypeHandler.class) 22 @TableField(typeHandler = EnumTypeHandler.class)
22 private DatasourceTypeEnum datasourceType; 23 private DatasourceTypeEnum datasourceType;
23 24
@@ -21,4 +21,6 @@ public class TkSceneLinkageEntity extends TenantBaseEntity { @@ -21,4 +21,6 @@ public class TkSceneLinkageEntity extends TenantBaseEntity {
21 private String description; 21 private String description;
22 22
23 private String organizationId; 23 private String organizationId;
  24 +
  25 + private String ruleChainId;
24 } 26 }
@@ -11,6 +11,8 @@ import org.apache.commons.lang3.StringUtils; @@ -11,6 +11,8 @@ import org.apache.commons.lang3.StringUtils;
11 import org.springframework.stereotype.Service; 11 import org.springframework.stereotype.Service;
12 import org.springframework.transaction.annotation.Transactional; 12 import org.springframework.transaction.annotation.Transactional;
13 import org.thingsboard.common.util.JacksonUtil; 13 import org.thingsboard.common.util.JacksonUtil;
  14 +import org.thingsboard.server.common.data.id.RuleChainId;
  15 +import org.thingsboard.server.common.data.id.TenantId;
14 import org.thingsboard.server.common.data.rule.NodeConnectionInfo; 16 import org.thingsboard.server.common.data.rule.NodeConnectionInfo;
15 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 17 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
16 import org.thingsboard.server.common.data.rule.RuleNode; 18 import org.thingsboard.server.common.data.rule.RuleNode;
@@ -22,54 +24,36 @@ import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO; @@ -22,54 +24,36 @@ import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
22 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; 24 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
23 import org.thingsboard.server.common.data.yunteng.enums.DatasourceTypeEnum; 25 import org.thingsboard.server.common.data.yunteng.enums.DatasourceTypeEnum;
24 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 26 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
  27 +import org.thingsboard.server.dao.rule.RuleChainService;
25 import org.thingsboard.server.dao.yunteng.ConvertConfig; 28 import org.thingsboard.server.dao.yunteng.ConvertConfig;
26 import org.thingsboard.server.dao.yunteng.mapper.ConvertConfigMapper; 29 import org.thingsboard.server.dao.yunteng.mapper.ConvertConfigMapper;
27 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; 30 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
28 import org.thingsboard.server.dao.yunteng.service.ConvertConfigService; 31 import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
29 32
30 -import java.time.LocalDateTime;  
31 import java.util.*; 33 import java.util.*;
32 import java.util.concurrent.ConcurrentHashMap; 34 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.atomic.AtomicInteger; 35 import java.util.concurrent.atomic.AtomicInteger;
  36 +import java.util.stream.Collectors;
34 37
35 @Slf4j 38 @Slf4j
36 @Service 39 @Service
37 @RequiredArgsConstructor 40 @RequiredArgsConstructor
38 public class TkConvertConfigServiceImpl 41 public class TkConvertConfigServiceImpl
39 - extends AbstractBaseService<ConvertConfigMapper, ConvertConfig>  
40 - implements ConvertConfigService { 42 + extends AbstractBaseService<ConvertConfigMapper, ConvertConfig>
  43 + implements ConvertConfigService {
41 private final String connectionType = "Success"; 44 private final String connectionType = "Success";
42 private final String originatorType = 45 private final String originatorType =
43 - "org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode"; 46 + "org.thingsboard.rule.engine.metadata.TbGetOriginatorFieldsNode";
44 private final String sceneOriginatorName = "scene@thingskit"; 47 private final String sceneOriginatorName = "scene@thingskit";
45 private final String scriptType = "org.thingsboard.rule.engine.transform.TbTransformMsgNode"; 48 private final String scriptType = "org.thingsboard.rule.engine.transform.TbTransformMsgNode";
46 private final String filterScriptType = "org.thingsboard.rule.engine.filter.TbJsFilterNode"; 49 private final String filterScriptType = "org.thingsboard.rule.engine.filter.TbJsFilterNode";
47 private final String convertNodeName = "dataConvert@thingskit"; 50 private final String convertNodeName = "dataConvert@thingskit";
  51 + private final RuleChainService ruleChainService;
48 52
49 @Override 53 @Override
50 public TkPageData<ConvertConfigDTO> page(String tenantId, Map<String, Object> queryMap) { 54 public TkPageData<ConvertConfigDTO> page(String tenantId, Map<String, Object> queryMap) {
51 - LocalDateTime startTime = (LocalDateTime) queryMap.get("startTime");  
52 - LocalDateTime endTime = (LocalDateTime) queryMap.get("endTime");  
53 - IPage<ConvertConfig> iPage =  
54 - baseMapper.selectPage(  
55 - getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false),  
56 - new LambdaQueryWrapper<ConvertConfig>()  
57 - .eq(ConvertConfig::getTenantId, tenantId)  
58 - .eq(  
59 - null != queryMap.get("status"),  
60 - ConvertConfig::getStatus,  
61 - queryMap.get("status"))  
62 - .eq(ConvertConfig::getNodeType, queryMap.get("nodeType"))  
63 - .and(  
64 - null != startTime && null != endTime,  
65 - qr ->  
66 - qr.ge(ConvertConfig::getCreateTime, startTime)  
67 - .le(ConvertConfig::getCreateTime, endTime))  
68 - .like(  
69 - null != queryMap.get("name"),  
70 - ConvertConfig::getName,  
71 - String.valueOf(queryMap.get("name")))  
72 - ); 55 + IPage<ConvertConfigDTO> iPage = baseMapper.getConvertPage(
  56 + getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false),tenantId,queryMap);
73 return getPageData(iPage, ConvertConfigDTO.class); 57 return getPageData(iPage, ConvertConfigDTO.class);
74 } 58 }
75 59
@@ -77,6 +61,8 @@ public class TkConvertConfigServiceImpl @@ -77,6 +61,8 @@ public class TkConvertConfigServiceImpl
77 @Transactional 61 @Transactional
78 public ConvertConfigDTO createOrUpdate(ConvertConfigDTO convertConfig) { 62 public ConvertConfigDTO createOrUpdate(ConvertConfigDTO convertConfig) {
79 ConvertConfig config = convertConfig.getEntity(ConvertConfig.class); 63 ConvertConfig config = convertConfig.getEntity(ConvertConfig.class);
  64 + //设置规则链ID
  65 + config.setRuleChainId(getRuleChainId(convertConfig));
80 config.setDatasourceContent( 66 config.setDatasourceContent(
81 JacksonUtil.convertValue(convertConfig.getDatasourceContent(), JsonNode.class)); 67 JacksonUtil.convertValue(convertConfig.getDatasourceContent(), JsonNode.class));
82 if (StringUtils.isNotEmpty(convertConfig.getId())) { 68 if (StringUtils.isNotEmpty(convertConfig.getId())) {
@@ -92,10 +78,9 @@ public class TkConvertConfigServiceImpl @@ -92,10 +78,9 @@ public class TkConvertConfigServiceImpl
92 if (!checkConfig.getName().equals(config.getName())) { 78 if (!checkConfig.getName().equals(config.getName())) {
93 // Check Name 79 // Check Name
94 boolean result = 80 boolean result =
95 - checkConvertConfigNameExist(  
96 - convertConfig.getId(), config.getName(), config.getType(), config.getTenantId()); 81 + checkConvertConfigNameExist(null, config.getName(), config.getType(), config.getTenantId());
97 if (result) { 82 if (result) {
98 - throw new TkDataValidationException(ErrorMessage.NAME_ALREADY_EXISTS.getMessage()); 83 + throw new TkDataValidationException(ErrorMessage.NODE_NAME_ALREADY_EXISTS.getMessage());
99 } 84 }
100 } 85 }
101 // 修改不改状态 86 // 修改不改状态
@@ -107,7 +92,7 @@ public class TkConvertConfigServiceImpl @@ -107,7 +92,7 @@ public class TkConvertConfigServiceImpl
107 checkConvertConfigNameExist( 92 checkConvertConfigNameExist(
108 null, config.getName(), config.getType(), config.getTenantId()); 93 null, config.getName(), config.getType(), config.getTenantId());
109 if (result) { 94 if (result) {
110 - throw new TkDataValidationException(ErrorMessage.NAME_ALREADY_EXISTS.getMessage()); 95 + throw new TkDataValidationException(ErrorMessage.NODE_NAME_ALREADY_EXISTS.getMessage());
111 } 96 }
112 // DEFAULT DISABLE 97 // DEFAULT DISABLE
113 config.setStatus(FastIotConstants.StateValue.DISABLE); 98 config.setStatus(FastIotConstants.StateValue.DISABLE);
@@ -143,12 +128,13 @@ public class TkConvertConfigServiceImpl @@ -143,12 +128,13 @@ public class TkConvertConfigServiceImpl
143 128
144 @Override 129 @Override
145 public ConvertConfigDTO findConvertConfigDTOByName( 130 public ConvertConfigDTO findConvertConfigDTOByName(
146 - String tenantId, String name, Integer nodeType) { 131 + String tenantId, String name,String type, Integer nodeType) {
147 ConvertConfig convertConfig = 132 ConvertConfig convertConfig =
148 baseMapper.selectOne( 133 baseMapper.selectOne(
149 new LambdaQueryWrapper<ConvertConfig>() 134 new LambdaQueryWrapper<ConvertConfig>()
150 .eq(ConvertConfig::getTenantId, tenantId) 135 .eq(ConvertConfig::getTenantId, tenantId)
151 .eq(ConvertConfig::getName, name) 136 .eq(ConvertConfig::getName, name)
  137 + .eq(ConvertConfig::getType,type)
152 .eq(ConvertConfig::getNodeType, nodeType)); 138 .eq(ConvertConfig::getNodeType, nodeType));
153 return null != convertConfig ? convertConfig.getDTO(ConvertConfigDTO.class) : null; 139 return null != convertConfig ? convertConfig.getDTO(ConvertConfigDTO.class) : null;
154 } 140 }
@@ -173,7 +159,12 @@ public class TkConvertConfigServiceImpl @@ -173,7 +159,12 @@ public class TkConvertConfigServiceImpl
173 ruleNode.setType(convertConfig.getType()); 159 ruleNode.setType(convertConfig.getType());
174 ruleNode.setConfiguration(convertConfig.getConfiguration()); 160 ruleNode.setConfiguration(convertConfig.getConfiguration());
175 ruleNode.setAdditionalInfo(convertConfig.getAdditionalInfo()); 161 ruleNode.setAdditionalInfo(convertConfig.getAdditionalInfo());
176 - 162 + if (StringUtils.isNotEmpty(convertConfig.getRuleChainId())) {
  163 + ruleNode.setRuleChainId(
  164 + new RuleChainId(UUID.fromString(convertConfig.getRuleChainId())));
  165 + } else {
  166 + ruleNode.setRuleChainId(ruleChainService.getRootTenantRuleChain(new TenantId(UUID.fromString(convertConfig.getTenantId()))).getId());
  167 + }
177 ruleNodes.add(ruleNode); 168 ruleNodes.add(ruleNode);
178 }); 169 });
179 return ruleNodes; 170 return ruleNodes;
@@ -204,15 +195,16 @@ public class TkConvertConfigServiceImpl @@ -204,15 +195,16 @@ public class TkConvertConfigServiceImpl
204 } 195 }
205 196
206 @Override 197 @Override
207 - public boolean checkConvertJSStatusEnable(String tenantId) { 198 + public boolean checkConvertJSStatusEnable(String tenantId,String ruleChainId) {
208 return baseMapper 199 return baseMapper
209 .selectList( 200 .selectList(
210 - new LambdaQueryWrapper<ConvertConfig>()  
211 - .eq(ConvertConfig::getTenantId, tenantId)  
212 - .eq(ConvertConfig::getStatus, FastIotConstants.StateValue.ENABLE)  
213 - .eq(ConvertConfig::getNodeType, FastIotConstants.JAVA_SCRIPT)) 201 + new LambdaQueryWrapper<ConvertConfig>()
  202 + .eq(ConvertConfig::getTenantId, tenantId)
  203 + .eq(ConvertConfig::getStatus, FastIotConstants.StateValue.ENABLE)
  204 + .eq(ConvertConfig::getNodeType, FastIotConstants.JAVA_SCRIPT)
  205 + .eq(ConvertConfig::getRuleChainId,ruleChainId))
214 .size() 206 .size()
215 - > FastIotConstants.MagicNumber.ZERO; 207 + > FastIotConstants.MagicNumber.ZERO;
216 } 208 }
217 /** 209 /**
218 * 删除规则节点 210 * 删除规则节点
@@ -254,6 +246,41 @@ public class TkConvertConfigServiceImpl @@ -254,6 +246,41 @@ public class TkConvertConfigServiceImpl
254 } 246 }
255 } 247 }
256 248
  249 + @Override
  250 + public RuleChainMetaData getTenantRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId,List<RuleNode> nodes,
  251 + int status,int nodeType,String nodeConnectionName) {
  252 + boolean needSaveRuleNode = true;
  253 + RuleChainMetaData ruleChainMetaData =
  254 + ruleChainService.loadRuleChainMetaData(tenantId, ruleChainId);
  255 + if (status == FastIotConstants.MagicNumber.ZERO) {
  256 + needSaveRuleNode = deleteRuleNode(nodes, ruleChainMetaData, nodeType, tenantId.getId().toString());
  257 + } else {
  258 + addRuleNode(nodes, ruleChainMetaData, nodeType, tenantId.getId().toString());
  259 + //添加节点连接信息
  260 + addConnectionInfo(nodeConnectionName,nodeType,ruleChainMetaData);
  261 + }
  262 + ruleChainMetaData.setNeedSaveRuleNode(needSaveRuleNode);
  263 + return ruleChainMetaData;
  264 + }
  265 +
  266 + @Override
  267 + public boolean deleteConvertConfigByRuleChainId(String tenantId, String ruleChainId, Integer nodeType) {
  268 + nodeType = null == nodeType?0:nodeType;
  269 + return baseMapper.delete(new LambdaQueryWrapper<ConvertConfig>().eq(ConvertConfig::getTenantId,tenantId).
  270 + eq(ConvertConfig::getRuleChainId,ruleChainId).eq(ConvertConfig::getNodeType,nodeType)) > FastIotConstants.MagicNumber.ZERO;
  271 + }
  272 +
  273 + @Override
  274 + public List<ConvertConfigDTO> getConvertConfigUsedByRuleChainIds(String tenantId, List<String> ruleChainIds,Integer nodeType) {
  275 + List<ConvertConfig> convertConfigs = baseMapper.selectList(new LambdaQueryWrapper<ConvertConfig>().
  276 + eq(ConvertConfig::getTenantId,tenantId).eq(null != nodeType,ConvertConfig::getNodeType,nodeType)
  277 + .in(ConvertConfig::getRuleChainId,ruleChainIds));
  278 + if(null != convertConfigs && !convertConfigs.isEmpty()){
  279 + return convertConfigs.stream().map(entity->entity.getDTO(ConvertConfigDTO.class)).collect(Collectors.toList());
  280 + }
  281 + return null;
  282 + }
  283 +
257 private boolean deleteConvertJS(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) { 284 private boolean deleteConvertJS(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData) {
258 boolean needDelete = false; 285 boolean needDelete = false;
259 // 1. Get firstNodeIndex 286 // 1. Get firstNodeIndex
@@ -329,7 +356,7 @@ public class TkConvertConfigServiceImpl @@ -329,7 +356,7 @@ public class TkConvertConfigServiceImpl
329 // 判断数据源是产品、设备、全部 356 // 判断数据源是产品、设备、全部
330 ConvertConfigDTO convertConfigDTO = 357 ConvertConfigDTO convertConfigDTO =
331 findConvertConfigDTOByName( 358 findConvertConfigDTOByName(
332 - tenantId, deleteRuleNode.getName(), FastIotConstants.CONVERT_DATA.intValue()); 359 + tenantId, deleteRuleNode.getName(),deleteRuleNode.getType(), FastIotConstants.CONVERT_DATA.intValue());
333 boolean haveFilterNode = false; 360 boolean haveFilterNode = false;
334 String filterNodeName = null; 361 String filterNodeName = null;
335 String filterType = null; 362 String filterType = null;
@@ -522,7 +549,7 @@ public class TkConvertConfigServiceImpl @@ -522,7 +549,7 @@ public class TkConvertConfigServiceImpl
522 // estimate datasource type 549 // estimate datasource type
523 ConvertConfigDTO convertConfigDTO = 550 ConvertConfigDTO convertConfigDTO =
524 findConvertConfigDTOByName( 551 findConvertConfigDTOByName(
525 - tenantId, ruleNode.getName(), FastIotConstants.CONVERT_DATA.intValue()); 552 + tenantId, ruleNode.getName(),ruleNode.getType(), FastIotConstants.CONVERT_DATA.intValue());
526 if (null != convertConfigDTO 553 if (null != convertConfigDTO
527 && null != convertConfigDTO.getDatasourceType() 554 && null != convertConfigDTO.getDatasourceType()
528 && !Objects.equals(convertConfigDTO.getDatasourceType(), DatasourceTypeEnum.ALL)) { 555 && !Objects.equals(convertConfigDTO.getDatasourceType(), DatasourceTypeEnum.ALL)) {
@@ -849,4 +876,33 @@ public class TkConvertConfigServiceImpl @@ -849,4 +876,33 @@ public class TkConvertConfigServiceImpl
849 objectNode.put("layoutY", layoutY + randomNum); 876 objectNode.put("layoutY", layoutY + randomNum);
850 return objectNode; 877 return objectNode;
851 } 878 }
  879 +
  880 + private String getRuleChainId(ConvertConfigDTO convertConfig){
  881 + //通过nodeType区分是转换脚本(0)、数据流转(1)
  882 + return StringUtils.isNotEmpty(convertConfig.getRuleChainId()) ? convertConfig.getRuleChainId():
  883 + ruleChainService.getRootTenantRuleChain(new TenantId(UUID.fromString(convertConfig.getTenantId()))).getId().toString();
  884 + }
  885 +
  886 + private void addConnectionInfo(String nodeConnectionName,Integer nodeType,RuleChainMetaData ruleChainMetaData){
  887 + if(null != nodeConnectionName && nodeType == FastIotConstants.SCENE_REACT){
  888 + int i = 0;
  889 + //查找事件节点下标
  890 + int formIndex = 0;
  891 + int toIndex = 0;
  892 + for(RuleNode ruleNode : ruleChainMetaData.getNodes()){
  893 + if(ruleNode.getType().equals(nodeConnectionName)){
  894 + formIndex = i;
  895 + }
  896 + if(ruleNode.getType().equals(FastIotConstants.TkNodeClassName.GET_ORIGINATOR_FIELDS_NODE)){
  897 + toIndex = i;
  898 + }
  899 + i++;
  900 + }
  901 + NodeConnectionInfo newConnectionInfo = new NodeConnectionInfo();
  902 + newConnectionInfo.setFromIndex(formIndex);
  903 + newConnectionInfo.setToIndex(toIndex);
  904 + newConnectionInfo.setType("SUCCESS");
  905 + ruleChainMetaData.getConnections().add(newConnectionInfo);
  906 + }
  907 + }
852 } 908 }
@@ -15,33 +15,30 @@ import org.thingsboard.server.common.data.device.profile.*; @@ -15,33 +15,30 @@ import org.thingsboard.server.common.data.device.profile.*;
15 import org.thingsboard.server.common.data.id.*; 15 import org.thingsboard.server.common.data.id.*;
16 import org.thingsboard.server.common.data.rule.RuleChain; 16 import org.thingsboard.server.common.data.rule.RuleChain;
17 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 17 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
18 -import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;  
19 import org.thingsboard.server.common.data.yunteng.constant.QueryConstant; 18 import org.thingsboard.server.common.data.yunteng.constant.QueryConstant;
20 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; 19 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
21 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; 20 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
22 import org.thingsboard.server.common.data.yunteng.dto.*; 21 import org.thingsboard.server.common.data.yunteng.dto.*;
  22 +import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
  23 +import org.thingsboard.server.common.data.yunteng.dto.scene.SceneLinkageDeviceProfileDTO;
23 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; 24 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum;
24 -import org.thingsboard.server.common.data.yunteng.enums.FunctionTypeEnum;  
25 import org.thingsboard.server.common.data.yunteng.enums.TcpAuthTypeEnum; 25 import org.thingsboard.server.common.data.yunteng.enums.TcpAuthTypeEnum;
26 import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; 26 import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum;
27 -import org.thingsboard.server.common.data.yunteng.id.TkThingsModelId;  
28 import org.thingsboard.server.common.data.yunteng.utils.CopyUtils; 27 import org.thingsboard.server.common.data.yunteng.utils.CopyUtils;
29 import org.thingsboard.server.common.data.yunteng.utils.DateTimeUtils; 28 import org.thingsboard.server.common.data.yunteng.utils.DateTimeUtils;
30 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; 29 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;
31 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 30 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
32 import org.thingsboard.server.dao.rule.RuleChainService; 31 import org.thingsboard.server.dao.rule.RuleChainService;
33 import org.thingsboard.server.dao.yunteng.entities.*; 32 import org.thingsboard.server.dao.yunteng.entities.*;
34 -import org.thingsboard.server.dao.yunteng.event.TkEdgeSyncService;  
35 import org.thingsboard.server.dao.yunteng.mapper.DeviceMapper; 33 import org.thingsboard.server.dao.yunteng.mapper.DeviceMapper;
36 -import org.thingsboard.server.dao.yunteng.mapper.ThingsModelMapper;  
37 import org.thingsboard.server.dao.yunteng.mapper.TkDeviceProfileCategoryMapper; 34 import org.thingsboard.server.dao.yunteng.mapper.TkDeviceProfileCategoryMapper;
38 import org.thingsboard.server.dao.yunteng.mapper.TkDeviceProfileMapper; 35 import org.thingsboard.server.dao.yunteng.mapper.TkDeviceProfileMapper;
39 -import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;  
40 import org.thingsboard.server.dao.yunteng.service.AbstractTbBaseService; 36 import org.thingsboard.server.dao.yunteng.service.AbstractTbBaseService;
  37 +import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
  38 +import org.thingsboard.server.dao.yunteng.service.SceneLinkageService;
41 import org.thingsboard.server.dao.yunteng.service.TkDeviceProfileService; 39 import org.thingsboard.server.dao.yunteng.service.TkDeviceProfileService;
42 40
43 import java.time.LocalDateTime; 41 import java.time.LocalDateTime;
44 -import java.time.ZoneOffset;  
45 import java.util.*; 42 import java.util.*;
46 import java.util.stream.Collectors; 43 import java.util.stream.Collectors;
47 44
@@ -58,6 +55,10 @@ public class TkDeviceProfileServiceImpl @@ -58,6 +55,10 @@ public class TkDeviceProfileServiceImpl
58 55
59 private final RuleChainService ruleChainService; 56 private final RuleChainService ruleChainService;
60 57
  58 + private final ConvertConfigService convertConfigService;
  59 +
  60 + private final SceneLinkageService sceneLinkageService;
  61 +
61 62
62 63
63 @Override 64 @Override
@@ -184,6 +185,83 @@ public class TkDeviceProfileServiceImpl @@ -184,6 +185,83 @@ public class TkDeviceProfileServiceImpl
184 return tbDeviceProfile; 185 return tbDeviceProfile;
185 } 186 }
186 187
  188 + @Override
  189 + public List<String> checkRuleChainIdUsedByDeviceProfiles(String tenantId, UUID ruleChainId) {
  190 + List<TkDeviceProfileEntity> entities=baseMapper.selectList(new LambdaQueryWrapper<TkDeviceProfileEntity>().eq(TkDeviceProfileEntity::getTenantId,
  191 + UUID.fromString(tenantId)).eq(TkDeviceProfileEntity::getDefaultRuleChainId,ruleChainId));
  192 + if(null == entities || entities.isEmpty()){
  193 + return null;
  194 + }
  195 + return entities.stream().map(entity->entity.getName()).collect(Collectors.toList());
  196 + }
  197 +
  198 + @Override
  199 + public void checkDeviceProfilesCanChangeRuleChain(List<String> deviceProfileIds, TenantId tenantId) {
  200 + List<UUID> queryDeviceProfileIds = deviceProfileIds.stream().map(UUID::fromString).collect(Collectors.toList());
  201 + //判断以上产品配置是否都属于该租户
  202 + List<TkDeviceProfileEntity> entities = baseMapper.selectList(new LambdaQueryWrapper<TkDeviceProfileEntity>().
  203 + eq(TkDeviceProfileEntity::getTenantId,tenantId.getId()).in(TkDeviceProfileEntity::getId,queryDeviceProfileIds));
  204 + if(null == entities || entities.size() != deviceProfileIds.size()){
  205 + throw new TkDataValidationException(ErrorMessage.NOT_BELONG_CURRENT_TENANT.getMessage());
  206 + }
  207 + Set<String> ruleChainIds = new HashSet<>(entities.stream().map(entity->entity.getDefaultRuleChainId().toString()).collect(Collectors.toList()));
  208 + //按规则链进行分类,找到具体的产品
  209 + Map<UUID,List<TkDeviceProfileEntity>> classification = entities.stream().collect(Collectors.groupingBy(TkDeviceProfileEntity::getDefaultRuleChainId));
  210 + //判断数据流转是否使用该规则链
  211 + checkDataConvertUsedDeviceProfile(tenantId.getId().toString(),new ArrayList<>(ruleChainIds),classification);
  212 + // 判断选中的产品是否被场景联动使用
  213 + checkSceneLinkageUsedDeviceProfile(
  214 + tenantId.getId().toString(), entities, deviceProfileIds, new ArrayList<>(ruleChainIds));
  215 + }
  216 +
  217 + private void checkDataConvertUsedDeviceProfile(String tenantId,List<String>ruleChainIds,Map<UUID,List<TkDeviceProfileEntity>> classification){
  218 + List<ConvertConfigDTO> convertConfigs = convertConfigService.getConvertConfigUsedByRuleChainIds(tenantId,ruleChainIds,1);
  219 + if(null !=convertConfigs && !convertConfigs.isEmpty()){
  220 + convertConfigs.stream().forEach(convertEntity->{
  221 + //找出这个规则链里面,有哪些产品被数据流转使用了
  222 + JsonNode datasource = convertEntity.getDatasourceContent();
  223 + if(null != datasource){
  224 + JsonNode usedDeviceProfileIds = datasource.get("convertProducts");
  225 + List<String> ids = null;
  226 + if(usedDeviceProfileIds.isArray()){
  227 + Iterator<JsonNode> iteratorNodes = usedDeviceProfileIds.iterator();
  228 + while (iteratorNodes.hasNext()){
  229 + ids.add(iteratorNodes.next().asText());
  230 + }
  231 + }
  232 + if(null != ids){
  233 + classification.entrySet().forEach(key->{
  234 + for (TkDeviceProfileEntity entity : classification.get(key)) {
  235 + if(ids.contains(entity.getId().toString())){
  236 + throw new TkDataValidationException(String.format(ErrorMessage.
  237 + CHOICE_DEVICE_PROFILE_RULE_CHAIN_IS_USED_FOR_CONVERT.getMessage(),entity.getName(),convertEntity.getName()));
  238 + }
  239 + }
  240 + });
  241 +
  242 + }
  243 + }
  244 + });
  245 + }
  246 + }
  247 + private void checkSceneLinkageUsedDeviceProfile(String tenantId,List<TkDeviceProfileEntity> entityList,List<String> choiceDeviceProfileIds,List<String> ruleChainIds){
  248 + //通过选中产品ID列表,判断是否有被场景联动使用
  249 + SceneLinkageDeviceProfileDTO usedSceneLinkage = sceneLinkageService.checkDeviceProfileIdsUsedForSceneLinkage(tenantId,choiceDeviceProfileIds,ruleChainIds);
  250 + if(null != usedSceneLinkage){
  251 + //被场景联动使用了,才进行逻辑处理
  252 + String sceneName = usedSceneLinkage.getSceneName();
  253 + List<String> deviceProfileIds = usedSceneLinkage.getDeviceProfileIds();
  254 + if(null != deviceProfileIds && !deviceProfileIds.isEmpty()){
  255 + entityList.forEach(deviceProfileEntity->{
  256 + if(deviceProfileIds.contains(deviceProfileEntity.getId().toString())){
  257 + throw new TkDataValidationException(String.format(ErrorMessage.
  258 + CHOICE_DEVICE_PROFILE_RULE_CHAIN_IS_USED_FOR_SCENE.getMessage(),
  259 + deviceProfileEntity.getName(),sceneName));
  260 + }
  261 + });
  262 + }
  263 + }
  264 + }
187 private void setDeviceScriptId(DeviceProfile profile, DeviceProfileTransportConfiguration transportConfiguration) { 265 private void setDeviceScriptId(DeviceProfile profile, DeviceProfileTransportConfiguration transportConfiguration) {
188 JsonNode jsonNode = JacksonUtil.convertValue(transportConfiguration, JsonNode.class); 266 JsonNode jsonNode = JacksonUtil.convertValue(transportConfiguration, JsonNode.class);
189 if (null != jsonNode) { 267 if (null != jsonNode) {
@@ -266,9 +344,10 @@ public class TkDeviceProfileServiceImpl @@ -266,9 +344,10 @@ public class TkDeviceProfileServiceImpl
266 344
267 @Override 345 @Override
268 public List<DeviceProfileDTO> findDeviceProfile( 346 public List<DeviceProfileDTO> findDeviceProfile(
269 - TenantId tenantId, String scriptId, DeviceTypeEnum deviceType, DeviceTransportType transportType,Boolean isSceneLinkage) { 347 + TenantId tenantId, String scriptId, DeviceTypeEnum deviceType, DeviceTransportType transportType,
  348 + Boolean isSceneLinkage,String ruleChainId) {
270 List<TkDeviceProfileEntity> listEntity = 349 List<TkDeviceProfileEntity> listEntity =
271 - baseMapper.profileByScriptId(tenantId.getId(), scriptId, deviceType, transportType, null,isSceneLinkage); 350 + baseMapper.profileByScriptId(tenantId.getId(), scriptId, deviceType, transportType, null,isSceneLinkage,ruleChainId);
272 return listEntity.stream().map(entity -> { 351 return listEntity.stream().map(entity -> {
273 return CopyUtils.copyAndReturn(entity, new DeviceProfileDTO()); 352 return CopyUtils.copyAndReturn(entity, new DeviceProfileDTO());
274 } 353 }
@@ -291,7 +370,7 @@ public class TkDeviceProfileServiceImpl @@ -291,7 +370,7 @@ public class TkDeviceProfileServiceImpl
291 if (null == deviceProfileIds || deviceProfileIds.isEmpty()) { 370 if (null == deviceProfileIds || deviceProfileIds.isEmpty()) {
292 return null; 371 return null;
293 } 372 }
294 - return baseMapper.profileByScriptId(tenantId.getId(), null, deviceType, transportType, deviceProfileIds,false); 373 + return baseMapper.profileByScriptId(tenantId.getId(), null, deviceType, transportType, deviceProfileIds,false,null);
295 } 374 }
296 375
297 @Override 376 @Override
@@ -299,7 +378,11 @@ public class TkDeviceProfileServiceImpl @@ -299,7 +378,11 @@ public class TkDeviceProfileServiceImpl
299 if (tenantId == null || null == ids) { 378 if (tenantId == null || null == ids) {
300 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 379 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
301 } 380 }
302 - return baseMapper.profileByTransportAndIds(tenantId, ids, transportType); 381 + List<TkDeviceProfileEntity> entities = baseMapper.profileByTransportAndIds(tenantId, ids, transportType);
  382 + if(null == entities || entities.isEmpty()){
  383 + return null;
  384 + }
  385 + return entities.stream().map(entity->entity.getDTO(DeviceProfileDTO.class)).collect(Collectors.toList());
303 } 386 }
304 387
305 @Override 388 @Override
@@ -42,4 +42,14 @@ public class TkDoActionServiceImpl extends AbstractBaseService<DoActionMapper, T @@ -42,4 +42,14 @@ public class TkDoActionServiceImpl extends AbstractBaseService<DoActionMapper, T
42 .map(doAction -> doAction.getDTO(DoActionDTO.class)) 42 .map(doAction -> doAction.getDTO(DoActionDTO.class))
43 .collect(Collectors.toList()); 43 .collect(Collectors.toList());
44 } 44 }
  45 +
  46 + @Override
  47 + public List<DoActionDTO> findDoActionsBySceneLinkageIds(String tenantId, List<String> sceneLinkageIds) {
  48 + List<TkDoActionEntity> entities = baseMapper.selectList(new LambdaQueryWrapper<TkDoActionEntity>().eq(TkDoActionEntity::getTenantId,tenantId)
  49 + .in(TkDoActionEntity::getSceneLinkageId,sceneLinkageIds));
  50 + if(null !=entities && !entities.isEmpty()){
  51 + return entities.stream().map(entity->entity.getDTO(DoActionDTO.class)).collect(Collectors.toList());
  52 + }
  53 + return null;
  54 + }
45 } 55 }
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 import lombok.RequiredArgsConstructor; 5 import lombok.RequiredArgsConstructor;
6 import org.springframework.stereotype.Service; 6 import org.springframework.stereotype.Service;
  7 +import org.thingsboard.server.common.data.yunteng.dto.scene.DoConditionDTO;
7 import org.thingsboard.server.dao.yunteng.entities.TkDoConditionEntity; 8 import org.thingsboard.server.dao.yunteng.entities.TkDoConditionEntity;
8 import org.thingsboard.server.dao.yunteng.mapper.DoConditionMapper; 9 import org.thingsboard.server.dao.yunteng.mapper.DoConditionMapper;
9 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; 10 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
@@ -20,12 +21,16 @@ import java.util.List; @@ -20,12 +21,16 @@ import java.util.List;
20 @RequiredArgsConstructor 21 @RequiredArgsConstructor
21 public class TkDoConditionServiceImpl extends AbstractBaseService<DoConditionMapper, TkDoConditionEntity> 22 public class TkDoConditionServiceImpl extends AbstractBaseService<DoConditionMapper, TkDoConditionEntity>
22 implements DoConditionService { 23 implements DoConditionService {
23 - private final DoConditionMapper triggerMapper; 24 + private final DoConditionMapper baseMapper;
24 @Override 25 @Override
25 public List<TkDoConditionEntity> getConditions(String sceneId) { 26 public List<TkDoConditionEntity> getConditions(String sceneId) {
26 LambdaQueryWrapper filter = new QueryWrapper<TkDoConditionEntity>().lambda() 27 LambdaQueryWrapper filter = new QueryWrapper<TkDoConditionEntity>().lambda()
27 .eq(TkDoConditionEntity::getSceneLinkageId,sceneId); 28 .eq(TkDoConditionEntity::getSceneLinkageId,sceneId);
28 - return triggerMapper.selectList(filter); 29 + return baseMapper.selectList(filter);
29 } 30 }
30 31
  32 + @Override
  33 + public List<DoConditionDTO> listByDeviceProfileIds(String tenantId, List<String> deviceProfileIds) {
  34 + return baseMapper.listByDeviceProfileIds(tenantId,deviceProfileIds);
  35 + }
31 } 36 }
@@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.JsonNode; @@ -7,6 +7,7 @@ import com.fasterxml.jackson.databind.JsonNode;
7 import com.fasterxml.jackson.databind.node.ObjectNode; 7 import com.fasterxml.jackson.databind.node.ObjectNode;
8 import java.util.*; 8 import java.util.*;
9 import java.util.concurrent.atomic.AtomicBoolean; 9 import java.util.concurrent.atomic.AtomicBoolean;
  10 +import java.util.concurrent.atomic.AtomicReference;
10 import java.util.stream.Collectors; 11 import java.util.stream.Collectors;
11 import lombok.RequiredArgsConstructor; 12 import lombok.RequiredArgsConstructor;
12 import org.apache.commons.lang3.StringUtils; 13 import org.apache.commons.lang3.StringUtils;
@@ -635,7 +636,54 @@ public class TkSceneLinkageServiceImpl @@ -635,7 +636,54 @@ public class TkSceneLinkageServiceImpl
635 } 636 }
636 637
637 @Override 638 @Override
638 - public SceneLinkageDTO selectById( String id) {  
639 - return baseMapper.findById(id); 639 + public SceneLinkageDTO selectById(String tenantId,String id) {
  640 + return baseMapper.findById(tenantId,id);
  641 + }
  642 + @Override
  643 + public SceneLinkageDeviceProfileDTO checkDeviceProfileIdsUsedForSceneLinkage(String tenantId, List<String> deviceProfileIds,List<String> ruleChainIds) {
  644 + //先判断触发器是否被场景联动使用
  645 + List<TriggerDTO> triggers = triggerService.getTriggersByDeviceProfileIds(tenantId,deviceProfileIds);
  646 + if(null != triggers && !triggers.isEmpty()){
  647 + TriggerDTO triggerDTO = triggers.get(0);
  648 + return new SceneLinkageDeviceProfileDTO(triggerDTO.getSceneLinkageId(),triggerDTO.getSceneLinkageName(),List.of(triggerDTO.getDeviceProfileId()));
  649 + }
  650 + //再判断执行条件是否被场景联动使用
  651 + List<DoConditionDTO> doConditions = doConditionService.listByDeviceProfileIds(tenantId,deviceProfileIds);
  652 + if(null != doConditions && !doConditions.isEmpty()){
  653 + DoConditionDTO doCondition = doConditions.get(0);
  654 + return new SceneLinkageDeviceProfileDTO(doCondition.getSceneLinkageId(),doCondition.getSceneLinkageName(),List.of(doCondition.getDeviceProfileId()));
  655 + }
  656 + //最后判断执行动作是否被场景联动使用
  657 + List<TkSceneLinkageEntity>entities = baseMapper.selectList(new LambdaQueryWrapper<TkSceneLinkageEntity>().eq(TkSceneLinkageEntity::getTenantId,tenantId)
  658 + .in(TkSceneLinkageEntity::getRuleChainId,ruleChainIds));
  659 + if(null !=entities && !entities.isEmpty()){
  660 + List<String> sceneLinkageIds = entities.stream().map(entity->entity.getId()).collect(Collectors.toList());
  661 + List<DoActionDTO> doActionList = doActionService.findDoActionsBySceneLinkageIds(tenantId,sceneLinkageIds);
  662 + if(null !=doActionList && !doActionList.isEmpty()){
  663 + for (DoActionDTO entity :doActionList){
  664 + if(entity.getOutTarget().equals(ActionTypeEnum.DEVICE_OUT)){
  665 + if(deviceProfileIds.contains(entity.getDeviceProfileId())){
  666 + return new SceneLinkageDeviceProfileDTO(entity.getSceneLinkageId(), entity.getSceneLinkageName(), List.of(entity.getDeviceProfileId()));
  667 + }
  668 + }
  669 + if(entity.getOutTarget().equals(ActionTypeEnum.MSG_NOTIFY)){
  670 + JsonNode doContext = entity.getDoContext();
  671 + if(null !=doContext){
  672 + JsonNode clearRuleJsonNode = doContext.get("clearRule");
  673 + if(null !=clearRuleJsonNode && clearRuleJsonNode.isArray()){
  674 + Iterator<JsonNode> iteratorNodes = clearRuleJsonNode.iterator();
  675 + while (iteratorNodes.hasNext()){
  676 + String deviceProfileId = iteratorNodes.next().get("deviceProfileId").asText();
  677 + if(deviceProfileIds.contains(deviceProfileId)){
  678 + return new SceneLinkageDeviceProfileDTO(entity.getSceneLinkageId(), entity.getSceneLinkageName(), List.of(deviceProfileId));
  679 + }
  680 + }
  681 + }
  682 + }
  683 + }
  684 + }
  685 + }
  686 + }
  687 + return null;
640 } 688 }
641 } 689 }
@@ -39,4 +39,9 @@ public class TkTriggerServiceImpl extends AbstractBaseService<TriggerMapper, TkT @@ -39,4 +39,9 @@ public class TkTriggerServiceImpl extends AbstractBaseService<TriggerMapper, TkT
39 .map(item -> item.getDTO(TriggerDTO.class)) 39 .map(item -> item.getDTO(TriggerDTO.class))
40 .collect(Collectors.toList()); 40 .collect(Collectors.toList());
41 } 41 }
  42 +
  43 + @Override
  44 + public List<TriggerDTO> getTriggersByDeviceProfileIds(String tenantId, List<String> deviceProfileIds) {
  45 + return triggerMapper.listByDeviceProfileIds(tenantId,deviceProfileIds);
  46 + }
42 } 47 }
1 package org.thingsboard.server.dao.yunteng.mapper; 1 package org.thingsboard.server.dao.yunteng.mapper;
2 2
3 import com.baomidou.mybatisplus.core.mapper.BaseMapper; 3 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4 +import com.baomidou.mybatisplus.core.metadata.IPage;
4 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
5 import org.apache.ibatis.annotations.Param; 6 import org.apache.ibatis.annotations.Param;
  7 +import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
6 import org.thingsboard.server.dao.yunteng.ConvertConfig; 8 import org.thingsboard.server.dao.yunteng.ConvertConfig;
7 9
8 import java.util.List; 10 import java.util.List;
  11 +import java.util.Map;
9 12
10 @Mapper 13 @Mapper
11 public interface ConvertConfigMapper extends BaseMapper<ConvertConfig> { 14 public interface ConvertConfigMapper extends BaseMapper<ConvertConfig> {
  15 + IPage<ConvertConfigDTO> getConvertPage(
  16 + IPage<?> page,@Param("tenantId") String tenantId, @Param("queryMap") Map<String, Object> queryMap);
12 boolean updateConvertStatusByIds( 17 boolean updateConvertStatusByIds(
13 @Param("tenantId") String tenantId, @Param("ids") List<String> ids, @Param("status") Integer status); 18 @Param("tenantId") String tenantId, @Param("ids") List<String> ids, @Param("status") Integer status);
14 } 19 }
@@ -16,4 +16,6 @@ import java.util.List; @@ -16,4 +16,6 @@ import java.util.List;
16 @Mapper 16 @Mapper
17 public interface DoActionMapper extends BaseMapper<TkDoActionEntity> { 17 public interface DoActionMapper extends BaseMapper<TkDoActionEntity> {
18 List<DoActionDTO> listBySceneId(@Param("sceneId") String sceneId); 18 List<DoActionDTO> listBySceneId(@Param("sceneId") String sceneId);
  19 +
  20 + List<DoActionDTO> listBySceneLinkageIds(@Param("tenantId") String tenantId,@Param("sceneLinkageIds") List<String> sceneLinkageIds);
19 } 21 }
@@ -16,4 +16,6 @@ import java.util.List; @@ -16,4 +16,6 @@ import java.util.List;
16 @Mapper 16 @Mapper
17 public interface DoConditionMapper extends BaseMapper<TkDoConditionEntity> { 17 public interface DoConditionMapper extends BaseMapper<TkDoConditionEntity> {
18 List<DoConditionDTO> listBySceneId(@Param("sceneId") String sceneId); 18 List<DoConditionDTO> listBySceneId(@Param("sceneId") String sceneId);
  19 +
  20 + List<DoConditionDTO> listByDeviceProfileIds(@Param("tenantId")String tenantId,@Param("deviceProfileIds")List<String> deviceProfileIds);
19 } 21 }
@@ -30,6 +30,6 @@ public interface SceneLinkageMapper extends BaseMapper<TkSceneLinkageEntity> { @@ -30,6 +30,6 @@ public interface SceneLinkageMapper extends BaseMapper<TkSceneLinkageEntity> {
30 * @param id 30 * @param id
31 * @return 31 * @return
32 */ 32 */
33 - SceneLinkageDTO findById( @Param("id") String id); 33 + SceneLinkageDTO findById(@Param("tenantId") String tenantId, @Param("id") String id);
34 34
35 } 35 }
@@ -5,9 +5,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage; @@ -5,9 +5,6 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
5 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
6 import org.apache.ibatis.annotations.Param; 6 import org.apache.ibatis.annotations.Param;
7 import org.thingsboard.server.common.data.DeviceTransportType; 7 import org.thingsboard.server.common.data.DeviceTransportType;
8 -import org.thingsboard.server.common.data.id.DeviceProfileId;  
9 -import org.thingsboard.server.common.data.id.TenantId;  
10 -import org.thingsboard.server.common.data.yunteng.dto.*;  
11 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; 8 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum;
12 import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum; 9 import org.thingsboard.server.common.data.yunteng.enums.TransportTypeEnum;
13 import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity; 10 import org.thingsboard.server.dao.yunteng.entities.TkDeviceProfileEntity;
@@ -39,9 +36,10 @@ public interface TkDeviceProfileMapper extends BaseMapper<TkDeviceProfileEntity> @@ -39,9 +36,10 @@ public interface TkDeviceProfileMapper extends BaseMapper<TkDeviceProfileEntity>
39 @Param("deviceType") DeviceTypeEnum deviceType, 36 @Param("deviceType") DeviceTypeEnum deviceType,
40 @Param("transportType")DeviceTransportType transportType, 37 @Param("transportType")DeviceTransportType transportType,
41 @Param("deviceProfileIds")List<UUID> deviceProfileIds, 38 @Param("deviceProfileIds")List<UUID> deviceProfileIds,
42 - @Param("isSceneLinkage") Boolean isSceneLinkage); 39 + @Param("isSceneLinkage") Boolean isSceneLinkage,
  40 + @Param("ruleChainId") String ruleChainId);
43 41
44 - List<DeviceProfileDTO> profileByTransportAndIds( 42 + List<TkDeviceProfileEntity> profileByTransportAndIds(
45 @Param("tenantId") UUID tenantId, 43 @Param("tenantId") UUID tenantId,
46 @Param("projectIds") List<String> projectIds, 44 @Param("projectIds") List<String> projectIds,
47 @Param("deviceType") TransportTypeEnum transportType); 45 @Param("deviceType") TransportTypeEnum transportType);
@@ -17,4 +17,6 @@ import java.util.List; @@ -17,4 +17,6 @@ import java.util.List;
17 public interface TriggerMapper extends BaseMapper<TkTriggerEntity> { 17 public interface TriggerMapper extends BaseMapper<TkTriggerEntity> {
18 18
19 List<TriggerDTO> listBySceneId(@Param("sceneId") String sceneId); 19 List<TriggerDTO> listBySceneId(@Param("sceneId") String sceneId);
  20 +
  21 + List<TriggerDTO> listByDeviceProfileIds(@Param("tenantId")String tenantId,@Param("deviceProfileIds")List<String> deviceProfileIds);
20 } 22 }
1 package org.thingsboard.server.dao.yunteng.service; 1 package org.thingsboard.server.dao.yunteng.service;
2 2
  3 +import org.thingsboard.server.common.data.id.RuleChainId;
  4 +import org.thingsboard.server.common.data.id.TenantId;
3 import org.thingsboard.server.common.data.rule.RuleChainMetaData; 5 import org.thingsboard.server.common.data.rule.RuleChainMetaData;
4 import org.thingsboard.server.common.data.rule.RuleNode; 6 import org.thingsboard.server.common.data.rule.RuleNode;
5 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO; 7 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
@@ -21,7 +23,7 @@ public interface ConvertConfigService extends BaseService<ConvertConfig> { @@ -21,7 +23,7 @@ public interface ConvertConfigService extends BaseService<ConvertConfig> {
21 23
22 boolean deleteConvertConfig(DeleteDTO deleteDTO, Integer nodeType); 24 boolean deleteConvertConfig(DeleteDTO deleteDTO, Integer nodeType);
23 25
24 - ConvertConfigDTO findConvertConfigDTOByName(String tenantId,String name,Integer nodeType); 26 + ConvertConfigDTO findConvertConfigDTOByName(String tenantId,String name,String type,Integer nodeType);
25 /** 27 /**
26 * 通过数据转换的IDS获取需要组装的节点 28 * 通过数据转换的IDS获取需要组装的节点
27 * 29 *
@@ -57,12 +59,35 @@ public interface ConvertConfigService extends BaseService<ConvertConfig> { @@ -57,12 +59,35 @@ public interface ConvertConfigService extends BaseService<ConvertConfig> {
57 * 检查该租户下是否已启用转换脚本状态 59 * 检查该租户下是否已启用转换脚本状态
58 * 60 *
59 * @param tenantId 租户ID 61 * @param tenantId 租户ID
  62 + * @param ruleChainId 规则链ID
60 * @return true已启用 false未启用 63 * @return true已启用 false未启用
61 */ 64 */
62 - boolean checkConvertJSStatusEnable(String tenantId); 65 + boolean checkConvertJSStatusEnable(String tenantId,String ruleChainId);
63 66
64 boolean deleteRuleNode( 67 boolean deleteRuleNode(
65 List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType,String tenantId); 68 List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType,String tenantId);
66 69
67 void addRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType,String tenantId); 70 void addRuleNode(List<RuleNode> nodes, RuleChainMetaData ruleChainMetaData, Integer nodeType,String tenantId);
  71 +
  72 + RuleChainMetaData getTenantRuleChainMetaData(TenantId tenantId, RuleChainId ruleChainId, List<RuleNode> nodes,
  73 + int status, int nodeType, String nodeConnectionName);
  74 +
  75 + /**
  76 + * 根据规则链ID删除对应的转换脚本
  77 + * @param tenantId
  78 + * @param ruleChainId
  79 + * @param nodeType
  80 + * @return
  81 + */
  82 + boolean deleteConvertConfigByRuleChainId(String tenantId,String ruleChainId,Integer nodeType);
  83 +
  84 +
  85 + /**
  86 + * 检查数据流转或规则链转换脚本使用了以下规则链
  87 + * @param tenantId 租户ID
  88 + * @param ruleChainIds 规则链ID列表
  89 + * @param nodeType 0 转换脚本 1数据流转
  90 + * @return 返回使用以下规则链的数据流转或规则链转换脚本信息
  91 + */
  92 + List<ConvertConfigDTO> getConvertConfigUsedByRuleChainIds(String tenantId,List<String> ruleChainIds,Integer nodeType);
68 } 93 }
@@ -16,4 +16,6 @@ public interface DoActionService extends BaseService<TkDoActionEntity>{ @@ -16,4 +16,6 @@ public interface DoActionService extends BaseService<TkDoActionEntity>{
16 List<TkDoActionEntity> getActionsByAll(String sceneId,String tenantId); 16 List<TkDoActionEntity> getActionsByAll(String sceneId,String tenantId);
17 17
18 List<DoActionDTO> findDoActionByAlarmProfileIds(String tenantId, Set<String> alarmProfileIds); 18 List<DoActionDTO> findDoActionByAlarmProfileIds(String tenantId, Set<String> alarmProfileIds);
  19 +
  20 + List<DoActionDTO> findDoActionsBySceneLinkageIds(String tenantId,List<String> sceneLinkageIds);
19 } 21 }
1 package org.thingsboard.server.dao.yunteng.service; 1 package org.thingsboard.server.dao.yunteng.service;
2 2
  3 +import org.thingsboard.server.common.data.yunteng.dto.scene.DoConditionDTO;
3 import org.thingsboard.server.dao.yunteng.entities.TkDoConditionEntity; 4 import org.thingsboard.server.dao.yunteng.entities.TkDoConditionEntity;
4 5
5 import java.util.List; 6 import java.util.List;
@@ -11,4 +12,6 @@ import java.util.List; @@ -11,4 +12,6 @@ import java.util.List;
11 */ 12 */
12 public interface DoConditionService extends BaseService<TkDoConditionEntity>{ 13 public interface DoConditionService extends BaseService<TkDoConditionEntity>{
13 List<TkDoConditionEntity> getConditions(String sceneId); 14 List<TkDoConditionEntity> getConditions(String sceneId);
  15 +
  16 + List<DoConditionDTO> listByDeviceProfileIds(String tenantId,List<String> deviceProfileIds);
14 } 17 }
@@ -2,6 +2,7 @@ package org.thingsboard.server.dao.yunteng.service; @@ -2,6 +2,7 @@ package org.thingsboard.server.dao.yunteng.service;
2 import com.fasterxml.jackson.databind.JsonNode; 2 import com.fasterxml.jackson.databind.JsonNode;
3 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; 3 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;
4 import org.thingsboard.server.common.data.yunteng.dto.scene.SceneLinkageDTO; 4 import org.thingsboard.server.common.data.yunteng.dto.scene.SceneLinkageDTO;
  5 +import org.thingsboard.server.common.data.yunteng.dto.scene.SceneLinkageDeviceProfileDTO;
5 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; 6 import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum;
6 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 7 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
7 import org.thingsboard.server.dao.yunteng.entities.TkSceneLinkageEntity; 8 import org.thingsboard.server.dao.yunteng.entities.TkSceneLinkageEntity;
@@ -92,6 +93,14 @@ public interface SceneLinkageService extends BaseService<TkSceneLinkageEntity>{ @@ -92,6 +93,14 @@ public interface SceneLinkageService extends BaseService<TkSceneLinkageEntity>{
92 * 详情 93 * 详情
93 * @return 94 * @return
94 */ 95 */
95 - SceneLinkageDTO selectById(String id); 96 + SceneLinkageDTO selectById(String tenantId,String id);
96 97
  98 + /**
  99 + * 判断哪些产品被产品联动使用了,并返回被使用的产品ID列表
  100 + * @param tenantId 租户ID
  101 + * @param deviceProfileIds 检查的场景联动
  102 + * @param ruleChainIds 规则链ID列表
  103 + * @return
  104 + */
  105 + SceneLinkageDeviceProfileDTO checkDeviceProfileIdsUsedForSceneLinkage(String tenantId, List<String> deviceProfileIds,List<String> ruleChainIds);
97 } 106 }
@@ -23,8 +23,8 @@ public interface TkDeviceProfileService extends TbBaseService<TkDeviceProfileEnt @@ -23,8 +23,8 @@ public interface TkDeviceProfileService extends TbBaseService<TkDeviceProfileEnt
23 23
24 TkPageData<DeviceProfileDTO> page(Map<String, Object> queryMap, boolean isTenantAdmin); 24 TkPageData<DeviceProfileDTO> page(Map<String, Object> queryMap, boolean isTenantAdmin);
25 25
26 - List<DeviceProfileDTO> findDeviceProfile(  
27 - TenantId tenantId, String scriptId, DeviceTypeEnum deviceType, DeviceTransportType transportType,Boolean isSceneLinkage); 26 + List<DeviceProfileDTO> findDeviceProfile(TenantId tenantId, String scriptId, DeviceTypeEnum deviceType,
  27 + DeviceTransportType transportType,Boolean isSceneLinkage,String ruleChainId);
28 28
29 List<TkDeviceProfileEntity> findCustomerDeviceProfiles( 29 List<TkDeviceProfileEntity> findCustomerDeviceProfiles(
30 TenantId tenantId, CustomerId customerId, DeviceTypeEnum deviceType,DeviceTransportType transportType); 30 TenantId tenantId, CustomerId customerId, DeviceTypeEnum deviceType,DeviceTransportType transportType);
@@ -64,4 +64,19 @@ public interface TkDeviceProfileService extends TbBaseService<TkDeviceProfileEnt @@ -64,4 +64,19 @@ public interface TkDeviceProfileService extends TbBaseService<TkDeviceProfileEnt
64 64
65 DeviceProfile buildTbDeviceProfileFromDeviceProfileDTO(DeviceProfileDTO deviceProfileDTO, User user); 65 DeviceProfile buildTbDeviceProfileFromDeviceProfileDTO(DeviceProfileDTO deviceProfileDTO, User user);
66 66
  67 + /**
  68 + * 判断规则链ID被哪些产品使用了
  69 + * @param tenantId 租户ID
  70 + * @param ruleChainId 规则链ID
  71 + * @return 产品名称列表
  72 + */
  73 + List<String> checkRuleChainIdUsedByDeviceProfiles(String tenantId,UUID ruleChainId);
  74 +
  75 + /**
  76 + * 检查产品(设备配置)是否允许修改规则链
  77 + * @param deviceProfileIds 设备配置ID列表
  78 + * @param tenantId 租户ID
  79 + */
  80 + void checkDeviceProfilesCanChangeRuleChain(List<String> deviceProfileIds,TenantId tenantId);
  81 +
67 } 82 }
@@ -12,4 +12,6 @@ import java.util.List; @@ -12,4 +12,6 @@ import java.util.List;
12 */ 12 */
13 public interface TriggerService extends BaseService<TkTriggerEntity>{ 13 public interface TriggerService extends BaseService<TkTriggerEntity>{
14 List<TriggerDTO> getTrigger(String sceneId); 14 List<TriggerDTO> getTrigger(String sceneId);
  15 +
  16 + List<TriggerDTO> getTriggersByDeviceProfileIds(String tenantId, List<String> deviceProfileIds);
15 } 17 }
@@ -9,6 +9,11 @@ @@ -9,6 +9,11 @@
9 <result property="configuration" column="configuration" 9 <result property="configuration" column="configuration"
10 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> 10 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
11 <result property="tenantId" column="tenant_id"/> 11 <result property="tenantId" column="tenant_id"/>
  12 + <result property="ruleChainId" column="rule_chain_id"/>
  13 + <result property="ruleChainName" column="rule_chain_name"/>
  14 + <result property="datasourceType" column="datasource_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
  15 + <result property="datasourceContent" column="datasource_content"
  16 + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
12 <result property="status" column="status"/> 17 <result property="status" column="status"/>
13 <result property="nodeType" column="node_type"/> 18 <result property="nodeType" column="node_type"/>
14 <result property="createTime" column="create_time"/> 19 <result property="createTime" column="create_time"/>
@@ -17,6 +22,10 @@ @@ -17,6 +22,10 @@
17 <result property="updater" column="updater"/> 22 <result property="updater" column="updater"/>
18 <result property="remark" column="remark"/> 23 <result property="remark" column="remark"/>
19 </resultMap> 24 </resultMap>
  25 + <sql id="columns">
  26 + tcc.id,tcc.name,tcc.type,tcc.configuration,tcc.tenant_id,tcc.rule_chain_id,tcc.status,tcc.node_type,
  27 + tcc.datasource_type,tcc.datasource_content,tcc.create_time,tcc.update_time,tcc.creator,tcc.updater,tcc.remark
  28 + </sql>
20 <update id="updateConvertStatusByIds"> 29 <update id="updateConvertStatusByIds">
21 UPDATE tk_convert_config 30 UPDATE tk_convert_config
22 SET status =#{status} 31 SET status =#{status}
@@ -30,4 +39,27 @@ @@ -30,4 +39,27 @@
30 </if> 39 </if>
31 </where> 40 </where>
32 </update> 41 </update>
  42 + <select id="getConvertPage" resultMap="convertMap">
  43 + SELECT
  44 + <include refid="columns"/>,rc.name as rule_chain_name
  45 + FROM tk_convert_config tcc LEFT JOIN rule_chain rc ON tcc.rule_chain_id = rc.id ::TEXT
  46 + <where>
  47 + tcc.tenant_id = #{tenantId}
  48 + <if test="queryMap.name != null and queryMap.name != ''">
  49 + AND tcc.name LIKE concat('%',#{queryMap.name}::TEXT,'%')
  50 + </if>
  51 + <if test="queryMap.status != null">
  52 + AND tcc.status = #{queryMap.status}
  53 + </if>
  54 + <if test="queryMap.nodeType != null">
  55 + AND tcc.node_type = #{queryMap.nodeType}
  56 + </if>
  57 + <if test="queryMap.startTime != null and queryMap.endTime != null">
  58 + AND tcc.create_time &gt;= #{queryMap.startTime} AND tcc.create_time &lt; #{queryMap.endTime}
  59 + </if>
  60 + <if test="queryMap.ruleChainId != null and queryMap.ruleChainId != ''">
  61 + AND tcc.rule_chain_id = #{queryMap.ruleChainId}
  62 + </if>
  63 + </where>
  64 + </select>
33 </mapper> 65 </mapper>
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 <result property="commandType" column="command_type"/> 15 <result property="commandType" column="command_type"/>
16 <result property="thingsModelId" column="things_model_id"/> 16 <result property="thingsModelId" column="things_model_id"/>
17 <result property="sceneLinkageId" column="scene_linkage_id"/> 17 <result property="sceneLinkageId" column="scene_linkage_id"/>
  18 + <result property="sceneLinkageName" column="scene_linkage_name"/>
18 <result property="deviceProfileId" column="device_profile_id"/> 19 <result property="deviceProfileId" column="device_profile_id"/>
19 <result property="alarmProfileId" column="alarm_profile_id"/> 20 <result property="alarmProfileId" column="alarm_profile_id"/>
20 <result property="tenantId" column="tenant_id"/> 21 <result property="tenantId" column="tenant_id"/>
@@ -24,12 +25,21 @@ @@ -24,12 +25,21 @@
24 <result property="creator" column="creator"/> 25 <result property="creator" column="creator"/>
25 </resultMap> 26 </resultMap>
26 <sql id="columns"> 27 <sql id="columns">
27 - id,device_id,entity_type,device_type,do_context,out_target,call_type,scene_linkage_id,alarm_profile_id,  
28 - tenant_id,updater,update_time,create_time,creator,command_type,things_model_id,device_profile_id 28 + tda.id,tda.device_id,tda.entity_type,tda.device_type,tda.do_context,tda.out_target,tda.call_type,tda.scene_linkage_id,tda.alarm_profile_id,
  29 + tda.tenant_id,tda.updater,tda.update_time,tda.create_time,tda.creator,tda.command_type,tda.things_model_id,tda.device_profile_id
29 </sql> 30 </sql>
30 <select id="listBySceneId" resultMap="actionDTO"> 31 <select id="listBySceneId" resultMap="actionDTO">
31 SELECT 32 SELECT
32 <include refid="columns"/> 33 <include refid="columns"/>
33 - FROM tk_do_action WHERE scene_linkage_id = #{sceneId} 34 + FROM tk_do_action tda WHERE tda.scene_linkage_id = #{sceneId}
  35 + </select>
  36 + <select id="listBySceneLinkageIds" resultMap="actionDTO">
  37 + SELECT
  38 + <include refid="columns"/>,tsl.name as scene_linkage_name
  39 + FROM tk_do_action tda LEFT JOIN tk_scene_linkage tsl ON tsl.id = tda.scene_linkage_id
  40 + WHERE tda.tenant_id = #{tenantId} AND tda.scene_linkage_id IN
  41 + <foreach collection="sceneLinkageIds" item="sceneLinkageId" open="(" separator="," close=")">
  42 + #{sceneLinkageId}
  43 + </foreach>
34 </select> 44 </select>
35 </mapper> 45 </mapper>
@@ -12,6 +12,7 @@ @@ -12,6 +12,7 @@
12 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> 12 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
13 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> 13 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
14 <result property="sceneLinkageId" column="scene_linkage_id"/> 14 <result property="sceneLinkageId" column="scene_linkage_id"/>
  15 + <result property="sceneLinkageName" column="scene_linkage_name"/>
15 <result property="tenantId" column="tenant_id"/> 16 <result property="tenantId" column="tenant_id"/>
16 <result property="updater" column="updater"/> 17 <result property="updater" column="updater"/>
17 <result property="deviceProfileId" column="device_profile_id"/> 18 <result property="deviceProfileId" column="device_profile_id"/>
@@ -21,13 +22,24 @@ @@ -21,13 +22,24 @@
21 </resultMap> 22 </resultMap>
22 23
23 <sql id="columns"> 24 <sql id="columns">
24 - id,entity_id,entity_type,device_type,trigger_condition,trigger_type,scene_linkage_id,tenant_id  
25 - ,creator,updater,create_time,update_time,device_profile_id 25 + tdc.id,tdc.entity_id,tdc.entity_type,tdc.device_type,tdc.trigger_condition,tdc.trigger_type,tdc.scene_linkage_id,tdc.tenant_id
  26 + ,tdc.creator,tdc.updater,tdc.create_time,tdc.update_time,tdc.device_profile_id
26 </sql> 27 </sql>
27 28
28 <select id="listBySceneId" resultMap="conditionDTO"> 29 <select id="listBySceneId" resultMap="conditionDTO">
29 SELECT 30 SELECT
30 <include refid="columns"/> 31 <include refid="columns"/>
31 - FROM tk_do_condition WHERE scene_linkage_id = #{sceneId} 32 + FROM tk_do_condition tdc WHERE tdc.scene_linkage_id = #{sceneId}
  33 + </select>
  34 +
  35 + <select id="listByDeviceProfileIds" resultMap="conditionDTO">
  36 + SELECT
  37 + <include refid="columns"/>,tsl.name as scene_linkage_name
  38 + FROM tk_do_condition tdc
  39 + LEFT JOIN tk_scene_linkage tsl ON tdc.scene_linkage_id = tsl.id
  40 + WHERE tdc.tenant_id = #{tenantId} AND tdc.device_profile_id IN
  41 + <foreach collection="deviceProfileIds" item="deviceProfileId" open="(" separator="," close=")">
  42 + #{deviceProfileId}
  43 + </foreach>
32 </select> 44 </select>
33 </mapper> 45 </mapper>
@@ -6,6 +6,8 @@ @@ -6,6 +6,8 @@
6 <result property="id" column="id"/> 6 <result property="id" column="id"/>
7 <result property="name" column="name"/> 7 <result property="name" column="name"/>
8 <result property="organizationId" column="organization_id"/> 8 <result property="organizationId" column="organization_id"/>
  9 + <result property="ruleChainId" column="rule_chain_id"/>
  10 + <result property="ruleChainName" column="rule_chain_name"/>
9 <result property="status" column="status"/> 11 <result property="status" column="status"/>
10 <result property="description" column="description"/> 12 <result property="description" column="description"/>
11 <result property="tenantId" column="tenant_id"/> 13 <result property="tenantId" column="tenant_id"/>
@@ -20,14 +22,15 @@ @@ -20,14 +22,15 @@
20 22
21 </resultMap> 23 </resultMap>
22 <sql id="columns"> 24 <sql id="columns">
23 - s.id,s.name,s.organization_id,s.status,s.description,s.tenant_id,s.updater,s.update_time,s.create_time,s.creator 25 + s.id,s.name,s.organization_id,s.rule_chain_id,s.status,s.description,s.tenant_id,s.updater,s.update_time,s.create_time,s.creator
24 </sql> 26 </sql>
25 <select id="getScenePage" resultMap="sceneLinkageMap"> 27 <select id="getScenePage" resultMap="sceneLinkageMap">
26 SELECT 28 SELECT
27 - <include refid="columns"/>,su.real_name creator_name 29 + <include refid="columns"/>,su.real_name creator_name,rc.name as rule_chain_name
28 FROM tk_scene_linkage s 30 FROM tk_scene_linkage s
29 LEFT JOIN sys_user su ON su.id = s.creator 31 LEFT JOIN sys_user su ON su.id = s.creator
30 LEFT JOIN tk_organization io ON io.id = s.organization_id 32 LEFT JOIN tk_organization io ON io.id = s.organization_id
  33 + LEFT JOIN rule_chain rc ON rc.id::TEXT = s.rule_chain_id
31 <where> 34 <where>
32 <if test="queryMap.tenantId !=null and queryMap.tenantId !=''"> 35 <if test="queryMap.tenantId !=null and queryMap.tenantId !=''">
33 AND s.tenant_id = #{queryMap.tenantId} 36 AND s.tenant_id = #{queryMap.tenantId}
@@ -44,6 +47,9 @@ @@ -44,6 +47,9 @@
44 #{organizationId} 47 #{organizationId}
45 </foreach> 48 </foreach>
46 </if> 49 </if>
  50 + <if test="queryMap.ruleChainId != null and queryMap.ruleChainId != ''">
  51 + AND s.rule_chain_id = #{queryMap.ruleChainId}
  52 + </if>
47 <if test="queryMap.currentUser !=null"> 53 <if test="queryMap.currentUser !=null">
48 AND s.creator = #{queryMap.currentUser} 54 AND s.creator = #{queryMap.currentUser}
49 </if> 55 </if>
@@ -58,6 +64,7 @@ @@ -58,6 +64,7 @@
58 LEFT JOIN sys_user su ON su.id = s.creator 64 LEFT JOIN sys_user su ON su.id = s.creator
59 LEFT JOIN tk_organization io ON io.id = s.organization_id 65 LEFT JOIN tk_organization io ON io.id = s.organization_id
60 <where> 66 <where>
  67 + s.tenant_id = #{tenantId}
61 <if test="id !=null"> 68 <if test="id !=null">
62 AND s.id = #{id} 69 AND s.id = #{id}
63 </if> 70 </if>
@@ -107,6 +107,9 @@ @@ -107,6 +107,9 @@
107 <if test="scriptId !=null and scriptId !=''"> 107 <if test="scriptId !=null and scriptId !=''">
108 AND base.script_id = #{scriptId} 108 AND base.script_id = #{scriptId}
109 </if> 109 </if>
  110 + <if test="ruleChainId !=null and ruleChainId !=''">
  111 + AND base.default_rule_chain_id::TEXT = #{ruleChainId}
  112 + </if>
110 <if test="deviceType !=null"> 113 <if test="deviceType !=null">
111 AND base.device_type = #{deviceType} 114 AND base.device_type = #{deviceType}
112 </if> 115 </if>
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> 13 typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
14 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> 14 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
15 <result property="sceneLinkageId" column="scene_linkage_id"/> 15 <result property="sceneLinkageId" column="scene_linkage_id"/>
  16 + <result property="sceneLinkageName" column="scene_linkage_name"/>
16 <result property="tenantId" column="tenant_id"/> 17 <result property="tenantId" column="tenant_id"/>
17 <result property="updater" column="updater"/> 18 <result property="updater" column="updater"/>
18 <result property="updateTime" column="update_time"/> 19 <result property="updateTime" column="update_time"/>
@@ -21,13 +22,24 @@ @@ -21,13 +22,24 @@
21 </resultMap> 22 </resultMap>
22 23
23 <sql id="columns"> 24 <sql id="columns">
24 - id,entity_id,entity_type,device_type,trigger_condition,trigger_type,scene_linkage_id,tenant_id,creator  
25 - ,updater,create_time,update_time,device_profile_id 25 + tt.id,tt.entity_id,tt.entity_type,tt.device_type,tt.trigger_condition,tt.trigger_type,tt.scene_linkage_id,tt.tenant_id,tt.creator
  26 + ,tt.updater,tt.create_time,tt.update_time,tt.device_profile_id
26 </sql> 27 </sql>
27 28
28 <select id="listBySceneId" resultMap="triggerDTO"> 29 <select id="listBySceneId" resultMap="triggerDTO">
29 SELECT 30 SELECT
30 <include refid="columns"/> 31 <include refid="columns"/>
31 - FROM tk_trigger WHERE scene_linkage_id = #{sceneId} 32 + FROM tk_trigger tt WHERE tt.scene_linkage_id = #{sceneId}
  33 + </select>
  34 +
  35 + <select id="listByDeviceProfileIds" resultMap="triggerDTO">
  36 + SELECT
  37 + <include refid="columns"/>,tsl.name as scene_linkage_name
  38 + FROM tk_trigger tt
  39 + LEFT JOIN tk_scene_linkage tsl ON tt.scene_linkage_id = tsl.id
  40 + WHERE tt.tenant_id = #{tenantId} AND tt.device_profile_id IN
  41 + <foreach collection="deviceProfileIds" item="deviceProfileId" open="(" separator="," close=")">
  42 + #{deviceProfileId}
  43 + </foreach>
32 </select> 44 </select>
33 </mapper> 45 </mapper>