Commit 210b8854544706f28a27505cb12df764e6f912f4
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; | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/ActionAlarmDTO.java
0 → 100644
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; | ... | ... |
... | ... | @@ -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 | } | ... | ... |
... | ... | @@ -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; | ... | ... |