Commit 14852ef3d9d03a138b3681ec38552c4eaea5a29f

Authored by xp.Huang
2 parents f1ba25ba 30880e57

Merge branch '20220913' into 'master_dev'

refactor: 调整组织结构下所有组织的接口实现

See merge request yunteng/thingskit!231
1 1 package org.thingsboard.server.controller.yunteng;
2 2
  3 +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
  4 +
3 5 import com.fasterxml.jackson.databind.JsonNode;
4 6 import io.swagger.annotations.Api;
5 7 import io.swagger.annotations.ApiOperation;
6 8 import io.swagger.annotations.ApiParam;
  9 +import java.util.*;
  10 +import java.util.concurrent.ConcurrentMap;
7 11 import lombok.RequiredArgsConstructor;
8 12 import org.springframework.beans.factory.annotation.Autowired;
9 13 import org.springframework.beans.factory.annotation.Value;
... ... @@ -25,10 +29,10 @@ import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
25 29 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
26 30 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
27 31 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  32 +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
28 33 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
29 34 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigReqDTO;
30 35 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertReqDTO;
31   -import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
32 36 import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
33 37 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
34 38 import org.thingsboard.server.controller.BaseController;
... ... @@ -38,11 +42,6 @@ import org.thingsboard.server.dao.yunteng.service.TkRuleChainService;
38 42 import org.thingsboard.server.service.rule.TbRuleChainService;
39 43 import org.thingsboard.server.service.security.permission.Operation;
40 44
41   -import java.util.*;
42   -import java.util.concurrent.ConcurrentMap;
43   -
44   -import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
45   -
46 45 @RestController
47 46 @RequiredArgsConstructor
48 47 @RequestMapping("api/yt/convert")
... ... @@ -52,10 +51,13 @@ public class TkConvertDataToController extends BaseController {
52 51 private final TkRuleChainService tkRuleChainService;
53 52 private final ConvertConfigService convertConfigService;
54 53 private final SceneLinkageService sceneLinkageService;
  54 +
55 55 @Value("${actors.rule.chain.debug_mode_rate_limits_per_tenant.enabled}")
56 56 private boolean debugPerTenantEnabled;
  57 +
57 58 @Autowired(required = false)
58 59 private ActorSystemContext actorContext;
  60 +
59 61 @Autowired private TbRuleChainService tbRuleChainService;
60 62
61 63 @GetMapping(params = {PAGE_SIZE, PAGE})
... ... @@ -79,7 +81,7 @@ public class TkConvertDataToController extends BaseController {
79 81 queryMap.put("nodeType", nodeType);
80 82 queryMap.put("name", name);
81 83 queryMap.put("status", status);
82   - checkTimeAndPut(queryMap,startTime,endTime);
  84 + checkTimeAndPut(queryMap, startTime, endTime);
83 85 if (orderType != null) {
84 86 queryMap.put(ORDER_TYPE, orderType.name());
85 87 }
... ... @@ -90,7 +92,7 @@ public class TkConvertDataToController extends BaseController {
90 92 @ApiOperation("获取详情")
91 93 public ResponseEntity<ConvertConfigDTO> findConvertConfigDTOById(@PathVariable("id") String id)
92 94 throws ThingsboardException {
93   - if(StringUtils.isEmpty(id)){
  95 + if (StringUtils.isEmpty(id)) {
94 96 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
95 97 }
96 98 return ResponseEntity.ok(
... ... @@ -230,6 +232,7 @@ public class TkConvertDataToController extends BaseController {
230 232 Map<String, Map<String, String>> origConfig = new HashMap<>();
231 233 Map<String, String> fields = new HashMap<>();
232 234 fields.put("deviceProfileId", "deviceProfileId");
  235 + fields.put("tenantId", "tenantId");
233 236 origConfig.put("fieldsMapping", fields);
234 237 origNode.setConfiguration(JacksonUtil.valueToTree(origConfig));
235 238 ruleNodes.add(origNode);
... ... @@ -261,9 +264,12 @@ public class TkConvertDataToController extends BaseController {
261 264 ruleChainService.loadRuleChainMetaData(getTenantId(), ruleChain.getId());
262 265 // 3. SETUP CONNECTION AND ADD OR DELETE RULE NODE
263 266 if (status == FastIotConstants.MagicNumber.ZERO) {
264   - needSaveRuleNode = convertConfigService.deleteRuleNode(nodes, ruleChainMetaData, nodeType,getCurrentUser().getCurrentTenantId());
  267 + needSaveRuleNode =
  268 + convertConfigService.deleteRuleNode(
  269 + nodes, ruleChainMetaData, nodeType, getCurrentUser().getCurrentTenantId());
265 270 } else {
266   - convertConfigService.addRuleNode(nodes, ruleChainMetaData, nodeType,getCurrentUser().getCurrentTenantId());
  271 + convertConfigService.addRuleNode(
  272 + nodes, ruleChainMetaData, nodeType, getCurrentUser().getCurrentTenantId());
267 273 needSaveRuleNode = true;
268 274 }
269 275 // 4. SAVE METADATA
... ...
... ... @@ -445,6 +445,12 @@ caffeine:
445 445 taskCenterInfos:
446 446 timeToLiveInMinutes: "${CACHE_SPECS_TASK_CENTER_TTL:1440}"
447 447 maxSize: "${CACHE_SPECS_TASK_CENTER_MAX_SIZE:10000}"
  448 + organization:
  449 + timeToLiveInMinutes: "${CACHE_SPECS_ORG_TTL:1440}"
  450 + maxSize: "${CACHE_SPECS_ORG_MAX_SIZE:10000}"
  451 + sceneReact:
  452 + timeToLiveInMinutes: "${CACHE_SPECS_SCENE_TTL:1440}"
  453 + maxSize: "${CACHE_SPECS_SCENE_MAX_SIZE:10000}"
448 454 redis:
449 455 # standalone or cluster
450 456 connection:
... ... @@ -1217,4 +1223,4 @@ logging:
1217 1223 # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
1218 1224 frp:
1219 1225 server:
1220   - address: ${FRP_SERVER_ADDRESS:http://127.0.0.1}
\ No newline at end of file
  1226 + address: ${FRP_SERVER_ADDRESS:http://127.0.0.1}
... ...
... ... @@ -30,6 +30,8 @@ public interface FastIotConstants {
30 30 String TASK_CENTER_EXECUTE_TIME = "taskCenterExecuteTime";
31 31 String TASK_CENTER_DEVICE_EXECUTE_TIME = "taskCenterDeviceExecuteTime";
32 32 String TASK_IMMEDIATE_EXECUTE = "taskImmediateExecute";
  33 + String ORGANIZATION = "organization";
  34 + String SCENE_REACT = "sceneReact";
33 35 }
34 36
35 37 interface TBCacheConfig {
... ... @@ -175,6 +177,13 @@ public interface FastIotConstants {
175 177 /**RPC单项双向*/
176 178 public static String ONEWAY = "oneway";
177 179 }
  180 + class Scene{
  181 +
  182 + /**触发器*/
  183 + public static String CONDITION_TRIGGER = "trigger";
  184 + /**执行条件*/
  185 + public static String CONDITION_CONDITION = "condition";
  186 + }
178 187 class Alarm{
179 188
180 189 /**遥测指标标识符*/
... ...
... ... @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j;
11 11 import org.apache.commons.lang3.StringUtils;
12 12 import org.jetbrains.annotations.NotNull;
13 13 import org.jetbrains.annotations.Nullable;
  14 +import org.springframework.cache.annotation.Cacheable;
14 15 import org.springframework.stereotype.Service;
15 16 import org.springframework.transaction.annotation.Transactional;
16 17 import org.thingsboard.common.util.JacksonUtil;
... ... @@ -32,10 +33,7 @@ import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
32 33 import org.thingsboard.server.dao.device.DeviceProfileDao;
33 34 import org.thingsboard.server.dao.yunteng.entities.*;
34 35 import org.thingsboard.server.dao.yunteng.mapper.*;
35   -import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
36   -import org.thingsboard.server.dao.yunteng.service.ConvertConfigService;
37   -import org.thingsboard.server.dao.yunteng.service.ThingsModelService;
38   -import org.thingsboard.server.dao.yunteng.service.TkDeviceService;
  36 +import org.thingsboard.server.dao.yunteng.service.*;
39 37
40 38 import java.time.LocalDateTime;
41 39 import java.util.*;
... ... @@ -50,7 +48,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
50 48 private final DeviceProfileDao deviceProfileDao;
51 49 private final TkDeviceProfileMapper tkProfileMapper;
52 50
53   - private final OrganizationMapper tkOrganizationMapper;
  51 + private final TkOrganizationService organizationService;
54 52 private final SceneLinkageMapper sceneLinkageMapper;
55 53 private final TriggerMapper triggerMapper;
56 54 private final DoConditionMapper conditionMapper;
... ... @@ -133,8 +131,8 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
133 131 TenantId id = TenantId.fromUUID(UUID.fromString(deviceTenantId));
134 132 DeviceProfile deviceProfile =
135 133 deviceProfileDao.findById(id, UUID.fromString(deviceDTO.getProfileId()));
136   - TkOrganizationEntity organization =
137   - tkOrganizationMapper.selectById(deviceDTO.getOrganizationId());
  134 + OrganizationDTO organization =
  135 + organizationService.findOrganizationById(deviceTenantId,deviceDTO.getOrganizationId());
138 136 if (null == deviceProfile || null == organization) {
139 137 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
140 138 } else if (!organization.getTenantId().equals(deviceTenantId)) {
... ... @@ -274,7 +272,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
274 272 String organizationId,
275 273 String deviceLabel,
276 274 String deviceProfileId) {
277   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  275 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
278 276 if (orgIds.isEmpty()) {
279 277 throw new TkDataValidationException(ErrorMessage.ORGANIZATION_NOT_EXTIED.getMessage());
280 278 }
... ... @@ -294,7 +292,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
294 292 @Override
295 293 public List<DeviceDTO> findDevicesByTransportTypeAndOrganizationId(
296 294 String tenantId, String organizationId, DeviceTransportType transportType) {
297   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  295 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
298 296 if (orgIds.isEmpty()) {
299 297 throw new TkDataValidationException(ErrorMessage.ORGANIZATION_NOT_EXTIED.getMessage());
300 298 }
... ... @@ -380,7 +378,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
380 378 String convertConfigId =
381 379 Optional.ofNullable(queryMap.get("convertConfigId")).map(Object::toString).orElse(null);
382 380 if (!StringUtils.isEmpty(organizationId)) {
383   - List<String> queryOrganizationIds = organizationAllIds(tenantId, organizationId);
  381 + List<String> queryOrganizationIds = organizationService.organizationAllIds(tenantId, organizationId);
384 382 queryMap.put("organizationIds", queryOrganizationIds);
385 383 }
386 384 // 用于数据流转已选,待选过滤============开始
... ... @@ -415,28 +413,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
415 413 return new TkPageData<>(records, deviceIPage.getTotal());
416 414 }
417 415
418   - /**
419   - * 组织结构下的所有组织ID
420   - *
421   - * @param tenantId 租户ID
422   - * @param organizationId 组织ID
423   - */
424   - @NotNull
425   - private List<String> organizationAllIds(String tenantId, String organizationId) {
426   - List<String> organizationIds = new ArrayList<>();
427   - if (StringUtils.isEmpty(organizationId)) {
428   - return organizationIds;
429   - }
430   - if (!StringUtils.isEmpty(organizationId)) {
431   - organizationIds.add(organizationId);
432   - }
433   - // 查询该组织的所有子类
434   - List<OrganizationDTO> organizationDTOS =
435   - tkOrganizationMapper.findOrganizationTreeList(tenantId, organizationIds);
436   - List<String> queryOrganizationIds = new ArrayList<>();
437   - organizationDTOS.forEach(item -> queryOrganizationIds.add(item.getId()));
438   - return queryOrganizationIds;
439   - }
  416 +
440 417
441 418 @Override
442 419 public TkPageData<RelationDeviceDTO> pageRelation(Map<String, Object> queryMap) {
... ... @@ -555,14 +532,14 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
555 532 @Override
556 533 public List<SelectItemDTO> findMasterDevices(
557 534 String tenantId, String customerId, String organizationId, String deviceProfileId) {
558   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  535 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
559 536 return baseMapper.masterDevices(customerId, tenantId, orgIds, deviceProfileId);
560 537 }
561 538
562 539 @Override
563 540 public List<SelectItemDTO> findSlaveDevices(
564 541 String masterId, String tenantId, String customerId, String organizationId) {
565   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  542 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
566 543 return baseMapper.slaveDevices(customerId, tenantId, orgIds, masterId);
567 544 }
568 545
... ... @@ -574,7 +551,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
574 551 @Override
575 552 public List<String> findDeviceKeys(
576 553 String tenantId, String customerId, String organizationId, List<String> deviceIds) {
577   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  554 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
578 555 return baseMapper.findDeviceKeys(tenantId, customerId, orgIds, deviceIds);
579 556 }
580 557
... ... @@ -685,10 +662,10 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
685 662 }
686 663 return baseMapper.findDeviceInfo(tenantId, tbDeviceId);
687 664 }
688   -
  665 + @Cacheable(cacheNames = FastIotConstants.CacheConfigKey.SCENE_REACT, key = "{#tenantId, #organizationId, #projectId}")
689 666 @Override
690 667 public List<String> rpcDevices(String tenantId, String organizationId, String projectId) {
691   - List<String> orgIds = organizationAllIds(tenantId, organizationId);
  668 + List<String> orgIds = organizationService.organizationAllIds(tenantId, organizationId);
692 669
693 670 List<TkDeviceEntity> organizationDevices =
694 671 baseMapper.selectList(
... ...
... ... @@ -6,15 +6,22 @@ import com.google.common.collect.Lists;
6 6 import com.google.common.collect.Sets;
7 7 import lombok.RequiredArgsConstructor;
8 8 import org.apache.commons.lang3.StringUtils;
  9 +import org.jetbrains.annotations.NotNull;
  10 +import org.springframework.beans.factory.annotation.Autowired;
  11 +import org.springframework.cache.annotation.CacheEvict;
  12 +import org.springframework.cache.annotation.Cacheable;
  13 +import org.springframework.cache.annotation.Caching;
9 14 import org.springframework.stereotype.Service;
10 15 import org.springframework.transaction.annotation.Transactional;
11 16 import org.springframework.util.Assert;
  17 +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
12 18 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
13 19 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
14 20 import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
15 21 import org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO;
16 22 import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils;
17 23 import org.thingsboard.server.common.data.yunteng.utils.tree.TreeUtils;
  24 +import org.thingsboard.server.dao.cache.EntitiesCacheManager;
18 25 import org.thingsboard.server.dao.yunteng.entities.*;
19 26 import org.thingsboard.server.dao.yunteng.mapper.*;
20 27 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
... ... @@ -23,6 +30,8 @@ import org.thingsboard.server.dao.yunteng.service.TkOrganizationService;
23 30 import java.util.*;
24 31 import java.util.stream.Collectors;
25 32
  33 +import static org.thingsboard.server.common.data.CacheConstants.DEVICE_CACHE;
  34 +
26 35 @Service
27 36 @RequiredArgsConstructor
28 37 public class TkOrganizationServiceImpl extends AbstractBaseService<OrganizationMapper, TkOrganizationEntity>
... ... @@ -34,6 +43,9 @@ public class TkOrganizationServiceImpl extends AbstractBaseService<OrganizationM
34 43 private final SceneLinkageMapper sceneMapper;
35 44 private final AlarmContactMapper contactMapper;
36 45
  46 + @Caching(evict= {
  47 + @CacheEvict(cacheNames = FastIotConstants.CacheConfigKey.ORGANIZATION, key = "{#tenantId, #organizationDTO.id}")
  48 + })
37 49 @Override
38 50 @Transactional
39 51 public OrganizationDTO saveOrganization(
... ... @@ -148,7 +160,9 @@ public class TkOrganizationServiceImpl extends AbstractBaseService<OrganizationM
148 160 .lambda()
149 161 .in(TkUserOrganizationMappingEntity::getOrganizationId, organizationIds));
150 162 }
151   -
  163 + @Caching(evict= {
  164 + @CacheEvict(cacheNames = FastIotConstants.CacheConfigKey.ORGANIZATION, key = "{#tenantId, #organizationDTO.id}")
  165 + })
152 166 @Override
153 167 @Transactional
154 168 public OrganizationDTO updateOrganization(
... ... @@ -339,4 +353,30 @@ public class TkOrganizationServiceImpl extends AbstractBaseService<OrganizationM
339 353 }
340 354 return organization.getDTO(OrganizationDTO.class);
341 355 }
  356 +
  357 +
  358 + /**
  359 + * 组织结构下的所有组织ID
  360 + *
  361 + * @param tenantId 租户ID
  362 + * @param organizationId 组织ID
  363 + */
  364 + @Cacheable(cacheNames = FastIotConstants.CacheConfigKey.ORGANIZATION, key = "{#tenantId, #organizationId}")
  365 + @Override
  366 + public List<String> organizationAllIds(String tenantId, String organizationId) {
  367 + List<String> organizationIds = new ArrayList<>();
  368 + if (StringUtils.isEmpty(organizationId)) {
  369 + return organizationIds;
  370 + }
  371 + if (!StringUtils.isEmpty(organizationId)) {
  372 + organizationIds.add(organizationId);
  373 + }
  374 + // 查询该组织的所有子类
  375 + List<OrganizationDTO> organizationDTOS =
  376 + baseMapper.findOrganizationTreeList(tenantId, organizationIds);
  377 + List<String> queryOrganizationIds = new ArrayList<>();
  378 + organizationDTOS.forEach(item -> queryOrganizationIds.add(item.getId()));
  379 + return queryOrganizationIds;
  380 + }
  381 +
342 382 }
... ...
... ... @@ -21,4 +21,12 @@ public interface TkOrganizationService extends BaseService<TkOrganizationEntity>
21 21 void unBindUserToOrganization(Set<String> userIds);
22 22
23 23 OrganizationDTO findOrganizationById(String id,String tenantId);
  24 +
  25 + /**
  26 + * 组织结构下的所有组织ID
  27 + *
  28 + * @param tenantId 租户ID
  29 + * @param organizationId 组织ID
  30 + */
  31 + List<String> organizationAllIds(String tenantId, String organizationId);
24 32 }
... ...
... ... @@ -16,6 +16,7 @@ package org.thingsboard.rule.engine.yunteng.scene;
16 16 import com.fasterxml.jackson.databind.ObjectMapper;
17 17 import java.util.List;
18 18 import java.util.Map;
  19 +import java.util.Optional;
19 20 import java.util.concurrent.ConcurrentHashMap;
20 21 import lombok.extern.slf4j.Slf4j;
21 22 import org.thingsboard.rule.engine.api.*;
... ... @@ -58,6 +59,7 @@ public class TbSceneReactNode implements TbNode {
58 59 public void onMsg(TbContext ctx, TbMsg msg) {
59 60 String deviceId = msg.getOriginator().getId().toString();
60 61 String tbProfileId = msg.getMetaData().getValue("deviceProfileId");
  62 + String tenantId = msg.getMetaData().getValue("tenantId");
61 63 String projectId = config.getProfile().get(tbProfileId);
62 64 boolean deviceHas = config.getScenes().containsKey(deviceId);
63 65 boolean profileHas = config.getProject().containsKey(projectId);
... ... @@ -73,7 +75,7 @@ public class TbSceneReactNode implements TbNode {
73 75 ReactState react = getOrCreateReactState(ctx, config, t.getScenId());
74 76 if (react != null) {
75 77 try {
76   - react.process(ctx, msg,t.getRuleId(), deviceId);
  78 + react.process(ctx, msg, t.getRuleId(), deviceId);
77 79 } catch (Exception e) {
78 80 ctx.tellFailure(msg, e);
79 81 }
... ... @@ -85,14 +87,24 @@ public class TbSceneReactNode implements TbNode {
85 87 projectScence.stream()
86 88 .forEach(
87 89 t -> {
88   - ReactState react = getOrCreateReactState(ctx, config, t.getScenId());
89   - if (react != null) {
90   - try {
91   - react.process(ctx, msg,t.getRuleId(), deviceId);
92   - } catch (Exception e) {
93   - ctx.tellFailure(msg, e);
94   - }
95   - }
  90 + String scenId = t.getScenId();
  91 + List<String> orgDevices =
  92 + ctx.getTkDeviceService()
  93 + .rpcDevices(tenantId, config.getOrgs().get(scenId), projectId);
  94 + Optional.ofNullable(orgDevices)
  95 + .ifPresent(
  96 + f -> {
  97 + if (f.contains(deviceId)) {
  98 + ReactState react = getOrCreateReactState(ctx, config, scenId);
  99 + if (react != null) {
  100 + try {
  101 + react.process(ctx, msg, t.getRuleId(), deviceId);
  102 + } catch (Exception e) {
  103 + ctx.tellFailure(msg, e);
  104 + }
  105 + }
  106 + }
  107 + });
96 108 });
97 109 }
98 110 }
... ...
... ... @@ -13,13 +13,17 @@ public class TbSceneReactNodeConfig implements NodeConfiguration<TbSceneReactNod
13 13
14 14 /** 【TB设备配置ID,TK产品ID】产品信息 */
15 15 private Map<String, String> profile;
16   - /** 【TK产品ID,场景】哪些产品会触发场景联动 */
  16 +
  17 + /** 【TK产品ID,场景】哪些产品会触发场景联动,包含产品的每一个触发器 */
17 18 private Map<String, List<RuleFilterDTO>> project;
18   - /** 【TB设备ID,场景】哪些设备会触发场景联动 */
  19 +
  20 + /** 【TB设备ID,场景】哪些设备会触发场景联动,包含设备的每一个触发器 */
19 21 private Map<String, List<RuleFilterDTO>> scenes;
  22 +
20 23 /** 【TK场景ID,场景名称】场景联动信息 */
21 24 private Map<String, String> names;
22   - /** 【TK场景ID,组织ID】场景联动所属组织信息 */
  25 +
  26 + /** 【TK场景ID,场景联动的根组织ID】场景联动所属组织信息 */
23 27 private Map<String, String> orgs;
24 28
25 29 @Override
... ...