Commit 210b8854544706f28a27505cb12df764e6f912f4

Authored by xp.Huang
2 parents 3884911a 9b39f0b5

Merge branch '20200311' into 'master'

refactor: 组织可用设备接口优化

See merge request huang/thingsboard3.3.2!65
Showing 24 changed files with 441 additions and 193 deletions
... ... @@ -187,7 +187,7 @@ public class YtConvertDataToController extends BaseController {
187 187 String sceneId = convertReqDTO.getId();
188 188 String currentTenant = getCurrentUser().getCurrentTenantId();
189 189 Integer sceneStatus = convertReqDTO.getStatus();
190   - JsonNode configuration = sceneLinkageService.getRuleNodeConfig(sceneId,currentTenant,sceneStatus);
  190 + JsonNode configuration = sceneLinkageService.getRuleNodeConfig(sceneId,currentTenant,getCurrentUser().getCustomerId().getId().toString(),sceneStatus);
191 191 boolean noValue = configuration == null;
192 192 if (noValue && convertReqDTO.getStatus() == FastIotConstants.StateValue.DISABLE) {
193 193 status = FastIotConstants.StateValue.DISABLE;
... ...
... ... @@ -48,7 +48,7 @@ public class YtSceneLinkageController extends BaseController {
48 48 throws ThingsboardException {
49 49 SceneLinkageDTO newSceneLinkageDTO =
50 50 sceneLinkageService.saveSceneLinkage(
51   - sceneLinkageDTO, getCurrentUser().getCurrentTenantId(),getCurrentUser().isPtTenantAdmin(), getCurrentUser().getCurrentUserId());
  51 + sceneLinkageDTO, getCurrentUser().getCurrentTenantId(),getCurrentUser().getCurrentUserId(),getCurrentUser().getCustomerId().getId().toString());
52 52 return Optional.ofNullable(newSceneLinkageDTO)
53 53 .map(
54 54 dto -> {
... ... @@ -67,7 +67,7 @@ public class YtSceneLinkageController extends BaseController {
67 67 public void updateSceneLinkage(
68 68 @Validated(UpdateGroup.class) @RequestBody SceneLinkageDTO sceneLinkageDTO)
69 69 throws ThingsboardException {
70   - sceneLinkageService.updateSceneLinkage(sceneLinkageDTO, getCurrentUser().getCurrentTenantId(),getCurrentUser().isPtTenantAdmin(), getCurrentUser().getCurrentUserId());
  70 + sceneLinkageService.updateSceneLinkage(sceneLinkageDTO, getCurrentUser().getCurrentTenantId(), getCurrentUser().getCurrentUserId(),getCurrentUser().getCustomerId().getId().toString());
71 71 }
72 72
73 73 @ApiOperation("查询(分页列表)")
... ... @@ -109,9 +109,8 @@ public class YtSceneLinkageController extends BaseController {
109 109 List<DeviceDTO> dtoList =
110 110 sceneLinkageService.findDeviceList(
111 111 organizationId,
112   - getCurrentUser().isPtTenantAdmin(),
113 112 getCurrentUser().getCurrentTenantId(),
114   - getCurrentUser().getCurrentUserId());
  113 + getCurrentUser().getCustomerId().getId().toString());
115 114 Map<String, Object> map = new HashMap<>();
116 115 map.put("items", dtoList);
117 116 return ResponseEntity.ok(map);
... ...
... ... @@ -529,12 +529,12 @@ spring:
529 529 database-platform: "${SPRING_JPA_DATABASE_PLATFORM:org.hibernate.dialect.PostgreSQLDialect}"
530 530 datasource:
531 531 driverClassName: "${SPRING_DRIVER_CLASS_NAME:org.postgresql.Driver}"
532   - #url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://47.99.141.212:20638/thingsboard-3.3.2}"
533   - #username: "${SPRING_DATASOURCE_USERNAME:postgres}"
534   - #password: "${SPRING_DATASOURCE_PASSWORD:Vrr861!@waja}"
535   - url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://101.133.234.90:28776/thingsboard-3.3.2}"
  532 + url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://47.99.141.212:20638/thingsboard-3.3.2}"
536 533 username: "${SPRING_DATASOURCE_USERNAME:postgres}"
537   - password: "${SPRING_DATASOURCE_PASSWORD:Bua312!!iwcw}"
  534 + password: "${SPRING_DATASOURCE_PASSWORD:Vrr861!@waja}"
  535 +# url: "${SPRING_DATASOURCE_URL:jdbc:postgresql://101.133.234.90:28776/thingsboard-3.3.2}"
  536 +# username: "${SPRING_DATASOURCE_USERNAME:postgres}"
  537 +# password: "${SPRING_DATASOURCE_PASSWORD:Bua312!!iwcw}"
538 538 hikari:
539 539 maximumPoolSize: "${SPRING_DATASOURCE_MAXIMUM_POOL_SIZE:16}"
540 540
... ... @@ -1126,8 +1126,8 @@ file:
1126 1126 randomFileName: ${file.storage.randomFileName}
1127 1127 account:
1128 1128 info:
1129   - emailSuffix: thingskit.com
  1129 + emailSuffix: yunteng.com
1130 1130 defaultPassword: 123456
1131 1131 logging:
1132 1132 level:
1133   - org.thingsboard.server.dao.yunteng.mapper: error
  1133 + org.thingsboard.server.dao.yunteng.mapper: debug
... ...
... ... @@ -55,6 +55,7 @@ public enum ErrorMessage {
55 55 FILE_NOT_FOUND(400036,"文件未找到"),
56 56 STORE_FILE_FAILED(400037,"文件存储失败"),
57 57 NOT_BELONG_CURRENT_TENANT(400038,"不属于当前租户"),
  58 + DEVICE_LOSED(400039,"设备相关参数丢失"),
58 59 HAVE_NO_PERMISSION(500002,"没有修改权限");
59 60 private final int code;
60 61 private String message;
... ...
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.databind.JsonNode;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import org.thingsboard.server.common.data.alarm.AlarmSeverity;
  8 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
  9 +import org.thingsboard.server.common.data.yunteng.enums.ActionTypeEnum;
  10 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * @Description 场景联动动作告警通知
  16 + * @Author cxy
  17 + * @Date 2021/11/24 17:32
  18 + */
  19 +@Data
  20 +public class ActionAlarmDTO extends TenantDTO{
  21 +
  22 +
  23 + private List<ActionTypeEnum> noticeType;
  24 +
  25 + /**告警联系人*/
  26 + private List<String> noticeUser;
  27 +
  28 + private AlarmSeverity alarmLevel;
  29 +
  30 +
  31 + private AlarmRule clearRule;
  32 +
  33 +}
... ...
... ... @@ -5,25 +5,32 @@ import io.swagger.annotations.ApiModelProperty;
5 5 import lombok.Data;
6 6 import lombok.EqualsAndHashCode;
7 7 import org.thingsboard.server.common.data.yunteng.enums.ActionTypeEnum;
  8 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
8 9
9 10 import java.util.List;
10 11
11   -/** @Description 场景联动执行动作数据传输表 @Author cxy @Date 2021/11/24 17:32 */
  12 +/**
  13 + * @Description 场景联动执行动作数据传输表
  14 + * @Author cxy
  15 + * @Date 2021/11/24 17:32
  16 + */
12 17 @Data
13 18 @EqualsAndHashCode(callSuper = true)
14   -public class DoActionDTO extends TenantDTO {
  19 +public class DoActionDTO extends TenantDTO{
15 20
16   - @ApiModelProperty(value = "所属设备id")
17   - private String deviceId;
  21 + @ApiModelProperty(value = "所属设备id")
  22 + private List<String> deviceId;
  23 + private ScopeEnum entityType;
18 24
19   - @ApiModelProperty(value = "场景联动内容")
20   - private JsonNode doContext;
  25 +
  26 + @ApiModelProperty(value = "场景联动内容")
  27 + private JsonNode doContext;
21 28
22 29 @ApiModelProperty(value = "输出目标:设备,告警,其他")
23 30 private ActionTypeEnum outTarget;
24 31
25   - @ApiModelProperty(value = "场景联动id")
26   - private String sceneLinkageId;
  32 + @ApiModelProperty(value = "场景联动id")
  33 + private String sceneLinkageId;
27 34
28 35 @ApiModelProperty(value = "输出目标为告警才进行配置")
29 36 private String alarmProfileId;
... ...
... ... @@ -4,8 +4,12 @@ import io.swagger.annotations.ApiModelProperty;
4 4 import lombok.Data;
5 5 import lombok.EqualsAndHashCode;
6 6 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
  7 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
  8 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
7 9 import org.thingsboard.server.common.data.yunteng.enums.TriggerTypeEnum;
8 10
  11 +import java.util.List;
  12 +
9 13 /**
10 14 * @Description 场景联动执行条件数据传输表
11 15 * @Author cxy
... ... @@ -18,11 +22,13 @@ public class DoConditionDTO extends TenantDTO{
18 22 @ApiModelProperty(value = "触发器类型")
19 23 private TriggerTypeEnum triggerType;
20 24
  25 +
21 26 @ApiModelProperty(value = "触发器关联实体")
22   - private String entityId;
  27 + private ScopeEnum entityType;
  28 + private List<String> entityId;
23 29
24 30 @ApiModelProperty(value = "触发条件")
25   - private AlarmCondition triggerCondition;
  31 + private AlarmRule triggerCondition;
26 32
27 33 @ApiModelProperty(value = "场景联动id")
28 34 private String sceneLinkageId;
... ...
... ... @@ -4,8 +4,13 @@ import io.swagger.annotations.ApiModelProperty;
4 4 import lombok.Data;
5 5 import lombok.EqualsAndHashCode;
6 6 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
  7 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
  8 +import org.thingsboard.server.common.data.device.profile.AlarmSchedule;
  9 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
7 10 import org.thingsboard.server.common.data.yunteng.enums.TriggerTypeEnum;
8 11
  12 +import java.util.List;
  13 +
9 14 /**
10 15 * @Description 场景联动触发器数据传输表
11 16 * @Author cxy
... ... @@ -19,10 +24,13 @@ public class TriggerDTO extends TenantDTO{
19 24 private TriggerTypeEnum triggerType;
20 25
21 26 @ApiModelProperty(value = "触发器关联实体,例如:设备ID、场景联动ID、定时任务CRON表达式")
22   - private String entityId;
  27 + private ScopeEnum entityType;
  28 + private List<String> entityId;
23 29
24 30 @ApiModelProperty(value = "触发条件")
25   - private AlarmCondition triggerCondition;
  31 + private AlarmRule triggerCondition;
  32 +
  33 +
26 34
27 35 @ApiModelProperty(value = "场景联动id")
28 36 private String sceneLinkageId;
... ...
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/** 取值范围枚举值 */
  4 +public enum ScopeEnum {
  5 + ALL,
  6 + PART
  7 +}
... ...
... ... @@ -3,31 +3,47 @@ package org.thingsboard.server.dao.yunteng.entities;
3 3 import com.baomidou.mybatisplus.annotation.TableField;
4 4 import com.baomidou.mybatisplus.annotation.TableName;
5 5 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
  6 +import com.fasterxml.jackson.annotation.JsonIgnore;
6 7 import com.fasterxml.jackson.databind.JsonNode;
7 8 import lombok.Data;
8 9 import lombok.EqualsAndHashCode;
9 10 import org.apache.ibatis.type.EnumTypeHandler;
10 11 import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
11 12 import org.thingsboard.server.common.data.yunteng.enums.ActionTypeEnum;
  13 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
  14 +import org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler;
12 15
13   -/** @Description 执行动作 @Author cxy @Date 2021/11/24 17:24 */
  16 +import java.util.Arrays;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * @Description 执行动作 @Author cxy @Date 2021/11/24 17:24
  21 + */
14 22 @Data
15 23 @TableName(value = ModelConstants.Table.IOTFS_DO_ACTION_TABLE_NAME, autoResultMap = true)
16 24 @EqualsAndHashCode(callSuper = true)
17 25 public class DoAction extends TenantBaseEntity {
18 26
19   - private static final long serialVersionUID = -5459834451418047957L;
  27 + private static final long serialVersionUID = -5459834451418047957L;
  28 +
20 29
21   - private String deviceId;
  30 + @TableField(typeHandler = ListStringTypeHandler.class)
  31 + private List<String> deviceId;
22 32
23   - @TableField(typeHandler = EnumTypeHandler.class)
24   - private ActionTypeEnum outTarget;
25   - /** 场景联动内容 */
26   - @TableField(typeHandler = JacksonTypeHandler.class)
27   - private JsonNode doContext;
  33 + @TableField(typeHandler = EnumTypeHandler.class)
  34 + private ScopeEnum entityType;
  35 + @TableField(typeHandler = EnumTypeHandler.class)
  36 + private ActionTypeEnum outTarget;
  37 + /**
  38 + * 场景联动内容
  39 + */
  40 + @TableField(typeHandler = JacksonTypeHandler.class)
  41 + private JsonNode doContext;
28 42
29   - /** 场景联动id */
30   - private String sceneLinkageId;
  43 + /**
  44 + * 场景联动id
  45 + */
  46 + private String sceneLinkageId;
31 47
32   - private String alarmProfileId;
  48 + private String alarmProfileId;
33 49 }
... ...
... ... @@ -7,20 +7,36 @@ import lombok.Data;
7 7 import lombok.EqualsAndHashCode;
8 8 import org.apache.ibatis.type.EnumTypeHandler;
9 9 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
  10 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
10 11 import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
  12 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
11 13 import org.thingsboard.server.common.data.yunteng.enums.TriggerTypeEnum;
  14 +import org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler;
12 15
13   -/** @Description 执行条件实体表 @Author cxy @Date 2021/11/24 17:16 */
  16 +import java.util.Arrays;
  17 +import java.util.List;
  18 +
  19 +/**
  20 + * @Description 执行条件实体表 @Author cxy @Date 2021/11/24 17:16
  21 + */
14 22 @Data
15   -@TableName(value = ModelConstants.Table.IOTFS_DO_CONDITION_TABLE_NAME,autoResultMap=true)
  23 +@TableName(value = ModelConstants.Table.IOTFS_DO_CONDITION_TABLE_NAME, autoResultMap = true)
16 24 @EqualsAndHashCode(callSuper = true)
17 25 public class DoCondition extends TenantBaseEntity {
18   - private static final long serialVersionUID = 2827674377416477646L;
19   - /** 设备 */
20   - private String entityId;
21   - @TableField(typeHandler = EnumTypeHandler.class)
22   - private TriggerTypeEnum triggerType;
23   - @TableField(typeHandler = JacksonTypeHandler.class)
24   - private AlarmCondition triggerCondition;
25   - private String sceneLinkageId;
  26 + private static final long serialVersionUID = 2827674377416477646L;
  27 + /**
  28 + * 设备
  29 + */
  30 + @TableField(typeHandler = ListStringTypeHandler.class)
  31 + private List<String> entityId;
  32 +
  33 + @TableField(typeHandler = EnumTypeHandler.class)
  34 + private ScopeEnum entityType;
  35 + @TableField(typeHandler = EnumTypeHandler.class)
  36 + private TriggerTypeEnum triggerType;
  37 + @TableField(typeHandler = JacksonTypeHandler.class)
  38 + private AlarmRule triggerCondition;
  39 + private String sceneLinkageId;
  40 +
  41 +
26 42 }
... ...
1 1 package org.thingsboard.server.dao.yunteng.entities;
  2 +
2 3 import com.baomidou.mybatisplus.annotation.TableField;
3 4 import com.baomidou.mybatisplus.annotation.TableName;
4 5 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
... ... @@ -6,21 +7,37 @@ import lombok.Data;
6 7 import lombok.EqualsAndHashCode;
7 8 import org.apache.ibatis.type.EnumTypeHandler;
8 9 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
  10 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
9 11 import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
  12 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
10 13 import org.thingsboard.server.common.data.yunteng.enums.TriggerTypeEnum;
  14 +import org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler;
  15 +
  16 +import java.util.Arrays;
  17 +import java.util.List;
11 18
12   -/** @Description 触发器实体表 @Author cxy @Date 2021/11/24 17:06 */
  19 +/**
  20 + * @Description 触发器实体表 @Author cxy @Date 2021/11/24 17:06
  21 + */
13 22 @Data
14   -@TableName(value = ModelConstants.Table.IOTFS_TRIGGER_TABLE_NAME,autoResultMap=true)
  23 +@TableName(value = ModelConstants.Table.IOTFS_TRIGGER_TABLE_NAME, autoResultMap = true)
15 24 @EqualsAndHashCode(callSuper = true)
16 25 public class Trigger extends TenantBaseEntity {
17 26
18   - private static final long serialVersionUID = -1847061176808850967L;
19   - /** 设备 */
20   - private String entityId;
21   - @TableField(typeHandler = EnumTypeHandler.class)
22   - private TriggerTypeEnum triggerType;
23   - @TableField(typeHandler = JacksonTypeHandler.class)
24   - private AlarmCondition triggerCondition;
25   - private String sceneLinkageId;
  27 + private static final long serialVersionUID = -1847061176808850967L;
  28 + /**
  29 + * 设备
  30 + */
  31 + @TableField(typeHandler = ListStringTypeHandler.class)
  32 + private List<String> entityId;
  33 +
  34 + @TableField(typeHandler = EnumTypeHandler.class)
  35 + private ScopeEnum entityType;
  36 + @TableField(typeHandler = EnumTypeHandler.class)
  37 + private TriggerTypeEnum triggerType;
  38 + @TableField(typeHandler = JacksonTypeHandler.class)
  39 + private AlarmRule triggerCondition;
  40 + private String sceneLinkageId;
  41 +
  42 +
26 43 }
... ...
... ... @@ -11,11 +11,13 @@ import lombok.RequiredArgsConstructor;
11 11 import org.apache.commons.lang3.StringUtils;
12 12 import org.springframework.stereotype.Service;
13 13 import org.springframework.transaction.annotation.Transactional;
  14 +import org.thingsboard.server.common.data.id.EntityId;
14 15 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
15 16 import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException;
16 17 import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
17 18 import org.thingsboard.server.common.data.yunteng.dto.*;
18 19 import org.thingsboard.server.common.data.yunteng.enums.ActionTypeEnum;
  20 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
19 21 import org.thingsboard.server.common.data.yunteng.enums.TriggerTypeEnum;
20 22 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;
21 23 import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils;
... ... @@ -47,7 +49,6 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
47 49 private final DoConditionService doConditionService;
48 50 private final DoActionService doActionService;
49 51 private final UserMapper userMapper;
50   - private final UserOrganizationMappingService userOrganizationMappingService;
51 52
52 53 /**
53 54 * 增加场景联动,触发器可以多个,执行条件可以多个,执行动作可以多个
... ... @@ -57,7 +58,7 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
57 58 */
58 59 @Override
59 60 @Transactional
60   - public SceneLinkageDTO saveSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId,boolean tenantAdmin,String currentUserId) {
  61 + public SceneLinkageDTO saveSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId, String currentUserId, String customerId) {
61 62 sceneLinkageDTO.setTenantId(tenantId);
62 63 // 第一步保存场景,获取场景ID
63 64 // 场景对象
... ... @@ -70,7 +71,7 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
70 71 }
71 72
72 73 String organizationId = sceneLinkage.getOrganizationId();
73   - List<DeviceDTO> organizationDevices = findDeviceList(organizationId,tenantAdmin,tenantId,currentUserId);
  74 + List<DeviceDTO> organizationDevices = findDeviceList(organizationId, tenantId, customerId);
74 75
75 76 List<String> tbDeviceIds = new ArrayList<>();
76 77 for (DeviceDTO item : organizationDevices) {
... ... @@ -92,15 +93,15 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
92 93 */
93 94 @Override
94 95 @Transactional
95   - public void deleteSceneLinkage(Set<String> ids, String tenantId,String currentUserId) {
  96 + public void deleteSceneLinkage(Set<String> ids, String tenantId, String currentUserId) {
96 97 LambdaQueryWrapper<SceneLinkage> Wrapper =
97 98 new QueryWrapper<SceneLinkage>()
98 99 .lambda()
99 100 .eq(SceneLinkage::getTenantId, tenantId)
100   - .eq(SceneLinkage::getCreator,currentUserId)
  101 + .eq(SceneLinkage::getCreator, currentUserId)
101 102 .in(SceneLinkage::getId, ids);
102 103 int result = sceneLinkageMapper.delete(Wrapper);
103   - if(result != ids.size()){
  104 + if (result != ids.size()) {
104 105 throw new YtDataValidationException("存在非当前用户创建的场景联动");
105 106 }
106 107 // 删除场景,一并删除数据库触发器,执行条件,执行动作的数据
... ... @@ -126,7 +127,7 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
126 127 */
127 128 @Override
128 129 @Transactional
129   - public SceneLinkageDTO updateSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId,boolean tenantAdmin ,String currentUserId) {
  130 + public SceneLinkageDTO updateSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId, String currentUserId, String customerId) {
130 131 // 获取场景
131 132 SceneLinkage sceneLinkage = baseMapper.selectById(sceneLinkageDTO.getId());
132 133 if (sceneLinkage == null) {
... ... @@ -136,7 +137,7 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
136 137 throw new YtDataValidationException("你不是此场景的创建者");
137 138 }
138 139 String organizationId = sceneLinkage.getOrganizationId();
139   - List<DeviceDTO> organizationDevices = findDeviceList(organizationId,tenantAdmin,tenantId,currentUserId);
  140 + List<DeviceDTO> organizationDevices = findDeviceList(organizationId, tenantId, customerId);
140 141
141 142 List<String> tbDeviceIds = new ArrayList<>();
142 143 for (DeviceDTO item : organizationDevices) {
... ... @@ -163,13 +164,23 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
163 164 List<TriggerDTO> triggerDTOS = sceneLinkage.getTriggers();
164 165 if (triggerDTOS != null && !triggerDTOS.isEmpty()) {
165 166 for (TriggerDTO triggerDTO : triggerDTOS) {
166   - String deviceId = triggerDTO.getEntityId();
167 167 if (!TriggerTypeEnum.DEVICE_TRIGGER.equals(triggerDTO.getTriggerType())) {
168 168 continue;
169 169 }
170   - if (!tbDeviceIds.contains(deviceId)) {
171   - throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_TRIGGER.getMessage());
  170 + List<String> deviceIds = triggerDTO.getEntityId();
  171 + if (ScopeEnum.PART.equals(triggerDTO.getEntityType())) {
  172 + if (deviceIds == null || deviceIds.isEmpty()) {
  173 + throw new YtDataValidationException(ErrorMessage.DEVICE_LOSED.getMessage());
  174 + } else {
  175 + for (String item : deviceIds) {
  176 + if (!tbDeviceIds.contains(item)) {
  177 + throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_TRIGGER.getMessage());
  178 + }
  179 + }
  180 + }
172 181 }
  182 +
  183 +
173 184 }
174 185 } else {
175 186 return;
... ... @@ -203,13 +214,21 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
203 214 private void updateDoAction(SceneLinkageDTO sceneLinkageDTO, List<String> tbDeviceIds) {
204 215 List<DoActionDTO> actionDTOS = sceneLinkageDTO.getDoActions();
205 216 if (actionDTOS != null && !actionDTOS.isEmpty()) {
206   - for (DoActionDTO item : actionDTOS) {
207   - String deviceId = item.getDeviceId();
208   - if (!ActionTypeEnum.DEVICE_OUT.equals(item.getOutTarget())) {
  217 + for (DoActionDTO action : actionDTOS) {
  218 + if (!ActionTypeEnum.DEVICE_OUT.equals(action.getOutTarget())) {
209 219 continue;
210 220 }
211   - if (!tbDeviceIds.contains(deviceId)) {
212   - throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_ACTION.getMessage());
  221 + List<String> deviceIds = action.getDeviceId();
  222 + if (ScopeEnum.PART.equals(action.getEntityType())) {
  223 + if (deviceIds == null || deviceIds.isEmpty()) {
  224 + throw new YtDataValidationException(ErrorMessage.DEVICE_LOSED.getMessage());
  225 + } else {
  226 + for (String item : deviceIds) {
  227 + if (!tbDeviceIds.contains(item)) {
  228 + throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_ACTION.getMessage());
  229 + }
  230 + }
  231 + }
213 232 }
214 233 }
215 234 }
... ... @@ -225,10 +244,12 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
225 244 .map(doActionDTO -> {
226 245 doActionDTO.setTenantId(sceneLinkageDTO.getTenantId());
227 246 doActionDTO.setSceneLinkageId(sceneLinkageDTO.getId());
228   - ObjectNode doContext = JacksonUtil.newObjectNode();
229   - doContext.put("method","methodThingskit");
230   - doContext.put("params",doActionDTO.getDoContext());
231   - doActionDTO.setDoContext(doContext);
  247 + if (ActionTypeEnum.DEVICE_OUT.equals(doActionDTO.getOutTarget())) {
  248 + ObjectNode doContext = JacksonUtil.newObjectNode();
  249 + doContext.put("method", "methodThingskit");
  250 + doContext.put("params", doActionDTO.getDoContext());
  251 + doActionDTO.setDoContext(doContext);
  252 + }
232 253 return doActionDTO.getEntity(DoAction.class);
233 254 })
234 255 .collect(Collectors.toList());
... ... @@ -246,13 +267,21 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
246 267 private void updateDoCondition(SceneLinkageDTO sceneLinkageDTO, List<String> tbDeviceIds) {
247 268 List<DoConditionDTO> conditionDTOS = sceneLinkageDTO.getDoConditions();
248 269 if (conditionDTOS != null && !conditionDTOS.isEmpty()) {
249   - for (DoConditionDTO item : conditionDTOS) {
250   - String deviceId = item.getEntityId();
251   - if (!TriggerTypeEnum.DEVICE_TRIGGER.equals(item.getTriggerType())) {
  270 + for (DoConditionDTO condition : conditionDTOS) {
  271 + if (!TriggerTypeEnum.DEVICE_TRIGGER.equals(condition.getTriggerType())) {
252 272 continue;
253 273 }
254   - if (!tbDeviceIds.contains(deviceId)) {
255   - throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_CONDITION.getMessage());
  274 + List<String> deviceIds = condition.getEntityId();
  275 + if (ScopeEnum.PART.equals(condition.getEntityType())) {
  276 + if (deviceIds == null || deviceIds.isEmpty()) {
  277 + throw new YtDataValidationException(ErrorMessage.DEVICE_LOSED.getMessage());
  278 + } else {
  279 + for (String item : deviceIds) {
  280 + if (!tbDeviceIds.contains(item)) {
  281 + throw new YtDataValidationException(ErrorMessage.ORGANIZATION_DEVICE_NOT_MATCHED_IN_ACTION.getMessage());
  282 + }
  283 + }
  284 + }
256 285 }
257 286 }
258 287 }
... ... @@ -340,63 +369,53 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
340 369
341 370 /**
342 371 * @param organizationId 组织ID
343   - * @param isTenantAdmin true租户管理员 false客户
344 372 * @param tenantId 租户ID
345   - * @param currentUserId 当前用户ID
  373 + * @param customerId 客户ID
346 374 * @return 设备集合
347 375 */
348 376 @Override
349 377 public List<DeviceDTO> findDeviceList(
350   - String organizationId, boolean isTenantAdmin, String tenantId, String currentUserId) {
351   - List<String> organizationIds = new ArrayList<>();
352   - organizationIds.add(organizationId);
  378 + String organizationId, String tenantId, String customerId) {
  379 + List<String> organizationFilter = new ArrayList<>();
  380 + organizationFilter.add(organizationId);
353 381 // 查询该组织的所有子类
354   - List<String> ids =
355   - organizationMapper.findOrganizationTreeList(tenantId, organizationIds).stream()
  382 + List<String> orgIds =
  383 + organizationMapper.findOrganizationTreeList(tenantId, organizationFilter).stream()
356 384 .map(organization -> organization.getId())
357 385 .collect(Collectors.toList());
358 386 // 拿到当前组织ids所包含的设备集合
359   - if(ids.isEmpty()){
360   - throw new YtDataValidationException(ErrorMessage.ORGANIZATION_NOT_EXTIED.getMessage());
  387 + if (orgIds.isEmpty()) {
  388 + throw new YtDataValidationException(ErrorMessage.ORGANIZATION_NOT_EXTIED.getMessage());
361 389 }
362   - List<YtDevice> deviceList =
  390 + List<YtDevice> orgDevices =
363 391 deviceMapper.selectList(
364   - new QueryWrapper<YtDevice>().lambda().in(YtDevice::getOrganizationId, ids));
365   - List<DeviceDTO> deviceDTOList =
366   - deviceList.stream()
367   - .map(device -> device.getDTO(DeviceDTO.class))
368   - .collect(Collectors.toList());
  392 + new QueryWrapper<YtDevice>().lambda().in(YtDevice::getOrganizationId, orgIds));
369 393
370   - List<DeviceDTO> result = new ArrayList<>();
371   - if (!isTenantAdmin) {
372   - // 查找分配给客户的设备
373   - List<String> list =
374   - deviceMapper.findDeviceIdsByCustomerId(userMapper.findUserCustomerIdById(currentUserId));
375   - list.forEach(
376   - id -> {
377   - for (DeviceDTO dto : deviceDTOList) {
378   - if (dto.getTbDeviceId().equals(id)) {
379   - result.add(dto);
380   - break;
381   - }
382   - }
383   - });
384   - } else {
385   - return deviceDTOList;
  394 +
  395 + List<String> customerDevices = deviceMapper.findDeviceIdsByCustomerId(customerId);
  396 + if (customerDevices == null || customerDevices.isEmpty()) {
  397 + return null;
386 398 }
  399 + List<DeviceDTO> result = orgDevices.stream()
  400 + .filter(f -> customerDevices.contains(f.getTbDeviceId()))
  401 + .map(device -> device.getDTO(DeviceDTO.class))
  402 + .collect(Collectors.toList());
  403 +
  404 +
387 405 return result;
388 406 }
389 407
390 408 /**
391 409 * 场景联动节点配置信息
392 410 *
393   - * @param sceneId 场景联动主键
394   - * @param tenantId 租户主键
395   - * @param state 是否禁用场景联动,true标识禁用,false标识启用。
  411 + * @param currentSceneId 场景联动主键
  412 + * @param tenantId 租户主键
  413 + * @param customerId 客户主键
  414 + * @param state 是否禁用场景联动,true标识禁用,false标识启用。
396 415 * @return
397 416 */
398 417 @Override
399   - public JsonNode getRuleNodeConfig(String sceneId, String tenantId, Integer state) {
  418 + public JsonNode getRuleNodeConfig(String currentSceneId, String tenantId, String customerId, Integer state) {
400 419 String ruleTyp = "org.thingsboard.rule.engine.filter.TbSceneReactNode";
401 420 List<SceneLinkage> runningScenes = baseMapper.selectList(
402 421 new QueryWrapper<SceneLinkage>()
... ... @@ -405,18 +424,28 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
405 424 .eq(SceneLinkage::getStatus, FastIotConstants.StateValue.ENABLE)
406 425 );
407 426 Set<String> enableIds = new HashSet<>();
408   - enableIds.add(sceneId);
409 427 for (SceneLinkage item : runningScenes) {
410 428 enableIds.add(item.getId());
411 429 }
  430 + enableIds.add(currentSceneId);
412 431 if (state == FastIotConstants.StateValue.DISABLE) {
413   - enableIds.remove(sceneId);
  432 + enableIds.remove(currentSceneId);
414 433 }
415 434
416   - if(enableIds.size() <= 0){
  435 + if (enableIds.size() <= 0) {
417 436 return null;
418 437 }
419   - List<Trigger> triggers = triggerMapper.selectList(
  438 +
  439 + List<DeviceDTO> organizationDevices = findDeviceList(currentSceneId, tenantId, customerId);
  440 + List<String> allDevices = new ArrayList<>();
  441 + for (DeviceDTO item : organizationDevices) {
  442 + allDevices.add(item.getTbDeviceId());
  443 + }
  444 +
  445 +
  446 + Map<String, List<String>> matchedDevices = new HashMap<>();
  447 +
  448 + List<Trigger> triggers = triggerMapper.selectList(
420 449 new QueryWrapper<Trigger>()
421 450 .lambda()
422 451 .eq(Trigger::getTenantId, tenantId)
... ... @@ -424,31 +453,66 @@ public class SceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageMap
424 453 .in(Trigger::getSceneLinkageId, enableIds)
425 454 );
426 455
427   - Map<String, List<String>> devices = new HashMap<>();
428   - for (Trigger item : triggers) {
429   - String deviceId = item.getEntityId();
430   - List<String> scenes = devices.computeIfAbsent(deviceId, k -> new ArrayList<String>());
431   - String triggerScenId = item.getSceneLinkageId();
432   - if (!scenes.contains(triggerScenId)) {
433   - scenes.add(triggerScenId);
434   - }
435   - if (scenes.isEmpty()) {
436   - devices.remove(deviceId);
437   - } else {
438   - devices.put(deviceId, scenes);
  456 +
  457 + triggers.forEach(trigger ->{
  458 + String scenId = trigger.getSceneLinkageId();
  459 + List<String> devices = trigger.getEntityId();
  460 + if(ScopeEnum.ALL.equals(trigger)){
  461 + trigger.setEntityId(allDevices);
  462 + triggerMapper.updateById(trigger);
  463 + devices = allDevices;
439 464 }
440   - }
441   - if (devices.isEmpty()) {
  465 + deviceSceneMap(matchedDevices,devices , scenId);
  466 + });
  467 +
  468 + List<DoCondition> conditions = doConditionMapper.selectList(new QueryWrapper<DoCondition>().lambda()
  469 + .eq(DoCondition::getSceneLinkageId, currentSceneId)
  470 + .eq(DoCondition::getEntityType,ScopeEnum.ALL));
  471 + conditions.forEach(item -> {
  472 + item.setEntityId(allDevices);
  473 + doConditionMapper.updateById(item);
  474 + });
  475 +
  476 + List<DoAction> actions = doActionMapper.selectList(new QueryWrapper<DoAction>().lambda()
  477 + .eq(DoAction::getSceneLinkageId, currentSceneId)
  478 + .eq(DoAction::getEntityType,ScopeEnum.ALL));
  479 + actions.forEach(item -> {
  480 + item.setDeviceId(allDevices);
  481 + doActionMapper.updateById(item);
  482 + });
  483 +
  484 + if (matchedDevices.isEmpty()) {
442 485 return null;
443 486 }
444 487
445 488 Map<String, Map> engineConfig = new HashMap<>();
446   - engineConfig.put("scenes", devices);
  489 + engineConfig.put("scenes", matchedDevices);
447 490
448 491
449 492 return JacksonUtil.convertValue(engineConfig, JsonNode.class);
450 493 }
451 494
  495 + /**
  496 + * 设备与场景联动的映射集合
  497 + *
  498 + * @param resultMap 缓存设备和场景联动映射结果的集合
  499 + * @param devices 设备主键集合
  500 + * @param scenId 场景联动主键
  501 + */
  502 + private void deviceSceneMap(Map<String, List<String>> resultMap, List<String> devices, String scenId) {
  503 + for (String deviceId : devices) {
  504 + List<String> scenes = resultMap.computeIfAbsent(deviceId, k -> new ArrayList<String>());
  505 + if (!scenes.contains(scenId)) {
  506 + scenes.add(scenId);
  507 + }
  508 + if (scenes.isEmpty()) {
  509 + resultMap.remove(deviceId);
  510 + } else {
  511 + resultMap.put(deviceId, scenes);
  512 + }
  513 + }
  514 + }
  515 +
452 516 private List<String> getQueryOrganizationIds(String tenantId, List<String> organizationIds) {
453 517 // 查询该组织的所有子类
454 518 List<OrganizationDTO> organizationDTOS =
... ...
... ... @@ -5,12 +5,15 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
5 5 import lombok.RequiredArgsConstructor;
6 6 import org.springframework.stereotype.Service;
7 7 import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO;
  8 +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum;
8 9 import org.thingsboard.server.dao.yunteng.entities.Trigger;
9 10 import org.thingsboard.server.dao.yunteng.mapper.TriggerMapper;
10 11 import org.thingsboard.server.dao.yunteng.service.AbstractBaseService;
11 12 import org.thingsboard.server.dao.yunteng.service.TriggerService;
12 13
  14 +import java.util.List;
13 15 import java.util.Optional;
  16 +import java.util.stream.Collectors;
14 17
15 18 /**
16 19 * @Description
... ... @@ -24,15 +27,16 @@ public class TriggerServiceImpl extends AbstractBaseService<TriggerMapper, Trigg
24 27 private final TriggerMapper triggerMapper;
25 28
26 29 @Override
27   - public TriggerDTO getTrigger(String sceneId, String deviceId) {
  30 + public List<TriggerDTO> getTrigger(String sceneId) {
28 31 LambdaQueryWrapper filter = new QueryWrapper<Trigger>().lambda()
29   - .eq(Trigger::getSceneLinkageId, sceneId)
30   - .eq(Trigger::getEntityId, deviceId);
31   - Trigger trigger = triggerMapper.selectOne(filter);
32   - if(trigger == null){
  32 + .eq(Trigger::getSceneLinkageId, sceneId);
  33 + List<Trigger> trigger = triggerMapper.selectList(filter);
  34 + if(trigger == null || trigger.isEmpty()){
33 35 return null;
34 36 }
35 37
36   - return trigger.getDTO(TriggerDTO.class);
  38 + return trigger.stream()
  39 + .map(item -> item.getDTO(TriggerDTO.class))
  40 + .collect(Collectors.toList());
37 41 }
38 42 }
... ...
  1 +package org.thingsboard.server.dao.yunteng.mapper;
  2 +
  3 +/**
  4 + * @version V1.0
  5 + * @Description :
  6 + * 1.其它地方抛出异常,交由控制层统一处理
  7 + * 2.服务层注意持久化的事务管理
  8 + * @Dependency: 依赖包
  9 + * @Author: junlianglee
  10 + * @Date Created in 2021/12/28$
  11 + * @Copyright 2016-2018 - Powered By 云腾五洲
  12 + */
  13 +
  14 +import org.apache.ibatis.type.BaseTypeHandler;
  15 +import org.apache.ibatis.type.JdbcType;
  16 +
  17 +import java.sql.CallableStatement;
  18 +import java.sql.PreparedStatement;
  19 +import java.sql.ResultSet;
  20 +import java.sql.SQLException;
  21 +import java.util.Arrays;
  22 +import java.util.List;
  23 +
  24 +public class ListStringTypeHandler extends BaseTypeHandler {
  25 +
  26 + @Override
  27 + public Object getNullableResult(ResultSet rs, String columnName)
  28 + throws SQLException {
  29 + return Arrays.asList(rs.getString(columnName).split(","));
  30 + }
  31 +
  32 + @Override
  33 + public Object getNullableResult(ResultSet resultSet, int i) throws SQLException {
  34 + return Arrays.asList(resultSet.getString(i).split(","));
  35 + }
  36 +
  37 + @Override
  38 + public Object getNullableResult(CallableStatement cs, int columnIndex)
  39 + throws SQLException {
  40 + return Arrays.asList(cs.getString(columnIndex).split(","));
  41 + }
  42 +
  43 + @Override
  44 + public void setNonNullParameter(PreparedStatement ps, int i,
  45 + Object parameter, JdbcType jdbcType) throws SQLException {
  46 + ps.setString(i, ((List) parameter).toString());
  47 + }
  48 +}
... ...
... ... @@ -20,11 +20,11 @@ public interface SceneLinkageService extends BaseService<SceneLinkage>{
20 20 * 新增场景联动
21 21 * @param sceneLinkageDTO 场景联动信息
22 22 * @param tenantId 租户主键
23   - * @param tenantAdmin 当前用户是否租户管理员
24 23 * @param currentUserId 当前登录用户主键
  24 + * @param customerId 客户ID
25 25 * @return sceneLinkageDTO
26 26 */
27   - SceneLinkageDTO saveSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId,boolean tenantAdmin,String currentUserId);
  27 + SceneLinkageDTO saveSceneLinkage(SceneLinkageDTO sceneLinkageDTO, String tenantId,String currentUserId,String customerId);
28 28
29 29 /**
30 30 * 删除场景联动
... ... @@ -37,11 +37,11 @@ public interface SceneLinkageService extends BaseService<SceneLinkage>{
37 37 * 修改场景联动
38 38 * @param sceneLinkageDTO 场景联动信息
39 39 * @param tenantId 租户主键
40   - * @param tenantAdmin 当前用户是否租户管理员
41 40 * @param currentUserId 当前登录用户主键
  41 + * @param customerId 客户ID
42 42 * @return
43 43 */
44   - SceneLinkageDTO updateSceneLinkage(SceneLinkageDTO sceneLinkageDTO,String tenantId,boolean tenantAdmin,String currentUserId);
  44 + SceneLinkageDTO updateSceneLinkage(SceneLinkageDTO sceneLinkageDTO,String tenantId,String currentUserId,String customerId);
45 45
46 46 /**
47 47 * 分页查询
... ... @@ -69,20 +69,20 @@ public interface SceneLinkageService extends BaseService<SceneLinkage>{
69 69 /**
70 70 * 通过组织id查询设备集合
71 71 * @param organizationId 组织ID
72   - * @param isTenantAdmin true租户管理员 false客户
73   - * @param tenantId 租户ID
74   - * @param currentUserId 当前用户ID
  72 + * @param tenantId 租户ID
  73 + * @param customerId 客户ID
75 74 * @return
76 75 */
77   - List<DeviceDTO> findDeviceList(String organizationId,boolean isTenantAdmin,String tenantId,String currentUserId);
  76 + List<DeviceDTO> findDeviceList(String organizationId,String tenantId,String customerId);
78 77
79 78 /**
80 79 * 获取租户的场景联动节点配置信息
81 80 * @param sceneId 场景联动主键
82 81 * @param tenantId 租户主键
  82 + * @param customerId 客户主键
83 83 * @param state 是否启动
84 84 * @return
85 85 */
86   - JsonNode getRuleNodeConfig(String sceneId,String tenantId,Integer state);
  86 + JsonNode getRuleNodeConfig(String sceneId,String tenantId,String customerId,Integer state);
87 87
88 88 }
... ...
... ... @@ -5,6 +5,7 @@ import org.thingsboard.server.common.data.yunteng.dto.MenuDTO;
5 5 import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO;
6 6 import org.thingsboard.server.dao.yunteng.entities.Trigger;
7 7
  8 +import java.util.List;
8 9 import java.util.Optional;
9 10
10 11 /**
... ... @@ -13,5 +14,5 @@ import java.util.Optional;
13 14 * @Date 2021/12/6 19:52
14 15 */
15 16 public interface TriggerService extends BaseService<Trigger>{
16   - TriggerDTO getTrigger(String sceneId, String deviceId);
  17 + List<TriggerDTO> getTrigger(String sceneId);
17 18 }
... ...
... ... @@ -4,7 +4,8 @@
4 4 <mapper namespace="org.thingsboard.server.dao.yunteng.mapper.DoActionMapper">
5 5 <resultMap id="actionDTO" type="org.thingsboard.server.common.data.yunteng.dto.DoActionDTO">
6 6 <result property="id" column="id"/>
7   - <result property="deviceId" column="device_id"/>
  7 + <result property="deviceId" column="device_id" typeHandler="org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler"/>
  8 + <result property="entityType" column="entity_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
8 9 <result property="doContext" column="do_context" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
9 10 <result property="outTarget" column="out_target" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
10 11 <result property="sceneLinkageId" column="scene_linkage_id"/>
... ...
... ... @@ -4,7 +4,8 @@
4 4 <mapper namespace="org.thingsboard.server.dao.yunteng.mapper.DoConditionMapper">
5 5 <resultMap id="conditionDTO" type="org.thingsboard.server.common.data.yunteng.dto.DoConditionDTO">
6 6 <result property="id" column="id"/>
7   - <result property="entityId" column="entity_id"/>
  7 + <result property="entityId" column="entity_id" typeHandler="org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler"/>
  8 + <result property="entityType" column="entity_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
8 9 <result property="triggerCondition" column="trigger_condition" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
9 10 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
10 11 <result property="sceneLinkageId" column="scene_linkage_id"/>
... ...
... ... @@ -4,7 +4,8 @@
4 4 <mapper namespace="org.thingsboard.server.dao.yunteng.mapper.TriggerMapper">
5 5 <resultMap id="triggerDTO" type="org.thingsboard.server.common.data.yunteng.dto.TriggerDTO">
6 6 <result property="id" column="id"/>
7   - <result property="entityId" column="entity_id"/>
  7 + <result property="entityId" column="entity_id" typeHandler="org.thingsboard.server.dao.yunteng.mapper.ListStringTypeHandler"/>
  8 + <result property="entityType" column="entity_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
8 9 <result property="triggerCondition" column="trigger_condition" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
9 10 <result property="triggerType" column="trigger_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
10 11 <result property="sceneLinkageId" column="scene_linkage_id"/>
... ...
... ... @@ -5,12 +5,14 @@ package org.thingsboard.rule.engine.yunteng.scene;
5 5
6 6 import com.fasterxml.jackson.databind.JsonNode;
7 7 import lombok.extern.slf4j.Slf4j;
  8 +import org.apache.commons.lang3.StringUtils;
8 9 import org.jetbrains.annotations.NotNull;
9 10 import org.thingsboard.rule.engine.api.TbContext;
10 11 import org.thingsboard.server.common.data.DataConstants;
11 12 import org.thingsboard.server.common.data.device.profile.AlarmCondition;
12 13 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter;
13 14 import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey;
  15 +import org.thingsboard.server.common.data.device.profile.AlarmRule;
14 16 import org.thingsboard.server.common.data.rule.RuleNodeState;
15 17 import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO;
16 18 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;
... ... @@ -38,7 +40,9 @@ class ReactState {
38 40 * 键:设备主键
39 41 * 值:设备指标参与的触发器
40 42 */
41   - private ConcurrentHashMap<String, TriggerState> triggerState = new ConcurrentHashMap<>();
  43 + private ConcurrentHashMap<String, TriggerState > triggerState = new ConcurrentHashMap<>();
  44 +
  45 + private ConcurrentHashMap<String, TriggerState> clearState = new ConcurrentHashMap<>();
42 46
43 47 /**场景联动的执行条件状态
44 48 * 键:设备主键
... ... @@ -50,6 +54,7 @@ class ReactState {
50 54
51 55
52 56
  57 + private final List<TriggerDTO> triggers;
53 58 /**【场景联动的执行条件】懒加载*/
54 59 private final List<DoCondition> conditions;
55 60 /**【场景联动的执行集合】懒加载*/
... ... @@ -64,6 +69,8 @@ class ReactState {
64 69
65 70 ReactState(String reactId,TbContext ctx, TbSceneReactNodeConfig config) {
66 71 this.reactId = reactId;
  72 + TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class);
  73 + this.triggers = triggerService.getTrigger(reactId);
67 74 DoConditionService conditionService = SpringBeanUtils.getBean(DoConditionService.class);
68 75 this.conditions = conditionService.getConditions(reactId);
69 76 DoActionService actionService = SpringBeanUtils.getBean(DoActionService.class);
... ... @@ -74,29 +81,48 @@ class ReactState {
74 81
75 82
76 83 public void process(TbContext ctx, TbMsg msg,String deviceId) throws ExecutionException, InterruptedException {
77   - TriggerState triggerState = getOrCreateTriggerState(deviceId);
78   - boolean matched = false;
79   - if( actions != null){
  84 +
  85 +
  86 +
  87 +
  88 + if( actions == null){
80 89 ctx.tellSuccess(msg);
81 90 }
82 91
83   - if(triggerState != null){
84   - matched = triggerState.process(ctx,msg);
  92 + boolean matched;
  93 + if(triggers == null || triggers.isEmpty()){
  94 + matched = true;
  95 + }else{
  96 + matched = false;
  97 + for(TriggerDTO trigger: triggers){
  98 + TriggerState triggerState = getOrCreateTriggerState(trigger,deviceId);
  99 + matched = triggerState.process(ctx,msg);
  100 + if(matched){
  101 + break;
  102 + }
  103 + }
85 104 }
86 105
87 106
88 107 if(matched && conditions.size() >0 ){
89 108 matched = false;
90 109 for(DoCondition item:conditions){
91   - TriggerState conditionState = getOrCreateConditionState(item.getEntityId(),item.getTriggerCondition());
92   - boolean result = false;
93   - if( conditionState != null){
94   - result =conditionState.process(ctx,msg);
95   - }
96   - if( result){
  110 + List<String> entityIds = item.getEntityId();
  111 + if(entityIds == null || entityIds.isEmpty()){
97 112 matched = true;
98 113 break;
99 114 }
  115 + for(String id:entityIds){
  116 + TriggerState conditionState = getOrCreateConditionState(item.getId(),id,item.getTriggerCondition());
  117 + if( conditionState == null
  118 + || conditionState.process(ctx,msg)){
  119 + matched = true;
  120 + break;
  121 + }
  122 + }
  123 + if(matched){
  124 + break;
  125 + }
100 126 }
101 127 }
102 128
... ... @@ -115,38 +141,40 @@ class ReactState {
115 141
116 142
117 143
118   - protected TriggerState getOrCreateTriggerState(String deviceId) {
119   - if(triggerState.containsKey(deviceId)){
120   - return triggerState.get(deviceId);
  144 + protected TriggerState getOrCreateTriggerState(TriggerDTO trigger,String deviceId) {
  145 + String triggerId = trigger.getId();
  146 + String cacheKey =triggerId+deviceId;
  147 + if(triggerState.containsKey(cacheKey)){
  148 + return triggerState.get(cacheKey);
121 149 }
122   - TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class);
123   - TriggerDTO trigger =triggerService.getTrigger(reactId,deviceId);
124   - if(trigger != null){
  150 + if(trigger.getEntityId().contains(deviceId)){
125 151 TriggerState state = createTriggerState(deviceId, trigger.getTriggerCondition());
126   - triggerState.put(deviceId, state);
  152 + triggerState.put(cacheKey, state);
127 153 return state;
128 154 }
129 155 return null;
  156 +
130 157 }
131 158
132   - protected TriggerState getOrCreateConditionState(String deviceId,AlarmCondition condition) {
133   - if(conditionState.containsKey(deviceId)){
134   - return conditionState.get(deviceId);
  159 + protected TriggerState getOrCreateConditionState(String conditionId, String deviceId, AlarmRule condition) {
  160 + String cacheKey =conditionId+deviceId;
  161 + if(conditionState.containsKey(cacheKey)){
  162 + return conditionState.get(cacheKey);
135 163 }else{
136 164 TriggerState state = createTriggerState(deviceId, condition);
137   - conditionState.put(deviceId, state);
  165 + conditionState.put(cacheKey, state);
138 166 return state;
139 167 }
140 168
141 169 }
142 170
143 171 @NotNull
144   - private TriggerState createTriggerState(String deviceId, AlarmCondition condition) {
  172 + private TriggerState createTriggerState(String deviceId, AlarmRule rule) {
145 173 Set<AlarmConditionFilterKey> filterKeys = new HashSet<>();
146   - for(AlarmConditionFilter filter :condition.getCondition()){
  174 + for(AlarmConditionFilter filter :rule.getCondition().getCondition()){
147 175 filterKeys.add(filter.getKey());
148 176 }
149   - TriggerState state = new TriggerState(deviceId,condition, filterKeys,null);
  177 + TriggerState state = new TriggerState(deviceId,rule, filterKeys,null);
150 178
151 179 return state;
152 180 }
... ...
... ... @@ -15,7 +15,7 @@ import java.util.Map;
15 15 @Data
16 16 public class TbSceneReactNodeConfig implements NodeConfiguration<TbSceneReactNodeConfig> {
17 17
18   - /**【设备ID,指标】设备的哪些指标会触发场景联动*/
  18 + /**【设备ID,场景】设备的哪些指标会触发场景联动*/
19 19 private Map<String, List<String>> scenes;
20 20
21 21
... ...
... ... @@ -73,11 +73,11 @@ class TriggerState {
73 73
74 74 private final Set<AlarmConditionFilterKey> entityKeys;
75 75
76   - TriggerState( String originator, AlarmCondition condition,Set<AlarmConditionFilterKey> filterKeys,DynamicPredicateValueCtx dynamicPredicateValueCtx) {
  76 + TriggerState( String originator, AlarmRule rule,Set<AlarmConditionFilterKey> filterKeys,DynamicPredicateValueCtx dynamicPredicateValueCtx) {
77 77
78 78 this.originator = originator;
79 79 this.dynamicPredicateValueCtx = dynamicPredicateValueCtx;
80   - ruleState = new TriggerRuleState(condition, filterKeys, new PersistedAlarmRuleState());
  80 + ruleState = new TriggerRuleState(rule.getCondition(), filterKeys, new PersistedAlarmRuleState(),rule.getSchedule());
81 81 this.entityKeys = filterKeys;
82 82 }
83 83
... ...
... ... @@ -34,17 +34,7 @@ public class TriggerRuleState {
34 34
35 35
36 36
37   - public TriggerRuleState(AlarmCondition condition, Set<AlarmConditionFilterKey> entityKeys, PersistedAlarmRuleState state) {
38   - this.condition = condition;
39   - this.schedule = new AnyTimeSchedule();
40   - this.entityKeys = entityKeys;
41   - if (state != null) {
42   - this.state = state;
43   - } else {
44   - this.state = new PersistedAlarmRuleState(0L, 0L, 0L);
45   - }
46   - this.spec = getSpec(condition);
47   - }
  37 +
48 38
49 39 public TriggerRuleState(AlarmCondition condition, Set<AlarmConditionFilterKey> entityKeys, PersistedAlarmRuleState state, AlarmSchedule schedule) {
50 40 this.condition = condition;
... ...