Showing
20 changed files
with
490 additions
and
127 deletions
... | ... | @@ -5,7 +5,6 @@ import io.swagger.annotations.ApiOperation; |
5 | 5 | import lombok.RequiredArgsConstructor; |
6 | 6 | import org.apache.commons.lang3.StringUtils; |
7 | 7 | import org.quartz.SchedulerException; |
8 | -import org.springframework.security.access.prepost.PreAuthorize; | |
9 | 8 | import org.springframework.validation.annotation.Validated; |
10 | 9 | import org.springframework.web.bind.annotation.*; |
11 | 10 | import org.thingsboard.server.common.data.exception.ThingsboardException; |
... | ... | @@ -37,13 +36,14 @@ public class TkTaskCenterController extends BaseController { |
37 | 36 | @GetMapping( |
38 | 37 | name = "page", |
39 | 38 | params = {PAGE_SIZE, PAGE}) |
40 | - public TkPageData<TkTaskCenterDTO> pageDevice( | |
39 | + public TkPageData<TkTaskCenterDTO> page( | |
41 | 40 | @RequestParam(PAGE_SIZE) int pageSize, |
42 | 41 | @RequestParam(PAGE) int page, |
43 | 42 | @RequestParam(value = "state", required = false) Integer state, |
44 | 43 | @RequestParam(value = "targetType", required = false) TargetTypeEnum targetType, |
45 | 44 | @RequestParam(value = ORDER_FILED, required = false) String orderBy, |
46 | - @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) | |
45 | + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType, | |
46 | + @RequestParam(value = "tbDeviceId", required = false) String tbDeviceId) | |
47 | 47 | throws ThingsboardException { |
48 | 48 | HashMap<String, Object> queryMap = new HashMap<>(); |
49 | 49 | queryMap.put(PAGE_SIZE, pageSize); |
... | ... | @@ -52,13 +52,17 @@ public class TkTaskCenterController extends BaseController { |
52 | 52 | queryMap.put(ORDER_TYPE, orderType); |
53 | 53 | queryMap.put("state", state); |
54 | 54 | queryMap.put("targetType", targetType); |
55 | + if (!StringUtils.isEmpty(tbDeviceId)) { | |
56 | + queryMap.put("tbDeviceId", tbDeviceId); | |
57 | + } | |
55 | 58 | return tkTaskCenterService.taskCenterPage(queryMap, getCurrentUser().getCurrentTenantId()); |
56 | 59 | } |
57 | 60 | |
58 | 61 | @PostMapping("/add") |
59 | 62 | @ApiOperation(value = "新增任务中心") |
60 | -// @PreAuthorize( | |
61 | -// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:add:post'})") | |
63 | + // @PreAuthorize( | |
64 | + // | |
65 | + // "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:add:post'})") | |
62 | 66 | public ResponseResult<TkTaskCenterDTO> save( |
63 | 67 | @RequestBody @Validated(AddGroup.class) TkTaskCenterDTO taskCenter) |
64 | 68 | throws ThingsboardException, SchedulerException { |
... | ... | @@ -69,8 +73,9 @@ public class TkTaskCenterController extends BaseController { |
69 | 73 | } |
70 | 74 | |
71 | 75 | @PutMapping("/update") |
72 | -// @PreAuthorize( | |
73 | -// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
76 | + // @PreAuthorize( | |
77 | + // | |
78 | + // "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
74 | 79 | @ApiOperation(value = "编辑任务中心") |
75 | 80 | public ResponseResult<TkTaskCenterDTO> update( |
76 | 81 | @RequestBody @Validated(UpdateGroup.class) TkTaskCenterDTO taskCenter) |
... | ... | @@ -82,8 +87,9 @@ public class TkTaskCenterController extends BaseController { |
82 | 87 | } |
83 | 88 | |
84 | 89 | @PutMapping("/{id}/update/{state}") |
85 | -// @PreAuthorize( | |
86 | -// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
90 | + // @PreAuthorize( | |
91 | + // | |
92 | + // "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:update:update'})") | |
87 | 93 | @ApiOperation(value = "更新状态") |
88 | 94 | public ResponseResult<Boolean> updateState( |
89 | 95 | @PathVariable("id") String id, @PathVariable("state") Integer state) |
... | ... | @@ -96,8 +102,8 @@ public class TkTaskCenterController extends BaseController { |
96 | 102 | } |
97 | 103 | |
98 | 104 | @DeleteMapping |
99 | -// @PreAuthorize( | |
100 | -// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:delete'})") | |
105 | + // @PreAuthorize( | |
106 | + // "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:delete'})") | |
101 | 107 | @ApiOperation(value = "删除任务中心") |
102 | 108 | public ResponseResult<Boolean> deleteTaskCenter(@RequestBody DeleteDTO deleteDTO) |
103 | 109 | throws ThingsboardException, SchedulerException { |
... | ... | @@ -105,18 +111,22 @@ public class TkTaskCenterController extends BaseController { |
105 | 111 | return ResponseResult.success(tkTaskCenterService.deleteTaskCenter(deleteDTO)); |
106 | 112 | } |
107 | 113 | |
108 | - @PutMapping("/{id}/cancel/{tbDeviceId}") | |
109 | -// @PreAuthorize( | |
110 | -// "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:cancel'})") | |
111 | - @ApiOperation(value = "设备取消任务执行") | |
112 | - public ResponseResult<Boolean> cancelExecute( | |
113 | - @PathVariable("id") String taskId, @PathVariable("tbDeviceId") String tbDeviceId)throws ThingsboardException { | |
114 | - if(StringUtils.isEmpty(taskId) || StringUtils.isEmpty(tbDeviceId)){ | |
114 | + @PutMapping("/{id}/update/{tbDeviceId}/{allow}") | |
115 | + // @PreAuthorize( | |
116 | + // | |
117 | + // "@check.checkPermissions({'TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:task_center:cancel'})") | |
118 | + @ApiOperation(value = "设备更新任务执行") | |
119 | + public ResponseResult<Boolean> cancelOrAllowExecute( | |
120 | + @PathVariable("id") String taskId, | |
121 | + @PathVariable("tbDeviceId") String tbDeviceId, | |
122 | + @PathVariable("allow") boolean allow) | |
123 | + throws ThingsboardException { | |
124 | + if (StringUtils.isEmpty(taskId) || StringUtils.isEmpty(tbDeviceId)) { | |
115 | 125 | throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); |
116 | 126 | } |
117 | 127 | return ResponseResult.success( |
118 | - tkTaskCenterService.cancelExecute( | |
119 | - taskId, tbDeviceId, getCurrentUser().getCurrentTenantId())); | |
128 | + tkTaskCenterService.cancelOrAllowExecute( | |
129 | + taskId, tbDeviceId, getCurrentUser().getCurrentTenantId(), allow)); | |
120 | 130 | } |
121 | 131 | |
122 | 132 | private TkTaskCenterDTO saveOrUpdate(TkTaskCenterDTO tkTaskCenterDTO) | ... | ... |
... | ... | @@ -16,6 +16,7 @@ import org.thingsboard.server.common.data.id.DeviceId; |
16 | 16 | import org.thingsboard.server.common.data.id.TenantId; |
17 | 17 | import org.thingsboard.server.common.data.rpc.ToDeviceRpcRequestBody; |
18 | 18 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
19 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
19 | 20 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
20 | 21 | import org.thingsboard.server.common.data.yunteng.dto.task.TargetContentDTO; |
21 | 22 | import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; |
... | ... | @@ -25,6 +26,8 @@ import org.thingsboard.server.dao.yunteng.service.TkDeviceService; |
25 | 26 | import org.thingsboard.server.dao.yunteng.service.TkTaskCenterService; |
26 | 27 | import org.thingsboard.server.service.rpc.TbCoreDeviceRpcService; |
27 | 28 | import org.thingsboard.server.service.security.model.SecurityUser; |
29 | +import java.time.LocalDateTime; | |
30 | +import java.time.ZoneOffset; | |
28 | 31 | import java.util.*; |
29 | 32 | |
30 | 33 | @Component("rpcCommandTask") |
... | ... | @@ -40,6 +43,8 @@ public class RpcCommandTask { |
40 | 43 | private final TkTaskCenterService tkTaskCenterService; |
41 | 44 | private final TbCoreDeviceRpcService tbCoreDeviceRpcService; |
42 | 45 | private final TkDeviceService tkDeviceService; |
46 | + private final CacheUtils cacheUtils; | |
47 | + | |
43 | 48 | public void process(String taskCenterId) { |
44 | 49 | // 通过任务中心ID查询执行命令及执行对象 |
45 | 50 | ListenableFuture<TkTaskCenterDTO> future = |
... | ... | @@ -57,6 +62,15 @@ public class RpcCommandTask { |
57 | 62 | // send cmd |
58 | 63 | if (targetContent.getData() != null && null != cmdJsonNode) { |
59 | 64 | String tenantId = tkTaskCenterDTO.getTenantId(); |
65 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
66 | + String key = | |
67 | + FastIotConstants.CacheConfigKey.TASK_CENTER_EXECUTE_TIME | |
68 | + + "_" | |
69 | + + tkTaskCenterDTO.getId(); | |
70 | + cacheUtils.put( | |
71 | + cacheName, | |
72 | + key, | |
73 | + LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
60 | 74 | if (targetType.equals(TargetTypeEnum.DEVICES)) { |
61 | 75 | for (String deviceId : targetContent.getData()) { |
62 | 76 | sendRpcCommand(cmdJsonNode, tenantId, deviceId, securityUser); |
... | ... | @@ -82,7 +96,7 @@ public class RpcCommandTask { |
82 | 96 | for (String deviceProfileId : targetContent.getData()) { |
83 | 97 | Futures.addCallback( |
84 | 98 | tkDeviceService.findDeviceListByDeviceProfileId(deviceProfileId, tenantId), |
85 | - new FutureCallback<List<DeviceDTO>>() { | |
99 | + new FutureCallback<>() { | |
86 | 100 | @Override |
87 | 101 | public void onSuccess(@Nullable List<DeviceDTO> deviceDTOS) { |
88 | 102 | if (null != deviceDTOS && !deviceDTOS.isEmpty()) { |
... | ... | @@ -125,7 +139,7 @@ public class RpcCommandTask { |
125 | 139 | true, |
126 | 140 | System.currentTimeMillis() + Math.max(minTimeout, defaultTimeout), |
127 | 141 | body, |
128 | - false, | |
142 | + true, | |
129 | 143 | null, |
130 | 144 | null); |
131 | 145 | tbCoreDeviceRpcService.processRestApiRpcRequest( | ... | ... |
... | ... | @@ -27,7 +27,8 @@ public interface FastIotConstants { |
27 | 27 | String MOBILE_LOGIN_SMS_CODE = "mobileLoginSmsCode"; |
28 | 28 | String AREA = "thingsArea"; |
29 | 29 | String PUBLIC_ID = "publicId_"; |
30 | - String TASK_CENTER_INFOS = "taskCenterInfos_"; | |
30 | + String TASK_CENTER_INFOS = "taskCenterInfos"; | |
31 | + String TASK_CENTER_EXECUTE_TIME = "taskCenterExecuteTime"; | |
31 | 32 | } |
32 | 33 | |
33 | 34 | interface TBCacheConfig { | ... | ... |
... | ... | @@ -120,6 +120,8 @@ public final class ModelConstants { |
120 | 120 | public static final String TK_DEVICE_STATE_LOG = "tk_device_state_log"; |
121 | 121 | /** 任务中心表 */ |
122 | 122 | public static final String TK_TASK_CENTER_NAME = "tk_task_center"; |
123 | + /** 设备与任务中心映射表 */ | |
124 | + public static final String TK_DEVICE_TASK_CENTER_NAME = "tk_device_task_center"; | |
123 | 125 | } |
124 | 126 | |
125 | 127 | public static class TableFields { | ... | ... |
... | ... | @@ -19,6 +19,6 @@ public class TargetContentDTO { |
19 | 19 | @ApiModelProperty(value = "设备配置ID") |
20 | 20 | String deviceProfileId; |
21 | 21 | |
22 | - @ApiModelProperty(value = "取消执行的数据:只有目标类型是产品时才会有值,且List<String>里面为tbDeviceId") | |
22 | + @ApiModelProperty(value = "取消执行的数据:key为产品ID即deviceProfileId,value为List<String>里面为tbDeviceId") | |
23 | 23 | Map<String, List<String>> cancelExecuteDevices; |
24 | 24 | } | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.dto.task; | |
2 | + | |
3 | +import io.swagger.annotations.ApiModelProperty; | |
4 | +import lombok.Data; | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.BaseDTO; | |
6 | + | |
7 | +@Data | |
8 | +public class TkDeviceTaskCenterDTO extends BaseDTO { | |
9 | + @ApiModelProperty(value = "设备ID") | |
10 | + private String tbDeviceId; | |
11 | + | |
12 | + @ApiModelProperty(value = "任务中心ID") | |
13 | + private String taskCenterId; | |
14 | + | |
15 | + @ApiModelProperty(value = "是否允许执行:0不执行 1允许执行") | |
16 | + private Integer state; | |
17 | + | |
18 | + @ApiModelProperty(value = "租户ID") | |
19 | + private String tenantId; | |
20 | +} | ... | ... |
... | ... | @@ -33,9 +33,14 @@ public class TkTaskCenterDTO extends TenantDTO { |
33 | 33 | @NotNull(message = "执行时间不能为空", groups = AddGroup.class) |
34 | 34 | private TaskExecuteTimeDTO executeTime; |
35 | 35 | |
36 | - @ApiModelProperty(value = "0禁用 1启用") | |
36 | + @ApiModelProperty(value = "状态:0禁用 1启用") | |
37 | 37 | private Integer state = FastIotConstants.StateValue.DISABLE; |
38 | 38 | |
39 | + @ApiModelProperty(value = "最后执行时间") | |
40 | + private Long lastExecuteTime; | |
41 | + | |
42 | + private TkDeviceTaskCenterDTO tkDeviceTaskCenter; | |
43 | + | |
39 | 44 | @ApiModelProperty(value = "备注") |
40 | 45 | private String remark; |
41 | 46 | } | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/entities/TkDeviceTaskCenterEntity.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@EqualsAndHashCode(callSuper = true) | |
9 | +@Data | |
10 | +@TableName(value = ModelConstants.Table.TK_DEVICE_TASK_CENTER_NAME) | |
11 | +public class TkDeviceTaskCenterEntity extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = -5425391296429906856L; | |
14 | + private String tbDeviceId; | |
15 | + | |
16 | + private String taskCenterId; | |
17 | + | |
18 | + private Integer state; | |
19 | +} | ... | ... |
... | ... | @@ -2,6 +2,8 @@ package org.thingsboard.server.dao.yunteng.impl; |
2 | 2 | |
3 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; |
5 | +import com.google.common.util.concurrent.Futures; | |
6 | +import com.google.common.util.concurrent.ListenableFuture; | |
5 | 7 | import lombok.RequiredArgsConstructor; |
6 | 8 | import lombok.extern.slf4j.Slf4j; |
7 | 9 | import org.apache.commons.lang3.StringUtils; |
... | ... | @@ -17,6 +19,7 @@ import org.thingsboard.server.dao.yunteng.entities.SysJobLogEntity; |
17 | 19 | import org.thingsboard.server.dao.yunteng.mapper.SysJobLogMapper; |
18 | 20 | import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; |
19 | 21 | import org.thingsboard.server.dao.yunteng.service.TkSysJobLogService; |
22 | +import java.time.ZoneOffset; | |
20 | 23 | import java.util.Map; |
21 | 24 | import java.util.Optional; |
22 | 25 | |
... | ... | @@ -61,9 +64,7 @@ public class SysJobLogServiceImpl extends AbstractBaseService<SysJobLogMapper, S |
61 | 64 | } |
62 | 65 | }) |
63 | 66 | .orElseThrow( |
64 | - () -> { | |
65 | - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
66 | - }); | |
67 | + () -> new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage())); | |
67 | 68 | } |
68 | 69 | |
69 | 70 | @Override |
... | ... | @@ -77,9 +78,7 @@ public class SysJobLogServiceImpl extends AbstractBaseService<SysJobLogMapper, S |
77 | 78 | Optional.ofNullable(sysJobLog) |
78 | 79 | .map(job -> baseMapper.updateById(jobLog)) |
79 | 80 | .orElseThrow( |
80 | - () -> { | |
81 | - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
82 | - }); | |
81 | + () -> new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage())); | |
83 | 82 | } |
84 | 83 | return jobLogDTO; |
85 | 84 | } |
... | ... | @@ -109,4 +108,21 @@ public class SysJobLogServiceImpl extends AbstractBaseService<SysJobLogMapper, S |
109 | 108 | } |
110 | 109 | return result; |
111 | 110 | } |
111 | + | |
112 | + @Override | |
113 | + public ListenableFuture<Long> findLastLogEndTimeByJobId(String jobId, String jobGroup) { | |
114 | + SysJobLogEntity entity = | |
115 | + baseMapper.selectOne( | |
116 | + new LambdaQueryWrapper<SysJobLogEntity>() | |
117 | + .eq(SysJobLogEntity::getJobId, jobId) | |
118 | + .eq(SysJobLogEntity::getJobGroup, jobGroup) | |
119 | + .orderBy(true, false, SysJobLogEntity::getEndTime) | |
120 | + .last("limit 1")); | |
121 | + return Optional.ofNullable(entity) | |
122 | + .map( | |
123 | + obj -> | |
124 | + Futures.immediateFuture( | |
125 | + obj.getEndTime().toInstant(ZoneOffset.of("+8")).toEpochMilli())) | |
126 | + .orElse(Futures.immediateFuture(null)); | |
127 | + } | |
112 | 128 | } | ... | ... |
... | ... | @@ -2,17 +2,23 @@ package org.thingsboard.server.dao.yunteng.impl; |
2 | 2 | |
3 | 3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
4 | 4 | import com.baomidou.mybatisplus.core.metadata.IPage; |
5 | +import com.google.common.util.concurrent.FutureCallback; | |
5 | 6 | import com.google.common.util.concurrent.Futures; |
6 | 7 | import com.google.common.util.concurrent.ListenableFuture; |
8 | +import com.google.common.util.concurrent.MoreExecutors; | |
7 | 9 | import lombok.RequiredArgsConstructor; |
8 | 10 | import org.apache.commons.lang3.StringUtils; |
11 | +import org.checkerframework.checker.nullness.qual.Nullable; | |
12 | +import org.jetbrains.annotations.NotNull; | |
9 | 13 | import org.quartz.*; |
10 | 14 | import org.springframework.stereotype.Service; |
11 | 15 | import org.springframework.transaction.annotation.Transactional; |
12 | 16 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
17 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
13 | 18 | import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; |
14 | 19 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
15 | 20 | import org.thingsboard.server.common.data.yunteng.dto.*; |
21 | +import org.thingsboard.server.common.data.yunteng.enums.JobGroupEnum; | |
16 | 22 | import org.thingsboard.server.common.data.yunteng.enums.StatusEnum; |
17 | 23 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
18 | 24 | import org.thingsboard.server.dao.util.yunteng.CronUtils; |
... | ... | @@ -32,24 +38,31 @@ import java.util.stream.Collectors; |
32 | 38 | public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJobEntity> |
33 | 39 | implements TkSysJobService { |
34 | 40 | private final Scheduler scheduler; |
35 | - | |
41 | + private final SysJobLogServiceImpl sysJobLogService; | |
42 | + private final CacheUtils cacheUtils; | |
36 | 43 | /** 项目启动时,初始化定时器 主要是防止手动修改数据库导致未同步到定时任务处理(注:不能手动修改数据库ID和任务组名,否则会导致脏数据) */ |
37 | 44 | @PostConstruct |
38 | 45 | public void init() throws SchedulerException { |
39 | 46 | scheduler.clear(); |
40 | - List<SysJobEntity> jobList = new ArrayList<>(); | |
41 | 47 | try { |
42 | - jobList.addAll( | |
43 | - baseMapper.selectList( | |
44 | - new LambdaQueryWrapper<SysJobEntity>() | |
45 | - .eq(SysJobEntity::getStatus, StatusEnum.ENABLE.getIndex()))); | |
48 | + List<SysJobEntity> jobList = | |
49 | + new ArrayList<>(baseMapper.selectList(new LambdaQueryWrapper<>())); | |
50 | + List<SysJobEntity> enableJobs = new ArrayList<>(); | |
51 | + for (SysJobEntity job : jobList) { | |
52 | + if (Objects.equals(job.getStatus(),StatusEnum.ENABLE.getIndex())) { | |
53 | + enableJobs.add(job); | |
54 | + } | |
55 | + if (Objects.equals(job.getJobGroup(), JobGroupEnum.TASK_CENTER.name())) { | |
56 | + // 查询任务中心的最新执行时间放在缓存里面 | |
57 | + queryJobLastExecuteTime(job.getSourceId(), job.getId(), job.getJobGroup()); | |
58 | + } | |
59 | + } | |
60 | + for (SysJobEntity job : enableJobs) { | |
61 | + ScheduleUtils.createScheduleJob(scheduler, job); | |
62 | + } | |
46 | 63 | } catch (Exception e) { |
47 | 64 | // TODO: 兼容ThingsboardInstallApplication。执行数据库脚本前,会跑表不存在异常。 |
48 | 65 | } |
49 | - | |
50 | - for (SysJobEntity job : jobList) { | |
51 | - ScheduleUtils.createScheduleJob(scheduler, job); | |
52 | - } | |
53 | 66 | } |
54 | 67 | |
55 | 68 | @Override |
... | ... | @@ -297,4 +310,22 @@ public class SysJobServiceImpl extends AbstractBaseService<SysJobMapper, SysJobE |
297 | 310 | .map(obj -> obj.getDTO(SysJobDTO.class)) |
298 | 311 | .orElse(null); |
299 | 312 | } |
313 | + | |
314 | + private void queryJobLastExecuteTime(String sourceId, String jobId, String jobGroup) { | |
315 | + ListenableFuture<Long> future = sysJobLogService.findLastLogEndTimeByJobId(jobId, jobGroup); | |
316 | + Futures.addCallback( | |
317 | + future, | |
318 | + new FutureCallback<>() { | |
319 | + @Override | |
320 | + public void onSuccess(@Nullable Long executeTime) { | |
321 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
322 | + String key = FastIotConstants.CacheConfigKey.TASK_CENTER_EXECUTE_TIME + "_" + sourceId; | |
323 | + cacheUtils.put(cacheName, key, executeTime); | |
324 | + } | |
325 | + | |
326 | + @Override | |
327 | + public void onFailure(@NotNull Throwable throwable) {} | |
328 | + }, | |
329 | + MoreExecutors.directExecutor()); | |
330 | + } | |
300 | 331 | } | ... | ... |
... | ... | @@ -613,9 +613,7 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
613 | 613 | return Optional.ofNullable(device) |
614 | 614 | .map(obj -> obj.getDTO(DeviceDTO.class)) |
615 | 615 | .orElseThrow( |
616 | - () -> { | |
617 | - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
618 | - }); | |
616 | + () -> new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage())); | |
619 | 617 | } |
620 | 618 | |
621 | 619 | @Override |
... | ... | @@ -710,4 +708,19 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev |
710 | 708 | .collect(Collectors.toList()))) |
711 | 709 | .orElse(Futures.immediateFuture(devices)); |
712 | 710 | } |
711 | + | |
712 | + @Override | |
713 | + public List<String> findTbDeviceIdsByDeviceProfileId(String deviceProfileId, String tenantId) { | |
714 | + if (StringUtils.isEmpty(deviceProfileId) || StringUtils.isEmpty(tenantId)) { | |
715 | + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
716 | + } | |
717 | + return Optional.ofNullable( | |
718 | + baseMapper.selectList( | |
719 | + new LambdaQueryWrapper<TkDeviceEntity>() | |
720 | + .eq(TkDeviceEntity::getTenantId, tenantId) | |
721 | + .eq(TkDeviceEntity::getDeviceProfileId, deviceProfileId) | |
722 | + .select(TkDeviceEntity::getTbDeviceId))) | |
723 | + .map(list -> list.stream().map(TkDeviceEntity::getTbDeviceId).collect(Collectors.toList())) | |
724 | + .orElse(null); | |
725 | + } | |
713 | 726 | } | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/impl/TkDeviceTaskCenterServiceImpl.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
4 | +import lombok.RequiredArgsConstructor; | |
5 | +import org.springframework.stereotype.Service; | |
6 | +import org.springframework.transaction.annotation.Transactional; | |
7 | +import org.thingsboard.server.common.data.StringUtils; | |
8 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
9 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
10 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkDeviceTaskCenterDTO; | |
11 | +import org.thingsboard.server.dao.yunteng.entities.TkDeviceTaskCenterEntity; | |
12 | +import org.thingsboard.server.dao.yunteng.mapper.TkDeviceTaskCenterMapper; | |
13 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
14 | +import org.thingsboard.server.dao.yunteng.service.TkDeviceTaskCenterService; | |
15 | +import java.util.List; | |
16 | + | |
17 | +@Service | |
18 | +@RequiredArgsConstructor | |
19 | +public class TkDeviceTaskCenterServiceImpl | |
20 | + extends AbstractBaseService<TkDeviceTaskCenterMapper, TkDeviceTaskCenterEntity> | |
21 | + implements TkDeviceTaskCenterService { | |
22 | + @Override | |
23 | + @Transactional | |
24 | + public TkDeviceTaskCenterDTO saveOrUpdate(TkDeviceTaskCenterDTO tkDeviceTaskCenterDTO) { | |
25 | + TkDeviceTaskCenterEntity entity = | |
26 | + tkDeviceTaskCenterDTO.getEntity(TkDeviceTaskCenterEntity.class); | |
27 | + if (StringUtils.isEmpty(tkDeviceTaskCenterDTO.getId())) { | |
28 | + baseMapper.insert(entity); | |
29 | + } else { | |
30 | + baseMapper.updateById(entity); | |
31 | + } | |
32 | + return tkDeviceTaskCenterDTO; | |
33 | + } | |
34 | + | |
35 | + @Override | |
36 | + @Transactional | |
37 | + public boolean delete(DeleteDTO delete) { | |
38 | + return baseMapper.deleteBatchIds(delete.getIds()) > FastIotConstants.MagicNumber.ZERO; | |
39 | + } | |
40 | + | |
41 | + @Override | |
42 | + public boolean updateStateByTbDeviceIdAndTaskCenterId( | |
43 | + String tenantId, String taskCenterId, String tbDeviceId, Integer state) { | |
44 | + TkDeviceTaskCenterEntity entity = | |
45 | + baseMapper.selectOne( | |
46 | + new LambdaQueryWrapper<TkDeviceTaskCenterEntity>() | |
47 | + .eq(TkDeviceTaskCenterEntity::getTbDeviceId, tbDeviceId) | |
48 | + .eq(TkDeviceTaskCenterEntity::getTaskCenterId, taskCenterId) | |
49 | + .eq(TkDeviceTaskCenterEntity::getTenantId, tenantId)); | |
50 | + if (null != entity) { | |
51 | + entity.setState(state); | |
52 | + baseMapper.updateById(entity); | |
53 | + } | |
54 | + return false; | |
55 | + } | |
56 | + | |
57 | + @Override | |
58 | + public boolean deleteByTaskCenterId(String tenantId, String taskCenterId) { | |
59 | + return baseMapper.delete( | |
60 | + new LambdaQueryWrapper<TkDeviceTaskCenterEntity>() | |
61 | + .eq(TkDeviceTaskCenterEntity::getTenantId, tenantId) | |
62 | + .eq(TkDeviceTaskCenterEntity::getTaskCenterId, taskCenterId)) | |
63 | + > FastIotConstants.MagicNumber.ZERO; | |
64 | + } | |
65 | + | |
66 | + @Override | |
67 | + @Transactional | |
68 | + public boolean insertBatch(List<TkDeviceTaskCenterEntity> list) { | |
69 | + return insertBatch(list, list.size()); | |
70 | + } | |
71 | +} | ... | ... |
... | ... | @@ -17,68 +17,49 @@ import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
17 | 17 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
18 | 18 | import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; |
19 | 19 | import org.thingsboard.server.common.data.yunteng.dto.SysJobDTO; |
20 | -import org.thingsboard.server.common.data.yunteng.dto.task.TargetContentDTO; | |
21 | -import org.thingsboard.server.common.data.yunteng.dto.task.TaskExecuteTimeDTO; | |
22 | -import org.thingsboard.server.common.data.yunteng.dto.task.TaskTypeDTO; | |
23 | -import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
20 | +import org.thingsboard.server.common.data.yunteng.dto.task.*; | |
24 | 21 | import org.thingsboard.server.common.data.yunteng.enums.JobGroupEnum; |
22 | +import org.thingsboard.server.common.data.yunteng.enums.StatusEnum; | |
25 | 23 | import org.thingsboard.server.common.data.yunteng.enums.TargetTypeEnum; |
26 | 24 | import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; |
27 | 25 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
26 | +import org.thingsboard.server.dao.yunteng.entities.TkDeviceTaskCenterEntity; | |
28 | 27 | import org.thingsboard.server.dao.yunteng.entities.TkTaskCenterEntity; |
29 | -import org.thingsboard.server.dao.yunteng.mapper.TaskCenterMapper; | |
30 | -import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
31 | -import org.thingsboard.server.dao.yunteng.service.TkDeviceService; | |
32 | -import org.thingsboard.server.dao.yunteng.service.TkSysJobService; | |
33 | -import org.thingsboard.server.dao.yunteng.service.TkTaskCenterService; | |
28 | +import org.thingsboard.server.dao.yunteng.mapper.TkTaskCenterMapper; | |
29 | +import org.thingsboard.server.dao.yunteng.service.*; | |
34 | 30 | |
35 | 31 | import javax.transaction.Transactional; |
36 | 32 | import java.util.*; |
37 | -import java.util.stream.Collectors; | |
38 | 33 | |
39 | 34 | @Service |
40 | 35 | @RequiredArgsConstructor |
41 | 36 | @Slf4j |
42 | 37 | public class TkTaskCenterServiceImpl |
43 | - extends AbstractBaseService<TaskCenterMapper, TkTaskCenterEntity> | |
38 | + extends AbstractBaseService<TkTaskCenterMapper, TkTaskCenterEntity> | |
44 | 39 | implements TkTaskCenterService { |
45 | 40 | private final TkSysJobService tkSysJobService; |
46 | 41 | private final TkDeviceService tkDeviceService; |
47 | 42 | private final CacheUtils cacheUtils; |
43 | + private final TkDeviceTaskCenterService tkDeviceTaskCenterService; | |
48 | 44 | |
49 | 45 | @Override |
50 | 46 | public TkPageData<TkTaskCenterDTO> taskCenterPage(Map<String, Object> queryMap, String tenantId) { |
51 | - Integer state = (Integer) queryMap.get("state"); | |
52 | - TargetTypeEnum targetTypeEnum = (TargetTypeEnum) queryMap.get("targetType"); | |
47 | + queryMap.put("tenantId", tenantId); | |
53 | 48 | IPage<TkTaskCenterEntity> page = |
54 | 49 | getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); |
55 | - IPage<TkTaskCenterEntity> taskCenterIPage = | |
56 | - baseMapper.selectPage( | |
57 | - page, | |
58 | - new LambdaQueryWrapper<TkTaskCenterEntity>() | |
59 | - .eq(TkTaskCenterEntity::getTenantId, tenantId) | |
60 | - .eq(null != state, TkTaskCenterEntity::getState, state) | |
61 | - .eq(null != targetTypeEnum, TkTaskCenterEntity::getTargetType, targetTypeEnum)); | |
62 | - if (!taskCenterIPage.getRecords().isEmpty()) { | |
63 | - List<TkTaskCenterDTO> listRecords = | |
64 | - taskCenterIPage.getRecords().stream() | |
65 | - .map( | |
66 | - entity -> { | |
67 | - TkTaskCenterDTO dto = entity.getDTO(TkTaskCenterDTO.class); | |
68 | - dto.setExecuteContent( | |
69 | - JacksonUtil.convertValue(entity.getExecuteContent(), TaskTypeDTO.class)); | |
70 | - dto.setExecuteTime( | |
71 | - JacksonUtil.convertValue( | |
72 | - entity.getExecuteTime(), TaskExecuteTimeDTO.class)); | |
73 | - dto.setExecuteTarget( | |
74 | - JacksonUtil.convertValue( | |
75 | - entity.getExecuteTarget(), TargetContentDTO.class)); | |
76 | - return dto; | |
77 | - }) | |
78 | - .collect(Collectors.toList()); | |
79 | - return new TkPageData<>(listRecords, taskCenterIPage.getTotal()); | |
50 | + IPage<TkTaskCenterDTO> iPage = baseMapper.getPageData(page, queryMap); | |
51 | + if (!iPage.getRecords().isEmpty()) { | |
52 | + iPage.getRecords().stream() | |
53 | + .peek( | |
54 | + obj -> { | |
55 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
56 | + String key = | |
57 | + FastIotConstants.CacheConfigKey.TASK_CENTER_EXECUTE_TIME + "_" + obj.getId(); | |
58 | + Optional<Long> lastExecuteTime = cacheUtils.get(cacheName, key); | |
59 | + lastExecuteTime.ifPresent(obj::setLastExecuteTime); | |
60 | + }); | |
80 | 61 | } |
81 | - return getPageData(taskCenterIPage, TkTaskCenterDTO.class); | |
62 | + return new TkPageData<>(iPage.getRecords(), iPage.getTotal()); | |
82 | 63 | } |
83 | 64 | |
84 | 65 | @Override |
... | ... | @@ -90,7 +71,9 @@ public class TkTaskCenterServiceImpl |
90 | 71 | throw new TkDataValidationException(ErrorMessage.EXECUTE_COMMAND_IS_NULL.getMessage()); |
91 | 72 | } |
92 | 73 | TaskExecuteTimeDTO executeTime = tkTaskCenterDTO.getExecuteTime(); |
93 | - if (null == executeTime || StringUtils.isEmpty(executeTime.getCron())) { | |
74 | + if (null == executeTime | |
75 | + || StringUtils.isEmpty(executeTime.getCron()) | |
76 | + || !tkSysJobService.checkCronExpressionIsValid(executeTime.getCron())) { | |
94 | 77 | throw new TkDataValidationException(ErrorMessage.CRON_INVALID.getMessage()); |
95 | 78 | } |
96 | 79 | entity.setExecuteContent( |
... | ... | @@ -113,16 +96,18 @@ public class TkTaskCenterServiceImpl |
113 | 96 | baseMapper.updateById(entity); |
114 | 97 | updateTaskCenterCache(entity); |
115 | 98 | } |
99 | + saveOrUpdateDeviceTaskCenter(tkTaskCenterDTO); | |
116 | 100 | return tkTaskCenterDTO; |
117 | 101 | } |
118 | 102 | |
119 | 103 | @Override |
120 | 104 | @Transactional |
121 | 105 | public boolean deleteTaskCenter(DeleteDTO deleteDTO) throws SchedulerException { |
106 | + String tenantId = deleteDTO.getTenantId(); | |
122 | 107 | List<TkTaskCenterEntity> list = |
123 | 108 | baseMapper.selectList( |
124 | 109 | new LambdaQueryWrapper<TkTaskCenterEntity>() |
125 | - .eq(TkTaskCenterEntity::getTenantId, deleteDTO.getTenantId()) | |
110 | + .eq(TkTaskCenterEntity::getTenantId, tenantId) | |
126 | 111 | .in(TkTaskCenterEntity::getId, deleteDTO.getIds())); |
127 | 112 | if (null == list || list.isEmpty()) { |
128 | 113 | throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); |
... | ... | @@ -139,13 +124,15 @@ public class TkTaskCenterServiceImpl |
139 | 124 | } |
140 | 125 | int result = baseMapper.deleteBatchIds(sourceIds); |
141 | 126 | if (result > FastIotConstants.MagicNumber.ZERO) { |
142 | - return tkSysJobService.deleteJobs( | |
143 | - sourceIds, JobGroupEnum.TASK_CENTER.name(), deleteDTO.getTenantId()); | |
127 | + for (String taskCenterId : sourceIds) { | |
128 | + tkDeviceTaskCenterService.deleteByTaskCenterId(tenantId, taskCenterId); | |
129 | + } | |
130 | + return tkSysJobService.deleteJobs(sourceIds, JobGroupEnum.TASK_CENTER.name(), tenantId); | |
144 | 131 | } |
145 | 132 | // 移除任务中心缓存 |
146 | 133 | for (String taskCenterId : sourceIds) { |
147 | - String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + taskCenterId; | |
148 | - cacheUtils.invalidate(key); | |
134 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
135 | + cacheUtils.invalidate(cacheName, taskCenterId); | |
149 | 136 | } |
150 | 137 | return false; |
151 | 138 | } |
... | ... | @@ -180,8 +167,8 @@ public class TkTaskCenterServiceImpl |
180 | 167 | if (StringUtils.isEmpty(id)) { |
181 | 168 | throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); |
182 | 169 | } |
183 | - String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + id; | |
184 | - Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(key); | |
170 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
171 | + Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(cacheName, id); | |
185 | 172 | TkTaskCenterEntity entity = |
186 | 173 | entityCache.orElseGet( |
187 | 174 | () -> |
... | ... | @@ -200,7 +187,7 @@ public class TkTaskCenterServiceImpl |
200 | 187 | JacksonUtil.convertValue(object.getExecuteTime(), TaskExecuteTimeDTO.class)); |
201 | 188 | return Futures.immediateFuture(tkTaskCenterDTO); |
202 | 189 | }) |
203 | - .orElse(null); | |
190 | + .orElse(Futures.immediateFuture(new TkTaskCenterDTO())); | |
204 | 191 | } |
205 | 192 | |
206 | 193 | @Override |
... | ... | @@ -243,7 +230,8 @@ public class TkTaskCenterServiceImpl |
243 | 230 | |
244 | 231 | @Override |
245 | 232 | @Transactional |
246 | - public boolean cancelExecute(String id, String tbDeviceId, String tenantId) { | |
233 | + public boolean cancelOrAllowExecute( | |
234 | + String id, String tbDeviceId, String tenantId, boolean isAllow) { | |
247 | 235 | boolean result = false; |
248 | 236 | TkTaskCenterEntity entity = baseMapper.selectById(id); |
249 | 237 | if (entity != null) { |
... | ... | @@ -253,31 +241,21 @@ public class TkTaskCenterServiceImpl |
253 | 241 | TargetContentDTO targetContent = |
254 | 242 | JacksonUtil.convertValue(entity.getExecuteTarget(), TargetContentDTO.class); |
255 | 243 | if (null != targetContent) { |
256 | - // 按设备执行 | |
257 | - if (Objects.equals(entity.getTargetType(), TargetTypeEnum.DEVICES)) { | |
258 | - List<String> data = targetContent.getData(); | |
259 | - List<String> removeResult = new ArrayList<>(); | |
260 | - if (null != data && !data.isEmpty()) { | |
261 | - for (String deviceId : data) { | |
262 | - if (!Objects.equals(deviceId, tbDeviceId)) { | |
263 | - removeResult.add(deviceId); | |
264 | - } | |
265 | - } | |
266 | - targetContent.setData(removeResult); | |
267 | - } | |
244 | + // 查询设备信息 | |
245 | + DeviceDTO dto = tkDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId); | |
246 | + Map<String, List<String>> map = targetContent.getCancelExecuteDevices(); | |
247 | + if (isAllow) { | |
248 | + map.get(dto.getDeviceProfileId()).remove(tbDeviceId); | |
268 | 249 | } else { |
269 | - // 按产品执行 | |
270 | - Map<String, List<String>> map = targetContent.getCancelExecuteDevices(); | |
271 | - DeviceDTO deviceDTO = tkDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId); | |
272 | - for (String key : map.keySet()) { | |
273 | - if (Objects.equals(key, deviceDTO.getDeviceProfileId())) { | |
274 | - map.get(key).add(tbDeviceId); | |
275 | - break; | |
276 | - } | |
277 | - } | |
250 | + map.get(dto.getDeviceProfileId()).add(tbDeviceId); | |
278 | 251 | } |
279 | 252 | entity.setExecuteTarget(JacksonUtil.convertValue(targetContent, JsonNode.class)); |
280 | 253 | baseMapper.updateById(entity); |
254 | + tkDeviceTaskCenterService.updateStateByTbDeviceIdAndTaskCenterId( | |
255 | + tenantId, | |
256 | + id, | |
257 | + tbDeviceId, | |
258 | + isAllow ? StatusEnum.ENABLE.getIndex() : StatusEnum.DISABLE.getIndex()); | |
281 | 259 | updateTaskCenterCache(entity); |
282 | 260 | } |
283 | 261 | } |
... | ... | @@ -285,10 +263,50 @@ public class TkTaskCenterServiceImpl |
285 | 263 | } |
286 | 264 | |
287 | 265 | private void updateTaskCenterCache(TkTaskCenterEntity entity) { |
288 | - String key = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS + entity.getId(); | |
289 | - Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(key); | |
266 | + String cacheName = FastIotConstants.CacheConfigKey.TASK_CENTER_INFOS; | |
267 | + Optional<TkTaskCenterEntity> entityCache = cacheUtils.get(cacheName, entity.getId()); | |
290 | 268 | if (entityCache.isPresent()) { |
291 | - cacheUtils.put(key, entity); | |
269 | + cacheUtils.put(cacheName, entity.getId(), entity); | |
270 | + } | |
271 | + } | |
272 | + | |
273 | + private void saveOrUpdateDeviceTaskCenter(TkTaskCenterDTO tkTaskCenter) { | |
274 | + String taskCenterId = tkTaskCenter.getId(); | |
275 | + String tenantId = tkTaskCenter.getTenantId(); | |
276 | + // 判断是按产品执行还是按设备执行 | |
277 | + List<String> data = tkTaskCenter.getExecuteTarget().getData(); | |
278 | + boolean isUpdate = !StringUtils.isEmpty(taskCenterId); | |
279 | + if (Objects.equals(tkTaskCenter.getTargetType(), TargetTypeEnum.DEVICES)) { | |
280 | + processDeviceTaskCenterMapping(isUpdate, tenantId, taskCenterId, data); | |
281 | + } else { | |
282 | + for (String key : data) { | |
283 | + List<String> tbDeviceIds = tkDeviceService.findTbDeviceIdsByDeviceProfileId(key, tenantId); | |
284 | + processDeviceTaskCenterMapping(isUpdate, tenantId, taskCenterId, tbDeviceIds); | |
285 | + } | |
286 | + } | |
287 | + } | |
288 | + | |
289 | + private void processDeviceTaskCenterMapping( | |
290 | + boolean isUpdate, String tenantId, String taskCenterId, List<String> deviceIds) { | |
291 | + if (null != deviceIds && !deviceIds.isEmpty()) { | |
292 | + if (isUpdate) { | |
293 | + tkDeviceTaskCenterService.deleteByTaskCenterId(tenantId, taskCenterId); | |
294 | + } | |
295 | + insertBatchByTbDeviceIdsAndTaskCenterId(tenantId, taskCenterId, deviceIds); | |
296 | + } | |
297 | + } | |
298 | + | |
299 | + private void insertBatchByTbDeviceIdsAndTaskCenterId( | |
300 | + String tenantId, String taskCenterId, List<String> deviceIds) { | |
301 | + List<TkDeviceTaskCenterEntity> saveList = new ArrayList<>(); | |
302 | + for (String key : deviceIds) { | |
303 | + TkDeviceTaskCenterEntity entity = new TkDeviceTaskCenterEntity(); | |
304 | + entity.setTbDeviceId(key); | |
305 | + entity.setTaskCenterId(taskCenterId); | |
306 | + entity.setTenantId(tenantId); | |
307 | + entity.setState(StatusEnum.ENABLE.getIndex()); | |
308 | + saveList.add(entity); | |
292 | 309 | } |
310 | + tkDeviceTaskCenterService.insertBatch(saveList); | |
293 | 311 | } |
294 | 312 | } | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/mapper/TkDeviceTaskCenterMapper.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/yunteng/mapper/TaskCenterMapper.java
... | ... | @@ -2,8 +2,7 @@ package org.thingsboard.server.dao.yunteng.mapper; |
2 | 2 | |
3 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
4 | 4 | import org.apache.ibatis.annotations.Mapper; |
5 | -import org.thingsboard.server.dao.yunteng.entities.TkTaskCenterEntity; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.TkDeviceTaskCenterEntity; | |
6 | 6 | |
7 | 7 | @Mapper |
8 | -public interface TaskCenterMapper extends BaseMapper<TkTaskCenterEntity> { | |
9 | -} | |
8 | +public interface TkDeviceTaskCenterMapper extends BaseMapper<TkDeviceTaskCenterEntity> {} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage;import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.apache.ibatis.annotations.Param; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; | |
7 | +import org.thingsboard.server.dao.yunteng.entities.TkTaskCenterEntity; | |
8 | +import java.util.Map; | |
9 | + | |
10 | +@Mapper | |
11 | +public interface TkTaskCenterMapper extends BaseMapper<TkTaskCenterEntity> { | |
12 | + IPage<TkTaskCenterDTO> getPageData( | |
13 | + IPage<?> page, | |
14 | + @Param("queryMap")Map<String,Object> queryMap); | |
15 | +} | ... | ... |
... | ... | @@ -204,4 +204,12 @@ public interface TkDeviceService extends BaseService<TkDeviceEntity> { |
204 | 204 | List<String> rpcDevices(String tenantId,String organizationId,String projectId); |
205 | 205 | |
206 | 206 | ListenableFuture<List<DeviceDTO>> findDeviceListByDeviceProfileId(String deviceProfileId,String tenantId); |
207 | + | |
208 | + /** | |
209 | + * 通过设备配置ID查询所有的tbDeviceId | |
210 | + * @param deviceProfileId 设备配置ID | |
211 | + * @param tenantId 租户ID | |
212 | + * @return id集合 | |
213 | + */ | |
214 | + List<String> findTbDeviceIdsByDeviceProfileId(String deviceProfileId,String tenantId); | |
207 | 215 | } | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/service/TkDeviceTaskCenterService.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
4 | +import org.thingsboard.server.common.data.yunteng.dto.task.TkDeviceTaskCenterDTO; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.TkDeviceTaskCenterEntity; | |
6 | +import java.util.List; | |
7 | + | |
8 | +public interface TkDeviceTaskCenterService { | |
9 | + /** | |
10 | + * 新增或修改设备与任务中心的映射关系 | |
11 | + * | |
12 | + * @param tkDeviceTaskCenterDTO 映射信息 | |
13 | + * @return 映射信息 | |
14 | + */ | |
15 | + TkDeviceTaskCenterDTO saveOrUpdate(TkDeviceTaskCenterDTO tkDeviceTaskCenterDTO); | |
16 | + | |
17 | + /** | |
18 | + * 删除设备与任务中心的映射关系 | |
19 | + * | |
20 | + * @param delete 删除参数 | |
21 | + * @return true成功 false失败 | |
22 | + */ | |
23 | + boolean delete(DeleteDTO delete); | |
24 | + | |
25 | + /** | |
26 | + * 根据任务中心ID和设备ID更新状态 | |
27 | + * @param tenantId 租户ID | |
28 | + * @param taskCenterId 任务重ID | |
29 | + * @param tbDeviceId 设备ID | |
30 | + * @param state 状态 | |
31 | + * @return true成功 false失败 | |
32 | + */ | |
33 | + boolean updateStateByTbDeviceIdAndTaskCenterId(String tenantId,String taskCenterId,String tbDeviceId,Integer state); | |
34 | + | |
35 | + /** | |
36 | + * 通过任务ID删除所有的映射关系 | |
37 | + * @param tenantId 租户ID | |
38 | + * @param taskCenterId 任务ID | |
39 | + * @return true成功 false失败 | |
40 | + */ | |
41 | + boolean deleteByTaskCenterId(String tenantId,String taskCenterId); | |
42 | + | |
43 | + /** | |
44 | + * 批量插入 | |
45 | + * | |
46 | + * @param list 插入实体集合 | |
47 | + * @return true成功 false失败 | |
48 | + */ | |
49 | + boolean insertBatch(List<TkDeviceTaskCenterEntity> list); | |
50 | +} | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | |
3 | -import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
3 | +import com.google.common.util.concurrent.ListenableFuture;import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
4 | 4 | import org.thingsboard.server.common.data.yunteng.dto.SysJobLogDTO; |
5 | 5 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
6 | 6 | |
... | ... | @@ -46,4 +46,12 @@ public interface TkSysJobLogService |
46 | 46 | * 清空任务日志 |
47 | 47 | */ |
48 | 48 | boolean cleanJobLog(); |
49 | + | |
50 | + /** | |
51 | + * 根据任务ID获取任务日志执行的最新时间戳 | |
52 | + * @param jobId 任务ID | |
53 | + * @param jobGroup 任务分组 | |
54 | + * @return 最新时间戳 | |
55 | + */ | |
56 | + ListenableFuture<Long> findLastLogEndTimeByJobId(String jobId, String jobGroup); | |
49 | 57 | } | ... | ... |
1 | 1 | package org.thingsboard.server.dao.yunteng.service; |
2 | 2 | |
3 | -import com.google.common.util.concurrent.ListenableFuture;import org.quartz.SchedulerException; | |
3 | +import com.google.common.util.concurrent.ListenableFuture; | |
4 | +import org.quartz.SchedulerException; | |
4 | 5 | import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; |
5 | 6 | import org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO; |
6 | 7 | import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; |
... | ... | @@ -15,7 +16,6 @@ public interface TkTaskCenterService { |
15 | 16 | * @return 分页数据 |
16 | 17 | */ |
17 | 18 | TkPageData<TkTaskCenterDTO> taskCenterPage(Map<String, Object> queryMap, String tenantId); |
18 | - | |
19 | 19 | /** |
20 | 20 | * 修改或保存任务中心 |
21 | 21 | * |
... | ... | @@ -28,18 +28,20 @@ public interface TkTaskCenterService { |
28 | 28 | * |
29 | 29 | * @param deleteDTO 删除IDS |
30 | 30 | */ |
31 | - boolean deleteTaskCenter(DeleteDTO deleteDTO)throws SchedulerException; | |
31 | + boolean deleteTaskCenter(DeleteDTO deleteDTO) throws SchedulerException; | |
32 | 32 | |
33 | 33 | /** |
34 | 34 | * 根据任务中心ID,查询任务信息 |
35 | + * | |
35 | 36 | * @param id 任务中心ID |
36 | 37 | * @param tenantId 租户ID |
37 | 38 | * @return 任务信息 |
38 | 39 | */ |
39 | - TkTaskCenterDTO findTaskCenterInfoById(String id,String tenantId); | |
40 | + TkTaskCenterDTO findTaskCenterInfoById(String id, String tenantId); | |
40 | 41 | |
41 | 42 | /** |
42 | 43 | * 根据任务中心ID,异步查询任务信息 |
44 | + * | |
43 | 45 | * @param id 任务中心ID |
44 | 46 | * @return 任务信息 |
45 | 47 | */ |
... | ... | @@ -47,19 +49,22 @@ public interface TkTaskCenterService { |
47 | 49 | |
48 | 50 | /** |
49 | 51 | * 启用禁用任务中心 |
52 | + * | |
50 | 53 | * @param id 任务中心ID |
51 | 54 | * @param state 1启用 0禁用 |
52 | 55 | * @param tenantId 租户ID |
53 | 56 | * @return true成功 false失败 |
54 | 57 | */ |
55 | - boolean updateState(String id,Integer state,String tenantId)throws SchedulerException; | |
58 | + boolean updateState(String id, Integer state, String tenantId) throws SchedulerException; | |
56 | 59 | |
57 | 60 | /** |
58 | 61 | * 设备取消任务执行 |
62 | + * | |
59 | 63 | * @param id 任务ID |
60 | 64 | * @param tbDeviceId 设备ID |
61 | 65 | * @param tenantId 租户ID |
66 | + * @param isAllow true允许执行 false取消执行 | |
62 | 67 | * @return true成功 false失败 |
63 | 68 | */ |
64 | - boolean cancelExecute(String id,String tbDeviceId,String tenantId); | |
69 | + boolean cancelOrAllowExecute(String id, String tbDeviceId, String tenantId, boolean isAllow); | |
65 | 70 | } | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.TkTaskCenterMapper"> | |
5 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.task.TkTaskCenterDTO" id="dataMap"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="name" column="name"/> | |
8 | + <result property="targetType" column="target_type" typeHandler="org.apache.ibatis.type.EnumTypeHandler" /> | |
9 | + <result property="executeTarget" column="execute_target" | |
10 | + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> | |
11 | + <result property="executeContent" column="execute_content" | |
12 | + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> | |
13 | + <result property="executeTime" column="execute_time" | |
14 | + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> | |
15 | + <result property="createTime" column="create_time"/> | |
16 | + <result property="creator" column="creator"/> | |
17 | + <result property="updater" column="updater"/> | |
18 | + <result property="updateTime" column="update_time"/> | |
19 | + <result property="tenantId" column="tenant_id" /> | |
20 | + <association property="tkDeviceTaskCenter" javaType="org.thingsboard.server.common.data.yunteng.dto.task.TkDeviceTaskCenterDTO"> | |
21 | + <result property="state" column="state"/> | |
22 | + <result property="taskCenterId" column="task_center_id"/> | |
23 | + <result property="tbDeviceId" column="tb_device_id"/> | |
24 | + </association> | |
25 | + </resultMap> | |
26 | + | |
27 | + | |
28 | + | |
29 | + <sql id="basicColumns"> | |
30 | + tc.id,tc.name,tc.target_type,tc.execute_target,tc.execute_content,tc.execute_time,tc.create_time,tc.creator, | |
31 | + tc.updater,tc.update_time,tc.tenant_id | |
32 | + </sql> | |
33 | + | |
34 | + <sql id="detailColumns"> | |
35 | + <include refid="basicColumns"/> | |
36 | + ,tdc.state,tdc.task_center_id,tb_device_id | |
37 | + </sql> | |
38 | + <select id="getPageData" resultMap="dataMap"> | |
39 | + SELECT | |
40 | + <include refid="detailColumns"/> | |
41 | + FROM tk_task_center tc | |
42 | + LEFT JOIN tk_device_task_center tdc ON tc.id = tdc.task_center_id | |
43 | + <where> | |
44 | + <if test="queryMap.tenantId !=null and queryMap.tenantId !=''"> | |
45 | + AND tc.tenant_id = #{queryMap.tenantId} | |
46 | + </if> | |
47 | + <if test="queryMap.state !=null"> | |
48 | + AND tc.state = #{queryMap.state} | |
49 | + </if> | |
50 | + <if test="queryMap.targetType !=null"> | |
51 | + AND tc.target_type = #{queryMap.targetType} | |
52 | + </if> | |
53 | + <if test="queryMap.tbDeviceId !=null and queryMap.tbDeviceId !=''"> | |
54 | + AND tdc.tb_device_id = #{queryMap.tbDeviceId} | |
55 | + </if> | |
56 | + </where> | |
57 | + </select> | |
58 | +</mapper> | ... | ... |