Commit b38380d08ecb8e3e34e7706293bf9aed57c63dc1
Merge branch '20221203' into 'master'
refactor: 场景联动设备过滤条件添加产品 See merge request huang/thingsboard3.3.2!148
Showing
8 changed files
with
97 additions
and
46 deletions
... | ... | @@ -475,8 +475,10 @@ public class TkDeviceController extends BaseController { |
475 | 475 | DeviceProfileId deviceProfileId = |
476 | 476 | new DeviceProfileId(UUID.fromString(deviceDTO.getProfileId())); |
477 | 477 | |
478 | + CustomerId customerId = StringUtils.isBlank(deviceDTO.getCustomerId())?null:new CustomerId(UUID.fromString(deviceDTO.getCustomerId())); | |
479 | + | |
478 | 480 | tbDevice.setAdditionalInfo(additionalInfo); |
479 | - tbDevice.setCustomerId(null); | |
481 | + tbDevice.setCustomerId(customerId); | |
480 | 482 | tbDevice.setDeviceProfileId(deviceProfileId); |
481 | 483 | tbDevice.setLabel(deviceDTO.getLabel()); |
482 | 484 | tbDevice.setName(deviceDTO.getName()); | ... | ... |
... | ... | @@ -43,6 +43,7 @@ public class DeviceDTO extends TenantDTO { |
43 | 43 | @ApiModelProperty(value = "关联网关设备") |
44 | 44 | private String gatewayId; |
45 | 45 | private String gatewayName; |
46 | + private String gatewayAlias; | |
46 | 47 | |
47 | 48 | @ApiModelProperty(value = "设备凭证") |
48 | 49 | private TkCredentialsDto deviceToken; | ... | ... |
1 | 1 | package org.thingsboard.server.common.data.yunteng.dto; |
2 | +import com.fasterxml.jackson.annotation.JsonFormat; | |
3 | +import com.fasterxml.jackson.databind.annotation.JsonSerialize; | |
4 | +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; | |
2 | 5 | import lombok.Data; |
3 | 6 | import org.thingsboard.server.common.data.yunteng.enums.DeviceState; |
4 | 7 | |
8 | +import java.time.LocalDateTime; | |
9 | + | |
5 | 10 | @Data |
6 | 11 | public class RelationDeviceDTO { |
7 | 12 | private String tbDeviceId; |
8 | 13 | private String tbDeviceName; |
14 | + private String alias; | |
9 | 15 | private String label; |
10 | 16 | private DeviceState deviceState; |
11 | - private Long createdTime; | |
17 | + | |
18 | + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") | |
19 | + @JsonSerialize(using = LocalDateTimeSerializer.class) | |
20 | + private LocalDateTime createdTime; | |
12 | 21 | private Long lastOnlineTime; |
13 | 22 | |
14 | 23 | public void setDeviceState(boolean deviceState) { | ... | ... |
... | ... | @@ -5,12 +5,17 @@ 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.DoActionDTO; |
8 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; | |
9 | +import org.thingsboard.server.common.data.yunteng.enums.ScopeEnum; | |
10 | +import org.thingsboard.server.dao.yunteng.entities.TkDeviceEntity; | |
8 | 11 | import org.thingsboard.server.dao.yunteng.entities.TkDoActionEntity; |
9 | 12 | import org.thingsboard.server.dao.yunteng.entities.TenantBaseEntity; |
13 | +import org.thingsboard.server.dao.yunteng.mapper.DeviceMapper; | |
10 | 14 | import org.thingsboard.server.dao.yunteng.mapper.DoActionMapper; |
11 | 15 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; |
12 | 16 | import org.thingsboard.server.dao.yunteng.service.DoActionService; |
13 | 17 | |
18 | +import java.util.ArrayList; | |
14 | 19 | import java.util.List; |
15 | 20 | import java.util.Set; |
16 | 21 | import java.util.stream.Collectors; |
... | ... | @@ -20,13 +25,36 @@ import java.util.stream.Collectors; |
20 | 25 | @RequiredArgsConstructor |
21 | 26 | public class TkDoActionServiceImpl extends AbstractBaseService<DoActionMapper, TkDoActionEntity> |
22 | 27 | implements DoActionService { |
28 | + private final DeviceMapper deviceMapper; | |
23 | 29 | @Override |
24 | - public List<TkDoActionEntity> getActions(String sceneId) { | |
30 | + public List<TkDoActionEntity> getActionsByAll(String sceneId) { | |
25 | 31 | LambdaQueryWrapper filter = |
26 | - new QueryWrapper<TkDoActionEntity>().lambda().eq(TkDoActionEntity::getSceneLinkageId, sceneId); | |
32 | + new LambdaQueryWrapper<TkDoActionEntity>().eq(TkDoActionEntity::getSceneLinkageId, sceneId).eq(TkDoActionEntity::getEntityType, ScopeEnum.ALL); | |
27 | 33 | return baseMapper.selectList(filter); |
28 | 34 | } |
29 | 35 | |
36 | + | |
37 | + @Override | |
38 | + public List<TkDoActionEntity> getActionsByPart(String sceneId) { | |
39 | + LambdaQueryWrapper filter = | |
40 | + new LambdaQueryWrapper<TkDoActionEntity>().eq(TkDoActionEntity::getSceneLinkageId, sceneId).eq(TkDoActionEntity::getEntityType, ScopeEnum.PART); | |
41 | + List<TkDoActionEntity> source = baseMapper.selectList(filter); | |
42 | + return source.stream().map(t ->{ | |
43 | + List<TkDeviceEntity> partDevices = deviceMapper.selectList(new LambdaQueryWrapper<TkDeviceEntity>().in(TkDeviceEntity::getTbDeviceId,t.getDeviceId())); | |
44 | + List<String> deviceId = new ArrayList<>(); | |
45 | + for(TkDeviceEntity item : partDevices){ | |
46 | + if(!DeviceTypeEnum.SENSOR.equals(item.getDeviceType())){ | |
47 | + //网关子设备才需要重写deviceId字段 | |
48 | + break; | |
49 | + } | |
50 | + deviceId.add(item.getGatewayId()); | |
51 | + } | |
52 | + t.setDeviceId(deviceId); | |
53 | + return t; | |
54 | + }).collect(Collectors.toList()); | |
55 | + | |
56 | + } | |
57 | + | |
30 | 58 | @Override |
31 | 59 | public List<DoActionDTO> findDoActionByAlarmProfileIds( |
32 | 60 | String tenantId, Set<String> alarmProfileIds) { | ... | ... |
... | ... | @@ -440,8 +440,7 @@ public class TkSceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageM |
440 | 440 | String currentSceneId, String tenantId, String customerId, Integer state) { |
441 | 441 | List<TkSceneLinkageEntity> runningScenes = |
442 | 442 | baseMapper.selectList( |
443 | - new QueryWrapper<TkSceneLinkageEntity>() | |
444 | - .lambda() | |
443 | + new LambdaQueryWrapper<TkSceneLinkageEntity>() | |
445 | 444 | .eq(TkSceneLinkageEntity::getTenantId, tenantId) |
446 | 445 | .eq(TkSceneLinkageEntity::getStatus, FastIotConstants.StateValue.ENABLE)); |
447 | 446 | Set<String> enableIds = new HashSet<>(); |
... | ... | @@ -468,17 +467,7 @@ public class TkSceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageM |
468 | 467 | |
469 | 468 | List<DeviceDTO> organizationDevices = |
470 | 469 | findDeviceList(self.getOrganizationId(), tenantId, customerId,new ArrayList<>()); |
471 | - List<String> allDevices = new ArrayList<>(); | |
472 | - List<String> rpcDevices = new ArrayList<>(); | |
473 | - if(organizationDevices != null && !organizationDevices.isEmpty()){ | |
474 | - for (DeviceDTO item : organizationDevices) { | |
475 | - allDevices.add(item.getTbDeviceId()); | |
476 | - DeviceTypeEnum deviceType = item.getDeviceType(); | |
477 | - if(!DeviceTypeEnum.SENSOR.equals(deviceType)){ | |
478 | - rpcDevices.add(item.getTbDeviceId()); | |
479 | - } | |
480 | - } | |
481 | - } | |
470 | + | |
482 | 471 | |
483 | 472 | Map<String, List<String>> matchedDevices = new HashMap<>(); |
484 | 473 | |
... | ... | @@ -495,6 +484,7 @@ public class TkSceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageM |
495 | 484 | String scenId = trigger.getSceneLinkageId(); |
496 | 485 | List<String> devices = trigger.getEntityId(); |
497 | 486 | if(currentSceneId.equals(scenId)){ |
487 | + List<String> allDevices = filterDevice(organizationDevices,trigger.getDeviceProfileId(),false); | |
498 | 488 | if (ScopeEnum.ALL.equals(trigger.getEntityType()) ) { |
499 | 489 | devices = allDevices; |
500 | 490 | }else{ |
... | ... | @@ -516,7 +506,7 @@ public class TkSceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageM |
516 | 506 | Executors.newScheduledThreadPool(1) |
517 | 507 | .schedule( |
518 | 508 | () -> { |
519 | - freshEntityIds(currentSceneId, allDevices,rpcDevices, triggers); | |
509 | + freshEntityIds(currentSceneId, organizationDevices, triggers); | |
520 | 510 | }, |
521 | 511 | 1, |
522 | 512 | TimeUnit.SECONDS); |
... | ... | @@ -528,51 +518,66 @@ public class TkSceneLinkageServiceImpl extends AbstractBaseService<SceneLinkageM |
528 | 518 | return JacksonUtil.convertValue(engineConfig, JsonNode.class); |
529 | 519 | } |
530 | 520 | |
521 | + private List<String> filterDevice(List<DeviceDTO> organizationDevices,String profileId,boolean rpc){ | |
522 | + List<String> allDevices = new ArrayList<>(); | |
523 | + if(organizationDevices != null && !organizationDevices.isEmpty()){ | |
524 | + for (DeviceDTO item : organizationDevices) { | |
525 | + if(StringUtils.isBlank(item.getDeviceProfileId()) || !item.getDeviceProfileId().equals(profileId)){ | |
526 | + continue; | |
527 | + } | |
528 | + DeviceTypeEnum deviceType = item.getDeviceType(); | |
529 | + if(rpc && DeviceTypeEnum.SENSOR.equals(deviceType)){ | |
530 | + allDevices.add(item.getGatewayId()); | |
531 | + continue; | |
532 | + } | |
533 | + allDevices.add(item.getTbDeviceId()); | |
534 | + } | |
535 | + } | |
536 | + return allDevices; | |
537 | + } | |
538 | + | |
531 | 539 | /** |
532 | 540 | * 异步刷新场景联动的设备ID |
533 | 541 | * |
534 | 542 | * @param sceneId |
535 | - * @param allDevices | |
543 | + * @param organizationDevices | |
536 | 544 | * @param triggers |
537 | 545 | */ |
538 | - public void freshEntityIds(String sceneId, List<String> allDevices,List<String> rpcDevices, List<TkTriggerEntity> triggers) { | |
546 | + public void freshEntityIds(String sceneId, List<DeviceDTO> organizationDevices,List<TkTriggerEntity> triggers) { | |
539 | 547 | triggers.forEach( |
540 | 548 | trigger -> { |
541 | 549 | if (ScopeEnum.ALL.equals(trigger.getEntityType()) |
542 | 550 | && sceneId.equals(trigger.getSceneLinkageId())) { |
543 | - trigger.setEntityId(allDevices); | |
551 | + List<String> ids = filterDevice(organizationDevices,trigger.getDeviceProfileId(),false); | |
552 | + trigger.setEntityId(ids); | |
544 | 553 | triggerMapper.updateById(trigger); |
545 | 554 | } |
546 | 555 | }); |
547 | 556 | |
548 | 557 | List<TkDoConditionEntity> conditions = |
549 | 558 | doConditionMapper.selectList( |
550 | - new QueryWrapper<TkDoConditionEntity>() | |
551 | - .lambda() | |
559 | + new LambdaQueryWrapper<TkDoConditionEntity>() | |
552 | 560 | .eq(TkDoConditionEntity::getSceneLinkageId, sceneId) |
553 | 561 | .eq(TkDoConditionEntity::getEntityType, ScopeEnum.ALL)); |
554 | 562 | conditions.forEach( |
555 | 563 | item -> { |
556 | 564 | if (sceneId.equals(item.getSceneLinkageId())) { |
557 | - item.setEntityId(allDevices); | |
565 | + List<String> ids = filterDevice(organizationDevices,item.getDeviceProfileId(),false); | |
566 | + item.setEntityId(ids); | |
558 | 567 | doConditionMapper.updateById(item); |
559 | 568 | } |
560 | 569 | }); |
561 | 570 | |
562 | 571 | List<TkDoActionEntity> actions = |
563 | 572 | doActionMapper.selectList( |
564 | - new QueryWrapper<TkDoActionEntity>() | |
565 | - .lambda() | |
573 | + new LambdaQueryWrapper<TkDoActionEntity>() | |
566 | 574 | .eq(TkDoActionEntity::getSceneLinkageId, sceneId) |
567 | 575 | .eq(TkDoActionEntity::getEntityType, ScopeEnum.ALL)); |
568 | 576 | actions.forEach( |
569 | 577 | item -> { |
570 | 578 | if (sceneId.equals(item.getSceneLinkageId())) { |
571 | - if(ActionTypeEnum.DEVICE_OUT.equals(item.getOutTarget())){ | |
572 | - item.setDeviceId(rpcDevices); | |
573 | - }else{ | |
574 | - item.setDeviceId(allDevices); | |
575 | - } | |
579 | + List<String> ids = filterDevice(organizationDevices,item.getDeviceProfileId(),ActionTypeEnum.DEVICE_OUT.equals(item.getOutTarget())?true:false); | |
580 | + item.setDeviceId(ids); | |
576 | 581 | |
577 | 582 | doActionMapper.updateById(item); |
578 | 583 | } | ... | ... |
... | ... | @@ -13,7 +13,8 @@ import java.util.Set; |
13 | 13 | */ |
14 | 14 | public interface DoActionService extends BaseService<TkDoActionEntity>{ |
15 | 15 | |
16 | - List<TkDoActionEntity> getActions(String sceneId); | |
16 | + List<TkDoActionEntity> getActionsByAll(String sceneId); | |
17 | + List<TkDoActionEntity> getActionsByPart(String sceneId); | |
17 | 18 | |
18 | 19 | List<DoActionDTO> findDoActionByAlarmProfileIds(String tenantId, Set<String> alarmProfileIds); |
19 | 20 | } | ... | ... |
... | ... | @@ -39,6 +39,7 @@ |
39 | 39 | <result property="organizationId" column="organization_id"/> |
40 | 40 | <result property="gatewayId" column="gateway_id"/> |
41 | 41 | <result property="gatewayName" column="gateway_name"/> |
42 | + <result property="gatewayAlias" column="gateway_alias"/> | |
42 | 43 | <association property="deviceProfile" |
43 | 44 | javaType="org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO"> |
44 | 45 | <result property="name" column="profile_name"/> |
... | ... | @@ -50,8 +51,9 @@ |
50 | 51 | </association> |
51 | 52 | </resultMap> |
52 | 53 | <resultMap id="relationDeviceMap" type="org.thingsboard.server.common.data.yunteng.dto.RelationDeviceDTO"> |
53 | - <result property="tbDeviceId" column="id"/> | |
54 | + <result property="tbDeviceId" column="tb_device_id"/> | |
54 | 55 | <result property="tbDeviceName" column="name"/> |
56 | + <result property="alias" column="alias"/> | |
55 | 57 | <result property="label" column="label"/> |
56 | 58 | <result property="deviceState" column="status"/> |
57 | 59 | <result property="createdTime" column="created_time"/> |
... | ... | @@ -71,7 +73,7 @@ |
71 | 73 | </sql> |
72 | 74 | <sql id="detailColumns"> |
73 | 75 | <include refid="pageColumns"/> |
74 | - ,ifd.gateway_id,idg.name gateway_name | |
76 | + ,ifd.gateway_id,idg.name gateway_name,idg.alias gateway_alias | |
75 | 77 | </sql> |
76 | 78 | <sql id="pageColumns"> |
77 | 79 | <include refid="basicColumns"/> |
... | ... | @@ -103,6 +105,8 @@ |
103 | 105 | ifd.name LIKE concat('%',#{queryMap.name}::TEXT,'%') |
104 | 106 | or |
105 | 107 | ifd.sn LIKE concat('%',#{queryMap.name}::TEXT,'%') |
108 | + or | |
109 | + ifd.alias LIKE concat('%',#{queryMap.name}::TEXT,'%') | |
106 | 110 | ) |
107 | 111 | </if> |
108 | 112 | <if test="queryMap.deviceType !=null and queryMap.deviceType !=''"> |
... | ... | @@ -207,27 +211,26 @@ |
207 | 211 | </select> |
208 | 212 | <select id="getRelationDevicePage" resultMap="relationDeviceMap"> |
209 | 213 | SELECT |
210 | - de.id, | |
214 | + de.tb_device_id, | |
211 | 215 | de.name, |
216 | + de.alias, | |
212 | 217 | de.label, |
213 | - de.created_time, | |
218 | + de.create_time as created_time, | |
214 | 219 | A.bool_v AS status, |
215 | 220 | b.long_v AS last_online_time |
216 | 221 | FROM |
217 | - device de | |
218 | - LEFT JOIN relation rt ON de."id" = rt.to_id | |
219 | - LEFT JOIN attribute_kv A ON de."id" = A.entity_id | |
222 | + tk_device de | |
223 | + LEFT JOIN relation rt ON de.tb_device_id::uuid = rt.to_id | |
224 | + LEFT JOIN attribute_kv A ON de.tb_device_id::uuid = A.entity_id | |
220 | 225 | AND A.entity_type = 'DEVICE' |
221 | 226 | AND A.attribute_key = 'active' |
222 | - LEFT JOIN attribute_kv b ON de."id" = b.entity_id | |
227 | + LEFT JOIN attribute_kv b ON de.tb_device_id::uuid = b.entity_id | |
223 | 228 | AND b.entity_type = 'DEVICE' |
224 | 229 | AND b.attribute_key = 'lastActivityTime' |
225 | 230 | <where> |
226 | 231 | rt.from_id ::TEXT = #{queryMap.fromId} |
227 | - AND de.tenant_id ::TEXT = #{queryMap.tenantId} | |
228 | - <if test="queryMap.customerId !=null and queryMap.customerId !=''"> | |
229 | - AND de.customer_id ::TEXT = #{queryMap.customerId} | |
230 | - </if> | |
232 | + AND de.tenant_id = #{queryMap.tenantId} | |
233 | + | |
231 | 234 | <if test="queryMap.name !=null and queryMap.name !=''"> |
232 | 235 | AND de.name LIKE concat('%',#{queryMap.name}::TEXT,'%') |
233 | 236 | </if> | ... | ... |
... | ... | @@ -97,7 +97,8 @@ class ReactState { |
97 | 97 | DoConditionService conditionService = SpringBeanUtils.getBean(DoConditionService.class); |
98 | 98 | this.conditions = conditionService.getConditions(reactId); |
99 | 99 | DoActionService actionService = SpringBeanUtils.getBean(DoActionService.class); |
100 | - this.actions = actionService.getActions(reactId); | |
100 | + this.actions = actionService.getActionsByAll(reactId); | |
101 | + this.actions.addAll(actionService.getActionsByPart(reactId)); | |
101 | 102 | for (TkDoActionEntity action : actions) { |
102 | 103 | /**动作中只有1个告警通知*/ |
103 | 104 | if (ActionTypeEnum.MSG_NOTIFY.equals(action.getOutTarget())) { |
... | ... | @@ -208,7 +209,8 @@ class ReactState { |
208 | 209 | if (alarm != null && alarm.getClearRule() != null) { |
209 | 210 | for (TriggerDTO rule : alarm.getClearRule()) { |
210 | 211 | if ((ScopeEnum.PART.equals(rule.getEntityType()) && !rule.getEntityId().contains(deviceId)) |
211 | - || !alarmAction.getDeviceId().contains(deviceId)) { | |
212 | +// || !alarmAction.getDeviceId().contains(deviceId) | |
213 | + ) { | |
212 | 214 | continue; |
213 | 215 | } |
214 | 216 | ... | ... |