Commit ecf6a4a8463d416dc5a6b8b1d143458f4b98dd89
1 parent
4749d93d
feat:【IoT 物联网】增加 OTA 升级任务的实现
Showing
23 changed files
with
277 additions
and
448 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaTaskRecordController.java
| ... | ... | @@ -9,12 +9,16 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; |
| 9 | 9 | import cn.iocoder.yudao.module.iot.service.ota.IotOtaTaskRecordService; |
| 10 | 10 | import io.swagger.v3.oas.annotations.Operation; |
| 11 | 11 | import io.swagger.v3.oas.annotations.Parameter; |
| 12 | +import io.swagger.v3.oas.annotations.Parameters; | |
| 12 | 13 | import io.swagger.v3.oas.annotations.tags.Tag; |
| 13 | 14 | import jakarta.annotation.Resource; |
| 14 | 15 | import jakarta.validation.Valid; |
| 15 | 16 | import org.springframework.security.access.prepost.PreAuthorize; |
| 16 | 17 | import org.springframework.validation.annotation.Validated; |
| 17 | -import org.springframework.web.bind.annotation.*; | |
| 18 | +import org.springframework.web.bind.annotation.GetMapping; | |
| 19 | +import org.springframework.web.bind.annotation.RequestMapping; | |
| 20 | +import org.springframework.web.bind.annotation.RequestParam; | |
| 21 | +import org.springframework.web.bind.annotation.RestController; | |
| 18 | 22 | |
| 19 | 23 | import java.util.Map; |
| 20 | 24 | |
| ... | ... | @@ -22,31 +26,29 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 22 | 26 | |
| 23 | 27 | @Tag(name = "管理后台 - IoT OTA 升级任务记录") |
| 24 | 28 | @RestController |
| 25 | -@RequestMapping("/iot/ota/task-record") | |
| 29 | +@RequestMapping("/iot/ota/task/record") | |
| 26 | 30 | @Validated |
| 27 | 31 | public class IotOtaTaskRecordController { |
| 28 | 32 | |
| 29 | 33 | @Resource |
| 30 | 34 | private IotOtaTaskRecordService otaTaskRecordService; |
| 31 | 35 | |
| 32 | - @GetMapping("/get-statistics") | |
| 33 | - @Operation(summary = "固件升级设备统计") | |
| 36 | + @GetMapping("/get-status-count") | |
| 37 | + @Operation(summary = "获得 OTA 升级记录状态统计") | |
| 38 | + @Parameters({ | |
| 39 | + @Parameter(name = "firmwareId", description = "固件编号", example = "1024"), | |
| 40 | + @Parameter(name = "taskId", description = "升级任务编号", example = "2048") | |
| 41 | + }) | |
| 34 | 42 | @PreAuthorize("@ss.hasPermission('iot:ota-task-record:query')") |
| 35 | - @Parameter(name = "firmwareId", description = "固件编号", required = true, example = "1024") | |
| 36 | - public CommonResult<Map<Integer, Long>> getOtaTaskRecordStatistics(@RequestParam(value = "firmwareId") Long firmwareId) { | |
| 37 | - return success(otaTaskRecordService.getOtaTaskRecordStatistics(firmwareId)); | |
| 38 | - } | |
| 39 | - | |
| 40 | - @GetMapping("/get-count") | |
| 41 | - @Operation(summary = "获得升级记录分页 tab 数量") | |
| 42 | - @PreAuthorize("@ss.hasPermission('iot:ota-task-record:query')") | |
| 43 | - public CommonResult<Map<Integer, Long>> getOtaTaskRecordCount(@Valid IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 44 | - return success(otaTaskRecordService.getOtaTaskRecordCount(pageReqVO)); | |
| 43 | + public CommonResult<Map<Integer, Long>> getOtaTaskRecordStatusCountMap( | |
| 44 | + @RequestParam(value = "firmwareId", required = false) Long firmwareId, | |
| 45 | + @RequestParam(value = "taskId", required = false) Long taskId) { | |
| 46 | + return success(otaTaskRecordService.getOtaTaskRecordStatusCountMap(firmwareId, taskId)); | |
| 45 | 47 | } |
| 46 | 48 | |
| 47 | 49 | @GetMapping("/page") |
| 48 | - @Operation(summary = "获得升级记录分页") | |
| 49 | - @PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')") | |
| 50 | + @Operation(summary = "获得 OTA 升级记录分页") | |
| 51 | + @PreAuthorize("@ss.hasPermission('iot:ota-task-record:query')") | |
| 50 | 52 | public CommonResult<PageResult<IotOtaTaskRecordRespVO>> getOtaTaskRecordPage( |
| 51 | 53 | @Valid IotOtaTaskRecordPageReqVO pageReqVO) { |
| 52 | 54 | PageResult<IotOtaTaskRecordDO> pageResult = otaTaskRecordService.getOtaTaskRecordPage(pageReqVO); |
| ... | ... | @@ -54,8 +56,8 @@ public class IotOtaTaskRecordController { |
| 54 | 56 | } |
| 55 | 57 | |
| 56 | 58 | @GetMapping("/get") |
| 57 | - @Operation(summary = "获得升级记录") | |
| 58 | - @PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')") | |
| 59 | + @Operation(summary = "获得 OTA 升级记录") | |
| 60 | + @PreAuthorize("@ss.hasPermission('iot:ota-task-record:query')") | |
| 59 | 61 | @Parameter(name = "id", description = "升级记录编号", required = true, example = "1024") |
| 60 | 62 | public CommonResult<IotOtaTaskRecordRespVO> getOtaTaskRecord(@RequestParam("id") Long id) { |
| 61 | 63 | IotOtaTaskRecordDO upgradeRecord = otaTaskRecordService.getOtaTaskRecord(id); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/task/IotOtaTaskCreateReqVO.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/task/record/IotOtaTaskRecordPageReqVO.java
| ... | ... | @@ -2,19 +2,16 @@ package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageParam; |
| 4 | 4 | import io.swagger.v3.oas.annotations.media.Schema; |
| 5 | -import jakarta.validation.constraints.NotNull; | |
| 6 | 5 | import lombok.Data; |
| 7 | 6 | |
| 8 | 7 | @Schema(description = "管理后台 - IoT OTA 升级记录分页 Request VO") |
| 9 | 8 | @Data |
| 10 | 9 | public class IotOtaTaskRecordPageReqVO extends PageParam { |
| 11 | 10 | |
| 12 | - // TODO @芋艿:分页条件字段梳理; | |
| 13 | - @Schema(description = "升级任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 14 | - @NotNull(message = "升级任务编号不能为空") | |
| 11 | + @Schema(description = "升级任务编号", example = "1024") | |
| 15 | 12 | private Long taskId; |
| 16 | 13 | |
| 17 | - @Schema(description = "设备标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "摄像头A1-1") | |
| 14 | + @Schema(description = "设备标识", example = "摄像头A1-1") | |
| 18 | 15 | private String deviceName; |
| 19 | 16 | |
| 20 | 17 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/task/record/IotOtaTaskRecordRespVO.java
| ... | ... | @@ -3,8 +3,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record; |
| 3 | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | 4 | import lombok.Data; |
| 5 | 5 | |
| 6 | -import java.time.LocalDateTime; | |
| 7 | - | |
| 8 | 6 | @Schema(description = "管理后台 - IoT OTA 升级记录 Response VO") |
| 9 | 7 | @Data |
| 10 | 8 | public class IotOtaTaskRecordRespVO { |
| ... | ... | @@ -23,12 +21,6 @@ public class IotOtaTaskRecordRespVO { |
| 23 | 21 | @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 24 | 22 | private Long taskId; |
| 25 | 23 | |
| 26 | - @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "iot") | |
| 27 | - private String productKey; | |
| 28 | - | |
| 29 | - @Schema(description = "设备名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "iot") | |
| 30 | - private String deviceName; | |
| 31 | - | |
| 32 | 24 | @Schema(description = "设备编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") |
| 33 | 25 | private String deviceId; |
| 34 | 26 | |
| ... | ... | @@ -47,10 +39,4 @@ public class IotOtaTaskRecordRespVO { |
| 47 | 39 | @Schema(description = "升级进度描述", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 48 | 40 | private String description; |
| 49 | 41 | |
| 50 | - @Schema(description = "升级开始时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 51 | - private LocalDateTime startTime; | |
| 52 | - | |
| 53 | - @Schema(description = "升级结束时间", requiredMode = Schema.RequiredMode.REQUIRED) | |
| 54 | - private LocalDateTime endTime; | |
| 55 | - | |
| 56 | 42 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceDO.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/ota/IotOtaTaskDO.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/ota/IotOtaTaskRecordDO.java
| ... | ... | @@ -7,9 +7,10 @@ import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskRecordStatusEnum; |
| 7 | 7 | import com.baomidou.mybatisplus.annotation.KeySequence; |
| 8 | 8 | import com.baomidou.mybatisplus.annotation.TableId; |
| 9 | 9 | import com.baomidou.mybatisplus.annotation.TableName; |
| 10 | -import lombok.*; | |
| 11 | - | |
| 12 | -import java.time.LocalDateTime; | |
| 10 | +import lombok.AllArgsConstructor; | |
| 11 | +import lombok.Builder; | |
| 12 | +import lombok.Data; | |
| 13 | +import lombok.NoArgsConstructor; | |
| 13 | 14 | |
| 14 | 15 | /** |
| 15 | 16 | * IoT OTA 升级任务记录 DO |
| ... | ... | @@ -70,13 +71,5 @@ public class IotOtaTaskRecordDO extends BaseDO { |
| 70 | 71 | * 如果想看历史记录,可以查看 {@link IotDeviceMessageDO} 设备日志 |
| 71 | 72 | */ |
| 72 | 73 | private String description; |
| 73 | - /** | |
| 74 | - * 升级开始时间 | |
| 75 | - */ | |
| 76 | - private LocalDateTime startTime; | |
| 77 | - /** | |
| 78 | - * 升级结束时间 | |
| 79 | - */ | |
| 80 | - private LocalDateTime endTime; | |
| 81 | 74 | |
| 82 | 75 | } |
| 83 | 76 | \ No newline at end of file | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/ota/IotOtaFirmwareMapper.java
| ... | ... | @@ -7,20 +7,11 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwa |
| 7 | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO; |
| 8 | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | |
| 10 | -import java.util.List; | |
| 11 | - | |
| 12 | 10 | @Mapper |
| 13 | 11 | public interface IotOtaFirmwareMapper extends BaseMapperX<IotOtaFirmwareDO> { |
| 14 | 12 | |
| 15 | - /** | |
| 16 | - * 根据产品ID和固件版本号查询固件信息列表。 | |
| 17 | - * | |
| 18 | - * @param productId 产品ID,用于筛选固件信息。 | |
| 19 | - * @param version 固件版本号,用于筛选固件信息。 | |
| 20 | - * @return 返回符合条件的固件信息列表。 | |
| 21 | - */ | |
| 22 | - default List<IotOtaFirmwareDO> selectByProductIdAndVersion(Long productId, String version) { | |
| 23 | - return selectList(IotOtaFirmwareDO::getProductId, productId, | |
| 13 | + default IotOtaFirmwareDO selectByProductIdAndVersion(Long productId, String version) { | |
| 14 | + return selectOne(IotOtaFirmwareDO::getProductId, productId, | |
| 24 | 15 | IotOtaFirmwareDO::getVersion, version); |
| 25 | 16 | } |
| 26 | 17 | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/ota/IotOtaTaskMapper.java
| ... | ... | @@ -7,20 +7,12 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.IotOtaTaskPageRe |
| 7 | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskDO; |
| 8 | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | |
| 10 | -import java.util.List; | |
| 11 | - | |
| 12 | -/** | |
| 13 | - * OTA 升级任务 Mapper | |
| 14 | - * | |
| 15 | - * @author Shelly | |
| 16 | - */ | |
| 17 | 10 | @Mapper |
| 18 | 11 | public interface IotOtaTaskMapper extends BaseMapperX<IotOtaTaskDO> { |
| 19 | 12 | |
| 20 | - default List<IotOtaTaskDO> selectByFirmwareIdAndName(Long firmwareId, String name) { | |
| 21 | - return selectList(new LambdaQueryWrapperX<IotOtaTaskDO>() | |
| 22 | - .eqIfPresent(IotOtaTaskDO::getFirmwareId, firmwareId) | |
| 23 | - .eqIfPresent(IotOtaTaskDO::getName, name)); | |
| 13 | + default IotOtaTaskDO selectByFirmwareIdAndName(Long firmwareId, String name) { | |
| 14 | + return selectOne(IotOtaTaskDO::getFirmwareId, firmwareId, | |
| 15 | + IotOtaTaskDO::getName, name); | |
| 24 | 16 | } |
| 25 | 17 | |
| 26 | 18 | default PageResult<IotOtaTaskDO> selectUpgradeTaskPage(IotOtaTaskPageReqVO pageReqVO) { | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/ota/IotOtaTaskRecordMapper.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.dal.mysql.ota; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | +import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record.IotOtaTaskRecordPageReqVO; | |
| 7 | +import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; | |
| 8 | +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 9 | +import org.apache.ibatis.annotations.Mapper; | |
| 10 | + | |
| 11 | +import java.util.List; | |
| 12 | +import java.util.Set; | |
| 13 | + | |
| 14 | +@Mapper | |
| 15 | +public interface IotOtaTaskRecordMapper extends BaseMapperX<IotOtaTaskRecordDO> { | |
| 16 | + | |
| 17 | + default List<IotOtaTaskRecordDO> selectListByFirmwareIdAndTaskId(Long firmwareId, Long taskId) { | |
| 18 | + return selectList(new LambdaQueryWrapperX<IotOtaTaskRecordDO>() | |
| 19 | + .eqIfPresent(IotOtaTaskRecordDO::getFirmwareId, firmwareId) | |
| 20 | + .eqIfPresent(IotOtaTaskRecordDO::getTaskId, taskId) | |
| 21 | + .select(IotOtaTaskRecordDO::getDeviceId, IotOtaTaskRecordDO::getStatus)); | |
| 22 | + } | |
| 23 | + | |
| 24 | + default PageResult<IotOtaTaskRecordDO> selectPage(IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 25 | + return selectPage(pageReqVO, new LambdaQueryWrapperX<IotOtaTaskRecordDO>() | |
| 26 | + .eqIfPresent(IotOtaTaskRecordDO::getTaskId, pageReqVO.getTaskId())); | |
| 27 | + } | |
| 28 | + | |
| 29 | + default void updateByTaskIdAndStatus(Long taskId, Integer fromStatus, IotOtaTaskRecordDO updateRecord) { | |
| 30 | + update(updateRecord, new LambdaUpdateWrapper<IotOtaTaskRecordDO>() | |
| 31 | + .eq(IotOtaTaskRecordDO::getTaskId, taskId) | |
| 32 | + .eq(IotOtaTaskRecordDO::getStatus, fromStatus)); | |
| 33 | + } | |
| 34 | + | |
| 35 | + default List<IotOtaTaskRecordDO> selectListByDeviceIdAndStatus(Set<Long> deviceIds, Set<Integer> statuses) { | |
| 36 | + return selectList(new LambdaQueryWrapperX<IotOtaTaskRecordDO>() | |
| 37 | + .inIfPresent(IotOtaTaskRecordDO::getDeviceId, deviceIds) | |
| 38 | + .inIfPresent(IotOtaTaskRecordDO::getStatus, statuses)); | |
| 39 | + } | |
| 40 | + | |
| 41 | +} | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/ota/IotOtaUpgradeRecordMapper.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.dal.mysql.ota; | |
| 2 | - | |
| 3 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | |
| 4 | -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; | |
| 5 | -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | |
| 6 | -import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record.IotOtaTaskRecordPageReqVO; | |
| 7 | -import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; | |
| 8 | -import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; | |
| 9 | -import org.apache.ibatis.annotations.Mapper; | |
| 10 | -import org.apache.ibatis.annotations.Param; | |
| 11 | -import org.apache.ibatis.annotations.Select; | |
| 12 | - | |
| 13 | -import java.util.List; | |
| 14 | -import java.util.Map; | |
| 15 | - | |
| 16 | -@Mapper | |
| 17 | -public interface IotOtaUpgradeRecordMapper extends BaseMapperX<IotOtaTaskRecordDO> { | |
| 18 | - | |
| 19 | - // TODO @li:selectByFirmwareIdAndTaskIdAndDeviceId;让方法自解释 | |
| 20 | - /** | |
| 21 | - * 根据条件查询单个OTA升级记录 | |
| 22 | - * | |
| 23 | - * @param firmwareId 固件ID,可选参数,用于筛选固件ID匹配的记录 | |
| 24 | - * @param taskId 任务ID,可选参数,用于筛选任务ID匹配的记录 | |
| 25 | - * @param deviceId 设备ID,可选参数,用于筛选设备ID匹配的记录 | |
| 26 | - * @return 返回符合条件的单个OTA升级记录,如果不存在则返回null | |
| 27 | - */ | |
| 28 | - default IotOtaTaskRecordDO selectByConditions(Long firmwareId, Long taskId, String deviceId) { | |
| 29 | - // 使用LambdaQueryWrapperX构建查询条件,根据传入的参数动态添加查询条件 | |
| 30 | - return selectOne(new LambdaQueryWrapperX<IotOtaTaskRecordDO>() | |
| 31 | - .eqIfPresent(IotOtaTaskRecordDO::getFirmwareId, firmwareId) | |
| 32 | - .eqIfPresent(IotOtaTaskRecordDO::getTaskId, taskId) | |
| 33 | - .eqIfPresent(IotOtaTaskRecordDO::getDeviceId, deviceId)); | |
| 34 | - } | |
| 35 | - | |
| 36 | - // TODO @li:这个是不是 groupby status 就 ok 拉? | |
| 37 | - /** | |
| 38 | - * 根据任务ID和设备名称查询OTA升级记录的状态统计信息。 | |
| 39 | - * 该函数通过SQL查询统计不同状态(0到5)的记录数量,并返回一个包含统计结果的Map列表。 | |
| 40 | - * | |
| 41 | - * @param taskId 任务ID,用于筛选特定任务的OTA升级记录。 | |
| 42 | - * @param deviceName 设备名称,支持模糊查询,用于筛选特定设备的OTA升级记录。 | |
| 43 | - * @return 返回一个Map列表,每个Map包含不同状态(0到5)的记录数量。 | |
| 44 | - */ | |
| 45 | - @Select("select count(case when status = 0 then 1 else 0) as `0` " + | |
| 46 | - "count(case when status = 1 then 1 else 0) as `1` " + | |
| 47 | - "count(case when status = 2 then 1 else 0) as `2` " + | |
| 48 | - "count(case when status = 3 then 1 else 0) as `3` " + | |
| 49 | - "count(case when status = 4 then 1 else 0) as `4` " + | |
| 50 | - "count(case when status = 5 then 1 else 0) as `5` " + | |
| 51 | - "from iot_ota_upgrade_record " + | |
| 52 | - "where task_id = #{taskId} " + | |
| 53 | - "and device_name like concat('%', #{deviceName}, '%') " + | |
| 54 | - "and status = #{status}") | |
| 55 | - List<Map<String, Object>> selectOtaUpgradeRecordCount(@Param("taskId") Long taskId, | |
| 56 | - @Param("deviceName") String deviceName); | |
| 57 | - | |
| 58 | - /** | |
| 59 | - * 根据固件ID查询OTA升级记录的状态统计信息。 | |
| 60 | - * 该函数通过SQL查询统计不同状态(0到5)的记录数量,并返回一个包含统计结果的Map列表。 | |
| 61 | - * | |
| 62 | - * @param firmwareId 固件ID,用于筛选特定固件的OTA升级记录。 | |
| 63 | - * @return 返回一个Map列表,每个Map包含不同状态(0到5)的记录数量。 | |
| 64 | - */ | |
| 65 | - @Select("select count(case when status = 0 then 1 else 0) as `0` " + | |
| 66 | - "count(case when status = 1 then 1 else 0) as `1` " + | |
| 67 | - "count(case when status = 2 then 1 else 0) as `2` " + | |
| 68 | - "count(case when status = 3 then 1 else 0) as `3` " + | |
| 69 | - "count(case when status = 4 then 1 else 0) as `4` " + | |
| 70 | - "count(case when status = 5 then 1 else 0) as `5` " + | |
| 71 | - "from iot_ota_upgrade_record " + | |
| 72 | - "where firmware_id = #{firmwareId}") | |
| 73 | - List<Map<String, Object>> selectOtaUpgradeRecordStatistics(Long firmwareId); | |
| 74 | - | |
| 75 | - // TODO @li:这里的注释,可以去掉哈 | |
| 76 | - /** | |
| 77 | - * 根据分页查询条件获取 OTA升级记录的分页结果 | |
| 78 | - * | |
| 79 | - * @param pageReqVO 分页查询请求参数,包含设备名称、任务ID等查询条件 | |
| 80 | - * @return 返回分页查询结果,包含符合条件的 OTA升级记录列表 | |
| 81 | - */ | |
| 82 | - // TODO @li:selectPage 就 ok 拉。 | |
| 83 | - default PageResult<IotOtaTaskRecordDO> selectUpgradeRecordPage(IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 84 | - // TODO @li:这里的注释,可以去掉哈;然后下面的“如果”。。。也没必要注释 | |
| 85 | - // 使用LambdaQueryWrapperX构建查询条件,并根据请求参数动态添加查询条件 | |
| 86 | - return selectPage(pageReqVO, new LambdaQueryWrapperX<IotOtaTaskRecordDO>() | |
| 87 | -// .likeIfPresent(IotOtaTaskRecordDO::getDeviceName, pageReqVO.getDeviceName()) // 如果设备名称存在,则添加模糊查询条件 | |
| 88 | - .eqIfPresent(IotOtaTaskRecordDO::getTaskId, pageReqVO.getTaskId())); // 如果任务ID存在,则添加等值查询条件 | |
| 89 | - } | |
| 90 | - | |
| 91 | - // TODO @li:这里的注释,可以去掉哈 | |
| 92 | - /** | |
| 93 | - * 根据任务ID和状态更新升级记录的状态 | |
| 94 | - * <p> | |
| 95 | - * 该函数用于将符合指定任务ID和状态的升级记录的状态更新为新的状态。 | |
| 96 | - * | |
| 97 | - * @param setStatus 要设置的新状态值,类型为Integer | |
| 98 | - * @param taskId 要更新的升级记录对应的任务ID,类型为Long | |
| 99 | - * @param whereStatus 用于筛选升级记录的当前状态值,类型为Integer | |
| 100 | - */ | |
| 101 | - // TODO @li:改成 updateByTaskIdAndStatus(taskId, status, IotOtaUpgradeRecordDO) 更通用一些。 | |
| 102 | - default void updateUpgradeRecordStatusByTaskIdAndStatus(Integer setStatus, Long taskId, Integer whereStatus) { | |
| 103 | - // 使用LambdaUpdateWrapper构建更新条件,将指定状态的记录更新为指定状态 | |
| 104 | - update(new LambdaUpdateWrapper<IotOtaTaskRecordDO>() | |
| 105 | - .set(IotOtaTaskRecordDO::getStatus, setStatus) | |
| 106 | - .eq(IotOtaTaskRecordDO::getTaskId, taskId) | |
| 107 | - .eq(IotOtaTaskRecordDO::getStatus, whereStatus) | |
| 108 | - ); | |
| 109 | - } | |
| 110 | - | |
| 111 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/DictTypeConstants.java
| ... | ... | @@ -16,4 +16,7 @@ public class DictTypeConstants { |
| 16 | 16 | |
| 17 | 17 | public static final String ALERT_LEVEL = "iot_alert_level"; |
| 18 | 18 | |
| 19 | + public static final String OTA_TASK_DEVICE_SCOPE = "iot_ota_task_device_scope"; | |
| 20 | + public static final String OTA_TASK_STATUS = "iot_ota_task_status"; | |
| 21 | + | |
| 19 | 22 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
| ... | ... | @@ -41,20 +41,25 @@ public interface ErrorCodeConstants { |
| 41 | 41 | ErrorCode DEVICE_GROUP_NOT_EXISTS = new ErrorCode(1_050_005_000, "设备分组不存在"); |
| 42 | 42 | ErrorCode DEVICE_GROUP_DELETE_FAIL_DEVICE_EXISTS = new ErrorCode(1_050_005_001, "设备分组下存在设备,不允许删除"); |
| 43 | 43 | |
| 44 | - // ========== 固件相关 1-050-008-000 ========== | |
| 44 | + // ========== OTA 固件相关 1-050-008-000 ========== | |
| 45 | 45 | |
| 46 | 46 | ErrorCode OTA_FIRMWARE_NOT_EXISTS = new ErrorCode(1_050_008_000, "固件信息不存在"); |
| 47 | 47 | ErrorCode OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE = new ErrorCode(1_050_008_001, "产品版本号重复"); |
| 48 | 48 | |
| 49 | - ErrorCode OTA_UPGRADE_TASK_NOT_EXISTS = new ErrorCode(1_050_008_100, "升级任务不存在"); | |
| 50 | - ErrorCode OTA_UPGRADE_TASK_NAME_DUPLICATE = new ErrorCode(1_050_008_101, "升级任务名称重复"); | |
| 51 | - ErrorCode OTA_UPGRADE_TASK_DEVICE_IDS_EMPTY = new ErrorCode(1_050_008_102, "设备编号列表不能为空"); | |
| 52 | - ErrorCode OTA_UPGRADE_TASK_DEVICE_LIST_EMPTY = new ErrorCode(1_050_008_103, "设备列表不能为空"); | |
| 53 | - ErrorCode OTA_UPGRADE_TASK_CANNOT_CANCEL = new ErrorCode(1_050_008_104, "升级任务不能取消"); | |
| 49 | + // ========== OTA 升级任务相关 1-050-008-100 ========== | |
| 54 | 50 | |
| 55 | - ErrorCode OTA_UPGRADE_RECORD_NOT_EXISTS = new ErrorCode(1_050_008_200, "升级记录不存在"); | |
| 56 | - ErrorCode OTA_UPGRADE_RECORD_DUPLICATE = new ErrorCode(1_050_008_201, "升级记录重复"); | |
| 57 | - ErrorCode OTA_UPGRADE_RECORD_CANNOT_RETRY = new ErrorCode(1_050_008_202, "升级记录不能重试"); | |
| 51 | + ErrorCode OTA_TASK_NOT_EXISTS = new ErrorCode(1_050_008_100, "升级任务不存在"); | |
| 52 | + ErrorCode OTA_TASK_CREATE_FAIL_NAME_DUPLICATE = new ErrorCode(1_050_008_101, "创建 OTA 任务失败,原因:任务名称重复"); | |
| 53 | + ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_FIRMWARE_EXISTS = new ErrorCode(1_050_008_102, | |
| 54 | + "创建 OTA 任务失败,原因:设备({})已经是该固件版本"); | |
| 55 | + ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_OTA_IN_PROCESS = new ErrorCode(1_050_008_102, | |
| 56 | + "创建 OTA 任务失败,原因:设备({})已经在升级中..."); | |
| 57 | + ErrorCode OTA_TASK_CREATE_FAIL_DEVICE_EMPTY = new ErrorCode(1_050_008_103, "创建 OTA 任务失败,原因:没有可升级的设备"); | |
| 58 | + ErrorCode OTA_TASK_CANCEL_FAIL_STATUS_END = new ErrorCode(1_050_008_104, "取消 OTA 任务失败,原因:任务状态不是进行中"); | |
| 59 | + | |
| 60 | + // ========== OTA 升级任务相关 1-050-008-100 ========== | |
| 61 | + | |
| 62 | + ErrorCode OTA_TASK_RECORD_NOT_EXISTS = new ErrorCode(1_050_008_200, "升级记录不存在"); | |
| 58 | 63 | |
| 59 | 64 | // ========== IoT 数据流转规则 1-050-010-000 ========== |
| 60 | 65 | ErrorCode DATA_RULE_NOT_EXISTS = new ErrorCode(1_050_010_000, "数据流转规则不存在"); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ota/IotOtaTaskRecordStatusEnum.java
| ... | ... | @@ -2,10 +2,13 @@ package cn.iocoder.yudao.module.iot.enums.ota; |
| 2 | 2 | |
| 3 | 3 | |
| 4 | 4 | import cn.iocoder.yudao.framework.common.core.ArrayValuable; |
| 5 | +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; | |
| 5 | 6 | import lombok.Getter; |
| 6 | 7 | import lombok.RequiredArgsConstructor; |
| 7 | 8 | |
| 8 | 9 | import java.util.Arrays; |
| 10 | +import java.util.List; | |
| 11 | +import java.util.Set; | |
| 9 | 12 | |
| 10 | 13 | /** |
| 11 | 14 | * IoT OTA 升级任务记录的状态枚举 |
| ... | ... | @@ -26,6 +29,17 @@ public enum IotOtaTaskRecordStatusEnum implements ArrayValuable<Integer> { |
| 26 | 29 | public static final Integer[] ARRAYS = Arrays.stream(values()) |
| 27 | 30 | .map(IotOtaTaskRecordStatusEnum::getStatus).toArray(Integer[]::new); |
| 28 | 31 | |
| 32 | + public static final Set<Integer> IN_PROCESS_STATUSES = SetUtils.asSet( | |
| 33 | + PENDING.getStatus(), | |
| 34 | + PUSHED.getStatus(), | |
| 35 | + UPGRADING.getStatus(), | |
| 36 | + SUCCESS.getStatus()); | |
| 37 | + | |
| 38 | + public static final List<Integer> PRIORITY_STATUSES = Arrays.asList( | |
| 39 | + SUCCESS.getStatus(), | |
| 40 | + PENDING.getStatus(), PUSHED.getStatus(), UPGRADING.getStatus(), | |
| 41 | + FAILURE.getStatus(), CANCELED.getStatus()); | |
| 42 | + | |
| 29 | 43 | /** |
| 30 | 44 | * 状态 |
| 31 | 45 | */ | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
| ... | ... | @@ -12,7 +12,6 @@ import java.time.LocalDateTime; |
| 12 | 12 | import java.util.Collection; |
| 13 | 13 | import java.util.List; |
| 14 | 14 | import java.util.Map; |
| 15 | -import java.util.Set; | |
| 16 | 15 | |
| 17 | 16 | /** |
| 18 | 17 | * IoT 设备 Service 接口 |
| ... | ... | @@ -155,22 +154,14 @@ public interface IotDeviceService { |
| 155 | 154 | List<IotDeviceDO> getDeviceListByState(Integer state); |
| 156 | 155 | |
| 157 | 156 | /** |
| 158 | - * 根据产品ID获取设备列表 | |
| 157 | + * 根据产品编号,获取设备列表 | |
| 159 | 158 | * |
| 160 | - * @param productId 产品ID,用于查询特定产品的设备列表 | |
| 161 | - * @return 返回与指定产品ID关联的设备列表,列表中的每个元素为IotDeviceDO对象 | |
| 159 | + * @param productId 产品编号 | |
| 160 | + * @return 设备列表 | |
| 162 | 161 | */ |
| 163 | 162 | List<IotDeviceDO> getDeviceListByProductId(Long productId); |
| 164 | 163 | |
| 165 | 164 | /** |
| 166 | - * 根据设备ID列表获取设备信息列表 | |
| 167 | - * | |
| 168 | - * @param deviceIdList 设备ID列表,包含需要查询的设备ID | |
| 169 | - * @return 返回与设备ID列表对应的设备信息列表,列表中的每个元素为IotDeviceDO对象 | |
| 170 | - */ | |
| 171 | - List<IotDeviceDO> getDeviceListByIdList(List<Long> deviceIdList); | |
| 172 | - | |
| 173 | - /** | |
| 174 | 165 | * 基于产品编号,获得设备数量 |
| 175 | 166 | * |
| 176 | 167 | * @param productId 产品编号 |
| ... | ... | @@ -248,6 +239,6 @@ public interface IotDeviceService { |
| 248 | 239 | * |
| 249 | 240 | * @param ids 设备编号数组 |
| 250 | 241 | */ |
| 251 | - void validateDevicesExist(Set<Long> ids); | |
| 242 | + List<IotDeviceDO> validateDeviceListExists(Collection<Long> ids); | |
| 252 | 243 | |
| 253 | 244 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| ... | ... | @@ -279,11 +279,6 @@ public class IotDeviceServiceImpl implements IotDeviceService { |
| 279 | 279 | } |
| 280 | 280 | |
| 281 | 281 | @Override |
| 282 | - public List<IotDeviceDO> getDeviceListByIdList(List<Long> deviceIdList) { | |
| 283 | - return deviceMapper.selectByIds(deviceIdList); | |
| 284 | - } | |
| 285 | - | |
| 286 | - @Override | |
| 287 | 282 | public void updateDeviceState(IotDeviceDO device, Integer state) { |
| 288 | 283 | // 1. 更新状态和时间 |
| 289 | 284 | IotDeviceDO updateObj = new IotDeviceDO().setId(device.getId()).setState(state); |
| ... | ... | @@ -474,14 +469,15 @@ public class IotDeviceServiceImpl implements IotDeviceService { |
| 474 | 469 | } |
| 475 | 470 | |
| 476 | 471 | @Override |
| 477 | - public void validateDevicesExist(Set<Long> ids) { | |
| 472 | + public List<IotDeviceDO> validateDeviceListExists(Collection<Long> ids) { | |
| 478 | 473 | if (CollUtil.isEmpty(ids)) { |
| 479 | - return; | |
| 474 | + return Collections.emptyList(); | |
| 480 | 475 | } |
| 481 | - List<IotDeviceDO> deviceIds = deviceMapper.selectByIds(ids); | |
| 482 | - if (deviceIds.size() != ids.size()) { | |
| 476 | + List<IotDeviceDO> devices = deviceMapper.selectByIds(ids); | |
| 477 | + if (devices.size() != ids.size()) { | |
| 483 | 478 | throw exception(DEVICE_NOT_EXISTS); |
| 484 | 479 | } |
| 480 | + return devices; | |
| 485 | 481 | } |
| 486 | 482 | |
| 487 | 483 | private IotDeviceServiceImpl getSelf() { | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaFirmwareService.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaFirmwareServiceImpl.java
| ... | ... | @@ -23,9 +23,14 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU |
| 23 | 23 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_FIRMWARE_NOT_EXISTS; |
| 24 | 24 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE; |
| 25 | 25 | |
| 26 | -@Slf4j | |
| 26 | +/** | |
| 27 | + * OTA 固件管理 Service 实现类 | |
| 28 | + * | |
| 29 | + * @author Shelly Chan | |
| 30 | + */ | |
| 27 | 31 | @Service |
| 28 | 32 | @Validated |
| 33 | +@Slf4j | |
| 29 | 34 | public class IotOtaFirmwareServiceImpl implements IotOtaFirmwareService { |
| 30 | 35 | |
| 31 | 36 | @Resource |
| ... | ... | @@ -37,7 +42,9 @@ public class IotOtaFirmwareServiceImpl implements IotOtaFirmwareService { |
| 37 | 42 | @Override |
| 38 | 43 | public Long createOtaFirmware(IotOtaFirmwareCreateReqVO saveReqVO) { |
| 39 | 44 | // 1.1 校验固件产品 + 版本号不能重复 |
| 40 | - validateProductAndVersionDuplicate(saveReqVO.getProductId(), saveReqVO.getVersion()); | |
| 45 | + if (otaFirmwareMapper.selectByProductIdAndVersion(saveReqVO.getProductId(), saveReqVO.getVersion()) != null) { | |
| 46 | + throw exception(OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE); | |
| 47 | + } | |
| 41 | 48 | // 1.2 校验产品存在 |
| 42 | 49 | productService.validateProductExists(saveReqVO.getProductId()); |
| 43 | 50 | |
| ... | ... | @@ -84,24 +91,11 @@ public class IotOtaFirmwareServiceImpl implements IotOtaFirmwareService { |
| 84 | 91 | } |
| 85 | 92 | |
| 86 | 93 | /** |
| 87 | - * 验证产品和版本号是否重复 | |
| 88 | - */ | |
| 89 | - private void validateProductAndVersionDuplicate(Long productId, String version) { | |
| 90 | - // 只查询1条记录检查是否存在 | |
| 91 | - IotOtaFirmwareDO firmware = otaFirmwareMapper.selectOne(IotOtaFirmwareDO::getProductId, productId, | |
| 92 | - IotOtaFirmwareDO::getVersion, version); | |
| 93 | - if (firmware != null) { | |
| 94 | - throw exception(OTA_FIRMWARE_PRODUCT_VERSION_DUPLICATE); | |
| 95 | - } | |
| 96 | - } | |
| 97 | - | |
| 98 | - /** | |
| 99 | 94 | * 计算文件签名 |
| 100 | - * | |
| 95 | + * | |
| 101 | 96 | * @param firmware 固件对象 |
| 102 | - * @throws Exception 下载或计算签名失败时抛出异常 | |
| 103 | 97 | */ |
| 104 | - private void calculateFileDigest(IotOtaFirmwareDO firmware) throws Exception { | |
| 98 | + private void calculateFileDigest(IotOtaFirmwareDO firmware) { | |
| 105 | 99 | String fileUrl = firmware.getFileUrl(); |
| 106 | 100 | // 下载文件并计算签名 |
| 107 | 101 | byte[] fileBytes = HttpUtil.downloadBytes(fileUrl); | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaTaskRecordService.java
| ... | ... | @@ -2,67 +2,67 @@ package cn.iocoder.yudao.module.iot.service.ota; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | 4 | import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record.IotOtaTaskRecordPageReqVO; |
| 5 | +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | |
| 5 | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; |
| 6 | 7 | import jakarta.validation.Valid; |
| 7 | 8 | |
| 8 | 9 | import java.util.List; |
| 9 | 10 | import java.util.Map; |
| 11 | +import java.util.Set; | |
| 10 | 12 | |
| 11 | -// TODO @li:注释写的有点冗余,可以看看别的模块哈。= = AI 生成的注释,有的时候太啰嗦了,需要处理下的哈 | |
| 12 | 13 | /** |
| 13 | - * IotOtaUpgradeRecordService 接口定义了与物联网设备OTA升级记录相关的操作。 | |
| 14 | - * 该接口提供了创建、更新、查询、统计和重试升级记录的功能。 | |
| 14 | + * IoT OTA 升级记录 Service 接口 | |
| 15 | 15 | */ |
| 16 | 16 | public interface IotOtaTaskRecordService { |
| 17 | 17 | |
| 18 | 18 | /** |
| 19 | 19 | * 批量创建 OTA 升级记录 |
| 20 | - * 该函数用于为指定的设备列表、固件ID和升级任务ID创建OTA升级记录。 | |
| 21 | 20 | * |
| 22 | - * @param deviceIds 设备ID列表,表示需要升级的设备集合。 | |
| 23 | - * @param firmwareId 固件ID,表示要升级到的固件版本。 | |
| 24 | - * @param upgradeTaskId 升级任务ID,表示此次升级任务的唯一标识。 | |
| 21 | + * @param devices 设备列表 | |
| 22 | + * @param firmwareId 固件编号 | |
| 23 | + * @param taskId 任务编号 | |
| 25 | 24 | */ |
| 26 | - void createOtaTaskRecordBatch(List<Long> deviceIds, Long firmwareId, Long upgradeTaskId); | |
| 25 | + void createOtaTaskRecordList(List<IotDeviceDO> devices, Long firmwareId, Long taskId); | |
| 27 | 26 | |
| 28 | 27 | /** |
| 29 | - * 获取 OTA 升级记录的数量统计 | |
| 28 | + * 获取 OTA 升级记录的状态统计 | |
| 30 | 29 | * |
| 31 | - * @return 返回一个 Map,其中键为状态码,值为对应状态的升级记录数量 | |
| 30 | + * @param firmwareId 固件编号 | |
| 31 | + * @param taskId 任务编号 | |
| 32 | + * @return 状态统计 Map,key 为状态码,value 为对应状态的升级记录数量 | |
| 32 | 33 | */ |
| 33 | - Map<Integer, Long> getOtaTaskRecordCount(@Valid IotOtaTaskRecordPageReqVO pageReqVO); | |
| 34 | + Map<Integer, Long> getOtaTaskRecordStatusCountMap(Long firmwareId, Long taskId); | |
| 34 | 35 | |
| 35 | 36 | /** |
| 36 | - * 获取 OTA 升级记录的统计信息 | |
| 37 | + * 获取 OTA 升级记录 | |
| 37 | 38 | * |
| 38 | - * @return 返回一个 Map,其中键为状态码,值为对应状态的升级记录统计信息 | |
| 39 | + * @param id 编号 | |
| 40 | + * @return OTA 升级记录 | |
| 39 | 41 | */ |
| 40 | - Map<Integer, Long> getOtaTaskRecordStatistics(Long firmwareId); | |
| 42 | + IotOtaTaskRecordDO getOtaTaskRecord(Long id); | |
| 41 | 43 | |
| 42 | 44 | /** |
| 43 | - * 获取指定 ID 的 OTA 升级记录的详细信息 | |
| 45 | + * 获取 OTA 升级记录分页 | |
| 44 | 46 | * |
| 45 | - * @param id 需要查询的升级记录的 ID | |
| 46 | - * @return 返回包含升级记录详细信息的响应对象 | |
| 47 | + * @param pageReqVO 分页查询 | |
| 48 | + * @return OTA 升级记录分页 | |
| 47 | 49 | */ |
| 48 | - IotOtaTaskRecordDO getOtaTaskRecord(Long id); | |
| 50 | + PageResult<IotOtaTaskRecordDO> getOtaTaskRecordPage(@Valid IotOtaTaskRecordPageReqVO pageReqVO); | |
| 49 | 51 | |
| 50 | 52 | /** |
| 51 | - * 分页查询 OTA 升级记录 | |
| 53 | + * 根据 OTA 任务编号,取消未结束的升级记录 | |
| 52 | 54 | * |
| 53 | - * @param pageReqVO 包含分页查询条件的请求对象,必须经过验证。 | |
| 54 | - * @return 返回包含分页查询结果的响应对象。 | |
| 55 | + * @param taskId 升级任务编号 | |
| 55 | 56 | */ |
| 56 | - PageResult<IotOtaTaskRecordDO> getOtaTaskRecordPage(@Valid IotOtaTaskRecordPageReqVO pageReqVO); | |
| 57 | + void cancelTaskRecordListByTaskId(Long taskId); | |
| 57 | 58 | |
| 58 | 59 | /** |
| 59 | - * 根据任务 ID 取消升级记录 | |
| 60 | - * <p> | |
| 61 | - * 该函数用于根据给定的任务ID,取消与该任务相关的升级记录。通常用于在任务执行失败或用户手动取消时, | |
| 62 | - * 清理或标记相关的升级记录为取消状态。 | |
| 60 | + * 根据设备编号和记录状态,获取 OTA 升级记录列表 | |
| 63 | 61 | * |
| 64 | - * @param taskId 要取消升级记录的任务ID。该ID唯一标识一个任务,通常由任务管理系统生成。 | |
| 62 | + * @param deviceIds 设备编号集合 | |
| 63 | + * @param statuses 记录状态集合 | |
| 64 | + * @return OTA 升级记录列表 | |
| 65 | 65 | */ |
| 66 | - void cancelUpgradeRecordByTaskId(Long taskId); | |
| 66 | + List<IotOtaTaskRecordDO> getOtaTaskRecordListByDeviceIdAndStatus(Set<Long> deviceIds, Set<Integer> statuses); | |
| 67 | 67 | |
| 68 | 68 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaTaskRecordServiceImpl.java
| ... | ... | @@ -2,177 +2,100 @@ package cn.iocoder.yudao.module.iot.service.ota; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.convert.Convert; |
| 4 | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; | |
| 6 | 5 | import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.record.IotOtaTaskRecordPageReqVO; |
| 7 | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 8 | -import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO; | |
| 9 | 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; |
| 10 | -import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskDO; | |
| 11 | -import cn.iocoder.yudao.module.iot.dal.mysql.ota.IotOtaUpgradeRecordMapper; | |
| 8 | +import cn.iocoder.yudao.module.iot.dal.mysql.ota.IotOtaTaskRecordMapper; | |
| 12 | 9 | import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskRecordStatusEnum; |
| 13 | -import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | |
| 14 | 10 | import jakarta.annotation.Resource; |
| 15 | 11 | import lombok.extern.slf4j.Slf4j; |
| 16 | 12 | import org.springframework.stereotype.Service; |
| 17 | -import org.springframework.transaction.annotation.Transactional; | |
| 18 | 13 | import org.springframework.validation.annotation.Validated; |
| 19 | 14 | |
| 15 | +import java.util.Arrays; | |
| 20 | 16 | import java.util.List; |
| 21 | 17 | import java.util.Map; |
| 22 | -import java.util.Objects; | |
| 23 | -import java.util.stream.Collectors; | |
| 18 | +import java.util.Set; | |
| 24 | 19 | |
| 25 | 20 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | -import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; | |
| 21 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; | |
| 22 | +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.OTA_TASK_RECORD_NOT_EXISTS; | |
| 27 | 23 | |
| 28 | -// TODO @li:@Service、@Validated、@Slf4j,先用关键注解;2)类注释,简单写 | |
| 29 | -@Slf4j | |
| 24 | +/** | |
| 25 | + * OTA 升级任务记录 Service 实现类 | |
| 26 | + */ | |
| 30 | 27 | @Service |
| 31 | 28 | @Validated |
| 29 | +@Slf4j | |
| 32 | 30 | public class IotOtaTaskRecordServiceImpl implements IotOtaTaskRecordService { |
| 33 | 31 | |
| 34 | 32 | @Resource |
| 35 | - private IotOtaUpgradeRecordMapper iotOtaUpgradeRecordMapper; | |
| 36 | - | |
| 37 | - @Resource | |
| 38 | - private IotDeviceService deviceService; | |
| 39 | - @Resource | |
| 40 | - private IotOtaFirmwareService firmwareService; | |
| 41 | - @Resource | |
| 42 | - private IotOtaTaskService upgradeTaskService; | |
| 33 | + private IotOtaTaskRecordMapper otaTaskRecordMapper; | |
| 43 | 34 | |
| 44 | 35 | @Override |
| 45 | - public void createOtaTaskRecordBatch(List<Long> deviceIds, Long firmwareId, Long upgradeTaskId) { | |
| 46 | - // 1. 校验升级记录信息是否存在,并且已经取消的任务可以重新开始 | |
| 47 | - deviceIds.forEach(deviceId -> validateUpgradeRecordDuplicate(firmwareId, upgradeTaskId, String.valueOf(deviceId))); | |
| 48 | - | |
| 49 | - // 2. 初始化OTA升级记录列表信息 | |
| 50 | - IotOtaTaskDO upgradeTask = upgradeTaskService.getOtaTask(upgradeTaskId); | |
| 51 | - IotOtaFirmwareDO firmware = firmwareService.getOtaFirmware(firmwareId); | |
| 52 | - List<IotDeviceDO> deviceList = deviceService.getDeviceListByIdList(deviceIds); | |
| 53 | - List<IotOtaTaskRecordDO> upgradeRecordList = deviceList.stream().map(device -> { | |
| 54 | - IotOtaTaskRecordDO upgradeRecord = new IotOtaTaskRecordDO(); | |
| 55 | - upgradeRecord.setFirmwareId(firmware.getId()); | |
| 56 | - upgradeRecord.setTaskId(upgradeTask.getId()); | |
| 57 | - upgradeRecord.setDeviceId(device.getId()); | |
| 58 | - upgradeRecord.setFromFirmwareId(Convert.toLong(device.getFirmwareId())); | |
| 59 | - upgradeRecord.setStatus(IotOtaTaskRecordStatusEnum.PENDING.getStatus()); | |
| 60 | - upgradeRecord.setProgress(0); | |
| 61 | - return upgradeRecord; | |
| 62 | - }).toList(); | |
| 63 | - // 3. 保存数据 | |
| 64 | - iotOtaUpgradeRecordMapper.insertBatch(upgradeRecordList); | |
| 65 | - // TODO @芋艿:在这里需要处理推送升级任务的逻辑 | |
| 36 | + public void createOtaTaskRecordList(List<IotDeviceDO> devices, Long firmwareId, Long taskId) { | |
| 37 | + List<IotOtaTaskRecordDO> records = convertList(devices, device -> | |
| 38 | + IotOtaTaskRecordDO.builder().firmwareId(firmwareId).taskId(taskId) | |
| 39 | + .deviceId(device.getId()).fromFirmwareId(Convert.toLong(device.getFirmwareId())) | |
| 40 | + .status(IotOtaTaskRecordStatusEnum.PENDING.getStatus()).progress(0).build()); | |
| 41 | + otaTaskRecordMapper.insertBatch(records); | |
| 66 | 42 | } |
| 67 | 43 | |
| 68 | - // TODO @li:1)方法注释,简单写;2)父类写了注释,子类就不用写了。。。 | |
| 69 | - /** | |
| 70 | - * 获取OTA升级记录的数量统计。 | |
| 71 | - * 该方法根据传入的查询条件,统计不同状态的OTA升级记录数量,并返回一个包含各状态数量的映射。 | |
| 72 | - * | |
| 73 | - * @param pageReqVO 包含查询条件的请求对象,主要包括任务ID和设备名称等信息。 | |
| 74 | - * @return 返回一个Map,其中键为状态常量,值为对应状态的记录数量。 | |
| 75 | - */ | |
| 76 | 44 | @Override |
| 77 | - @Transactional | |
| 78 | - public Map<Integer, Long> getOtaTaskRecordCount(IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 79 | - // 分别查询不同状态的OTA升级记录数量 | |
| 80 | - List<Map<String, Object>> upgradeRecordCountList = iotOtaUpgradeRecordMapper.selectOtaUpgradeRecordCount( | |
| 81 | - pageReqVO.getTaskId(), pageReqVO.getDeviceName()); | |
| 82 | - Map<String, Object> upgradeRecordCountMap = ObjectUtils.defaultIfNull(upgradeRecordCountList.get(0)); | |
| 83 | - Objects.requireNonNull(upgradeRecordCountMap); | |
| 84 | - return upgradeRecordCountMap.entrySet().stream().collect(Collectors.toMap( | |
| 85 | - entry -> Convert.toInt(entry.getKey()), | |
| 86 | - entry -> Convert.toLong(entry.getValue()))); | |
| 45 | + public Map<Integer, Long> getOtaTaskRecordStatusCountMap(Long firmwareId, Long taskId) { | |
| 46 | + // 按照 status 枚举,初始化 countMap 为 0 | |
| 47 | + Map<Integer, Long> countMap = convertMap(Arrays.asList(IotOtaTaskRecordStatusEnum.values()), | |
| 48 | + IotOtaTaskRecordStatusEnum::getStatus, iotOtaTaskRecordStatusEnum -> 0L); | |
| 49 | + | |
| 50 | + // 查询记录,只返回 id、status 字段 | |
| 51 | + List<IotOtaTaskRecordDO> records = otaTaskRecordMapper.selectListByFirmwareIdAndTaskId(firmwareId, taskId); | |
| 52 | + Map<Long, List<Integer>> deviceStatusesMap = convertMultiMap(records, | |
| 53 | + IotOtaTaskRecordDO::getDeviceId, IotOtaTaskRecordDO::getStatus); | |
| 54 | + // 找到第一个匹配的优先级状态,避免重复计算 | |
| 55 | + deviceStatusesMap.forEach((deviceId, statuses) -> { | |
| 56 | + for (Integer priorityStatus : IotOtaTaskRecordStatusEnum.PRIORITY_STATUSES) { | |
| 57 | + if (statuses.contains(priorityStatus)) { | |
| 58 | + countMap.put(priorityStatus, countMap.get(priorityStatus) + 1); | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + } | |
| 62 | + }); | |
| 63 | + return countMap; | |
| 87 | 64 | } |
| 88 | 65 | |
| 89 | 66 | @Override |
| 90 | - @Transactional | |
| 91 | - public Map<Integer, Long> getOtaTaskRecordStatistics(Long firmwareId) { | |
| 92 | - // 查询并统计不同状态的OTA升级记录数量 | |
| 93 | - List<Map<String, Object>> upgradeRecordStatisticsList = iotOtaUpgradeRecordMapper.selectOtaUpgradeRecordStatistics(firmwareId); | |
| 94 | - Map<String, Object> upgradeRecordStatisticsMap = ObjectUtils.defaultIfNull(upgradeRecordStatisticsList.get(0)); | |
| 95 | - Objects.requireNonNull(upgradeRecordStatisticsMap); | |
| 96 | - return upgradeRecordStatisticsMap.entrySet().stream().collect(Collectors.toMap( | |
| 97 | - entry -> Convert.toInt(entry.getKey()), | |
| 98 | - entry -> Convert.toLong(entry.getValue()))); | |
| 67 | + public IotOtaTaskRecordDO getOtaTaskRecord(Long id) { | |
| 68 | + return otaTaskRecordMapper.selectById(id); | |
| 99 | 69 | } |
| 100 | 70 | |
| 101 | 71 | @Override |
| 102 | - public IotOtaTaskRecordDO getOtaTaskRecord(Long id) { | |
| 103 | - return iotOtaUpgradeRecordMapper.selectById(id); | |
| 72 | + public PageResult<IotOtaTaskRecordDO> getOtaTaskRecordPage(IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 73 | + return otaTaskRecordMapper.selectPage(pageReqVO); | |
| 104 | 74 | } |
| 105 | 75 | |
| 106 | 76 | @Override |
| 107 | - public PageResult<IotOtaTaskRecordDO> getOtaTaskRecordPage(IotOtaTaskRecordPageReqVO pageReqVO) { | |
| 108 | - return iotOtaUpgradeRecordMapper.selectUpgradeRecordPage(pageReqVO); | |
| 77 | + public void cancelTaskRecordListByTaskId(Long taskId) { | |
| 78 | + // 设置取消记录的描述 | |
| 79 | + IotOtaTaskRecordDO updateRecord = IotOtaTaskRecordDO.builder() | |
| 80 | + .status(IotOtaTaskRecordStatusEnum.CANCELED.getStatus()) | |
| 81 | + .description("管理员取消升级任务") | |
| 82 | + .build(); | |
| 83 | + | |
| 84 | + otaTaskRecordMapper.updateByTaskIdAndStatus( | |
| 85 | + taskId, IotOtaTaskRecordStatusEnum.PENDING.getStatus(), updateRecord); | |
| 109 | 86 | } |
| 110 | 87 | |
| 111 | 88 | @Override |
| 112 | - public void cancelUpgradeRecordByTaskId(Long taskId) { | |
| 113 | - // 暂定只有待推送的升级记录可以取消 TODO @芋艿:可以看看阿里云,哪些可以取消 | |
| 114 | - iotOtaUpgradeRecordMapper.updateUpgradeRecordStatusByTaskIdAndStatus( | |
| 115 | - IotOtaTaskRecordStatusEnum.CANCELED.getStatus(), taskId, | |
| 116 | - IotOtaTaskRecordStatusEnum.PENDING.getStatus()); | |
| 89 | + public List<IotOtaTaskRecordDO> getOtaTaskRecordListByDeviceIdAndStatus(Set<Long> deviceIds, Set<Integer> statuses) { | |
| 90 | + return otaTaskRecordMapper.selectListByDeviceIdAndStatus(deviceIds, statuses); | |
| 117 | 91 | } |
| 118 | 92 | |
| 119 | - /** | |
| 120 | - * 验证指定的升级记录是否存在。 | |
| 121 | - * <p> | |
| 122 | - * 该函数通过给定的ID查询升级记录,如果查询结果为空,则抛出异常,表示升级记录不存在。 | |
| 123 | - * | |
| 124 | - * @param id 升级记录的唯一标识符,类型为Long。 | |
| 125 | - * @throws cn.iocoder.yudao.framework.common.exception.ServiceException,则抛出异常,异常类型为OTA_UPGRADE_RECORD_NOT_EXISTS。 | |
| 126 | - */ | |
| 127 | 93 | private IotOtaTaskRecordDO validateUpgradeRecordExists(Long id) { |
| 128 | - // 根据ID查询升级记录 | |
| 129 | - IotOtaTaskRecordDO upgradeRecord = iotOtaUpgradeRecordMapper.selectById(id); | |
| 130 | - // 如果查询结果为空,抛出异常 | |
| 94 | + IotOtaTaskRecordDO upgradeRecord = otaTaskRecordMapper.selectById(id); | |
| 131 | 95 | if (upgradeRecord == null) { |
| 132 | - throw exception(OTA_UPGRADE_RECORD_NOT_EXISTS); | |
| 96 | + throw exception(OTA_TASK_RECORD_NOT_EXISTS); | |
| 133 | 97 | } |
| 134 | 98 | return upgradeRecord; |
| 135 | 99 | } |
| 136 | 100 | |
| 137 | - // TODO @li:注释有点冗余 | |
| 138 | - /** | |
| 139 | - * 校验固件升级记录是否重复。 | |
| 140 | - * <p> | |
| 141 | - * 该函数用于检查给定的固件ID、任务ID和设备ID是否已经存在未取消的升级记录。 | |
| 142 | - * 如果存在未取消的记录,则抛出异常,提示升级记录重复。 | |
| 143 | - * | |
| 144 | - * @param firmwareId 固件ID,用于标识特定的固件版本 | |
| 145 | - * @param taskId 任务ID,用于标识特定的升级任务 | |
| 146 | - * @param deviceId 设备ID,用于标识特定的设备 | |
| 147 | - */ | |
| 148 | - private void validateUpgradeRecordDuplicate(Long firmwareId, Long taskId, String deviceId) { | |
| 149 | - IotOtaTaskRecordDO upgradeRecord = iotOtaUpgradeRecordMapper.selectByConditions(firmwareId, taskId, deviceId); | |
| 150 | - if (upgradeRecord == null) { | |
| 151 | - return; | |
| 152 | - } | |
| 153 | - if (!Objects.equals(upgradeRecord.getStatus(), IotOtaTaskRecordStatusEnum.CANCELED.getStatus())) { | |
| 154 | - throw exception(OTA_UPGRADE_RECORD_DUPLICATE); | |
| 155 | - } | |
| 156 | - } | |
| 157 | - | |
| 158 | - // TODO @li:注释有点冗余 | |
| 159 | - /** | |
| 160 | - * 验证升级记录是否可以重试。 | |
| 161 | - * <p> | |
| 162 | - * 该方法用于检查给定的升级记录是否处于允许重试的状态。如果升级记录的状态为 | |
| 163 | - * PENDING、PUSHED 或 UPGRADING,则抛出异常,表示不允许重试。 | |
| 164 | - * | |
| 165 | - * @param upgradeRecord 需要验证的升级记录对象,类型为 IotOtaUpgradeRecordDO | |
| 166 | - * @throws cn.iocoder.yudao.framework.common.exception.ServiceException,则抛出 OTA_UPGRADE_RECORD_CANNOT_RETRY 异常 | |
| 167 | - */ | |
| 168 | - // TODO @li:这种一次性的方法(不复用的),其实一步一定要抽成小方法; | |
| 169 | - private void validateUpgradeRecordCanRetry(IotOtaTaskRecordDO upgradeRecord) { | |
| 170 | - if (ObjectUtils.equalsAny(upgradeRecord.getStatus(), | |
| 171 | - IotOtaTaskRecordStatusEnum.PENDING.getStatus(), | |
| 172 | - IotOtaTaskRecordStatusEnum.PUSHED.getStatus(), | |
| 173 | - IotOtaTaskRecordStatusEnum.UPGRADING.getStatus())) { | |
| 174 | - throw exception(OTA_UPGRADE_RECORD_CANNOT_RETRY); | |
| 175 | - } | |
| 176 | - } | |
| 177 | - | |
| 178 | 101 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaTaskService.java
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/ota/IotOtaTaskServiceImpl.java
| 1 | 1 | package cn.iocoder.yudao.module.iot.service.ota; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | -import cn.hutool.core.convert.Convert; | |
| 4 | +import cn.hutool.core.util.ObjUtil; | |
| 5 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | 6 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 7 | 7 | import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.IotOtaTaskCreateReqVO; |
| ... | ... | @@ -9,8 +9,10 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.task.IotOtaTaskPageRe |
| 9 | 9 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 10 | 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO; |
| 11 | 11 | import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskDO; |
| 12 | +import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaTaskRecordDO; | |
| 12 | 13 | import cn.iocoder.yudao.module.iot.dal.mysql.ota.IotOtaTaskMapper; |
| 13 | 14 | import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskDeviceScopeEnum; |
| 15 | +import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskRecordStatusEnum; | |
| 14 | 16 | import cn.iocoder.yudao.module.iot.enums.ota.IotOtaTaskStatusEnum; |
| 15 | 17 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 16 | 18 | import jakarta.annotation.Resource; |
| ... | ... | @@ -24,6 +26,7 @@ import java.util.List; |
| 24 | 26 | import java.util.Objects; |
| 25 | 27 | |
| 26 | 28 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 29 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; | |
| 27 | 30 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; |
| 28 | 31 | |
| 29 | 32 | /** |
| ... | ... | @@ -45,26 +48,29 @@ public class IotOtaTaskServiceImpl implements IotOtaTaskService { |
| 45 | 48 | private IotOtaFirmwareService otaFirmwareService; |
| 46 | 49 | @Resource |
| 47 | 50 | @Lazy // 延迟,避免循环依赖报错 |
| 48 | - private IotOtaTaskRecordService otaUpgradeRecordService; | |
| 51 | + private IotOtaTaskRecordService otaTaskRecordService; | |
| 49 | 52 | |
| 50 | 53 | @Override |
| 51 | 54 | @Transactional(rollbackFor = Exception.class) |
| 52 | 55 | public Long createOtaTask(IotOtaTaskCreateReqVO createReqVO) { |
| 53 | - // 1.1 校验同一固件的升级任务名称不重复 | |
| 54 | - validateFirmwareTaskDuplicate(createReqVO.getFirmwareId(), createReqVO.getName()); | |
| 55 | - // 1.2 校验固件信息是否存在 | |
| 56 | + // 1.1 校验固件信息是否存在 | |
| 56 | 57 | IotOtaFirmwareDO firmware = otaFirmwareService.validateFirmwareExists(createReqVO.getFirmwareId()); |
| 57 | - // 1.3 补全设备范围信息,并且校验是否又设备可以升级,如果没有设备可以升级,则报错 | |
| 58 | - validateScopeAndDevice(createReqVO.getDeviceScope(), createReqVO.getDeviceIds(), firmware.getProductId()); | |
| 59 | - | |
| 60 | - // 2. 保存 OTA 升级任务信息到数据库 | |
| 61 | - IotOtaTaskDO upgradeTask = initOtaUpgradeTask(createReqVO, firmware.getProductId()); | |
| 62 | - otaTaskMapper.insert(upgradeTask); | |
| 63 | - | |
| 64 | - // 3. 生成设备升级记录信息并存储,等待定时任务轮询 | |
| 65 | - // TODO @芋艿:在处理; | |
| 66 | -// otaUpgradeRecordService.createOtaUpgradeRecordBatch(upgradeTask.getDeviceIds(), firmware.getId(), upgradeTask.getId()); | |
| 67 | - return upgradeTask.getId(); | |
| 58 | + // 1.2 校验同一固件的升级任务名称不重复 | |
| 59 | + if (otaTaskMapper.selectByFirmwareIdAndName(firmware.getId(), createReqVO.getName()) != null) { | |
| 60 | + throw exception(OTA_TASK_CREATE_FAIL_NAME_DUPLICATE); | |
| 61 | + } | |
| 62 | + // 1.3 校验设备范围信息 | |
| 63 | + List<IotDeviceDO> devices = validateOtaTaskDeviceScope(createReqVO, firmware.getProductId()); | |
| 64 | + | |
| 65 | + // 2. 保存升级任务,直接转换 | |
| 66 | + IotOtaTaskDO task = BeanUtils.toBean(createReqVO, IotOtaTaskDO.class) | |
| 67 | + .setStatus(IotOtaTaskStatusEnum.IN_PROGRESS.getStatus()) | |
| 68 | + .setDeviceTotalCount(devices.size()).setDeviceSuccessCount(0); | |
| 69 | + otaTaskMapper.insert(task); | |
| 70 | + | |
| 71 | + // 3. 生成设备升级记录 | |
| 72 | + otaTaskRecordService.createOtaTaskRecordList(devices, firmware.getId(), task.getId()); | |
| 73 | + return task.getId(); | |
| 68 | 74 | } |
| 69 | 75 | |
| 70 | 76 | @Override |
| ... | ... | @@ -73,18 +79,17 @@ public class IotOtaTaskServiceImpl implements IotOtaTaskService { |
| 73 | 79 | // 1.1 校验升级任务是否存在 |
| 74 | 80 | IotOtaTaskDO upgradeTask = validateUpgradeTaskExists(id); |
| 75 | 81 | // 1.2 校验升级任务是否可以取消 |
| 76 | - // TODO @li:ObjUtil notequals | |
| 77 | - if (!Objects.equals(upgradeTask.getStatus(), IotOtaTaskStatusEnum.IN_PROGRESS.getStatus())) { | |
| 78 | - throw exception(OTA_UPGRADE_TASK_CANNOT_CANCEL); | |
| 82 | + if (ObjUtil.notEqual(upgradeTask.getStatus(), IotOtaTaskStatusEnum.IN_PROGRESS.getStatus())) { | |
| 83 | + throw exception(OTA_TASK_CANCEL_FAIL_STATUS_END); | |
| 79 | 84 | } |
| 80 | 85 | |
| 81 | - // 2. 更新 OTA 升级任务状态为已取消 | |
| 86 | + // 2. 更新升级任务状态为已取消 | |
| 82 | 87 | otaTaskMapper.updateById(IotOtaTaskDO.builder() |
| 83 | 88 | .id(id).status(IotOtaTaskStatusEnum.CANCELED.getStatus()) |
| 84 | 89 | .build()); |
| 85 | 90 | |
| 86 | - // 3. 更新 OTA 升级记录状态为已取消 | |
| 87 | - otaUpgradeRecordService.cancelUpgradeRecordByTaskId(id); | |
| 91 | + // 3. 更新升级记录状态为已取消 | |
| 92 | + otaTaskRecordService.cancelTaskRecordListByTaskId(id); | |
| 88 | 93 | } |
| 89 | 94 | |
| 90 | 95 | @Override |
| ... | ... | @@ -97,50 +102,55 @@ public class IotOtaTaskServiceImpl implements IotOtaTaskService { |
| 97 | 102 | return otaTaskMapper.selectUpgradeTaskPage(pageReqVO); |
| 98 | 103 | } |
| 99 | 104 | |
| 100 | - /** | |
| 101 | - * 校验固件升级任务是否重复 | |
| 102 | - */ | |
| 103 | - private void validateFirmwareTaskDuplicate(Long firmwareId, String taskName) { | |
| 104 | - List<IotOtaTaskDO> upgradeTaskList = otaTaskMapper.selectByFirmwareIdAndName(firmwareId, taskName); | |
| 105 | - if (CollUtil.isNotEmpty(upgradeTaskList)) { | |
| 106 | - throw exception(OTA_UPGRADE_TASK_NAME_DUPLICATE); | |
| 107 | - } | |
| 108 | - } | |
| 109 | - | |
| 110 | - private void validateScopeAndDevice(Integer scope, List<Long> deviceIds, Long productId) { | |
| 111 | - if (Objects.equals(scope, IotOtaTaskDeviceScopeEnum.SELECT.getScope())) { | |
| 112 | - if (CollUtil.isEmpty(deviceIds)) { | |
| 113 | - throw exception(OTA_UPGRADE_TASK_DEVICE_IDS_EMPTY); | |
| 105 | + private List<IotDeviceDO> validateOtaTaskDeviceScope(IotOtaTaskCreateReqVO createReqVO, Long productId) { | |
| 106 | + // 情况一:选择设备 | |
| 107 | + if (Objects.equals(createReqVO.getDeviceScope(), IotOtaTaskDeviceScopeEnum.SELECT.getScope())) { | |
| 108 | + // 1.1 校验设备存在 | |
| 109 | + List<IotDeviceDO> devices = deviceService.validateDeviceListExists(createReqVO.getDeviceIds()); | |
| 110 | + for (IotDeviceDO device : devices) { | |
| 111 | + if (ObjUtil.notEqual(device.getProductId(), productId)) { | |
| 112 | + throw exception(DEVICE_NOT_EXISTS); | |
| 113 | + } | |
| 114 | 114 | } |
| 115 | - return; | |
| 115 | + // 1.2 校验设备是否已经是该固件版本 | |
| 116 | + devices.forEach(device -> { | |
| 117 | + if (Objects.equals(device.getFirmwareId(), createReqVO.getFirmwareId())) { | |
| 118 | + throw exception(OTA_TASK_CREATE_FAIL_DEVICE_FIRMWARE_EXISTS, device.getDeviceName()); | |
| 119 | + } | |
| 120 | + }); | |
| 121 | + // 1.3 校验设备是否已经在升级中 | |
| 122 | + List<IotOtaTaskRecordDO> records = otaTaskRecordService.getOtaTaskRecordListByDeviceIdAndStatus( | |
| 123 | + convertSet(devices, IotDeviceDO::getId), IotOtaTaskRecordStatusEnum.IN_PROCESS_STATUSES); | |
| 124 | + devices.forEach(device -> { | |
| 125 | + if (CollUtil.contains(records, item -> item.getDeviceId().equals(device.getId()))) { | |
| 126 | + throw exception(OTA_TASK_CREATE_FAIL_DEVICE_OTA_IN_PROCESS, device.getDeviceName()); | |
| 127 | + } | |
| 128 | + }); | |
| 129 | + return devices; | |
| 116 | 130 | } |
| 117 | - | |
| 118 | - if (Objects.equals(scope, IotOtaTaskDeviceScopeEnum.ALL.getScope())) { | |
| 119 | - List<IotDeviceDO> deviceList = deviceService.getDeviceListByProductId(productId); | |
| 120 | - if (CollUtil.isEmpty(deviceList)) { | |
| 121 | - throw exception(OTA_UPGRADE_TASK_DEVICE_LIST_EMPTY); | |
| 131 | + // 情况二:全部设备 | |
| 132 | + if (Objects.equals(createReqVO.getDeviceScope(), IotOtaTaskDeviceScopeEnum.ALL.getScope())) { | |
| 133 | + List<IotDeviceDO> devices = deviceService.getDeviceListByProductId(productId); | |
| 134 | + // 2.1.1 移除已经是该固件版本的设备 | |
| 135 | + devices.removeIf(device -> Objects.equals(device.getFirmwareId(), createReqVO.getFirmwareId())); | |
| 136 | + // 2.1.2 移除已经在升级中的设备 | |
| 137 | + List<IotOtaTaskRecordDO> records = otaTaskRecordService.getOtaTaskRecordListByDeviceIdAndStatus( | |
| 138 | + convertSet(devices, IotDeviceDO::getId), IotOtaTaskRecordStatusEnum.IN_PROCESS_STATUSES); | |
| 139 | + devices.removeIf(device -> CollUtil.contains(records, | |
| 140 | + item -> item.getDeviceId().equals(device.getId()))); | |
| 141 | + // 2.2 校验是否有可升级的设备 | |
| 142 | + if (CollUtil.isEmpty(devices)) { | |
| 143 | + throw exception(OTA_TASK_CREATE_FAIL_DEVICE_EMPTY); | |
| 122 | 144 | } |
| 145 | + return devices; | |
| 123 | 146 | } |
| 147 | + throw new IllegalArgumentException("不支持的设备范围:" + createReqVO.getDeviceScope()); | |
| 124 | 148 | } |
| 125 | 149 | |
| 126 | 150 | private IotOtaTaskDO validateUpgradeTaskExists(Long id) { |
| 127 | 151 | IotOtaTaskDO upgradeTask = otaTaskMapper.selectById(id); |
| 128 | 152 | if (Objects.isNull(upgradeTask)) { |
| 129 | - throw exception(OTA_UPGRADE_TASK_NOT_EXISTS); | |
| 130 | - } | |
| 131 | - return upgradeTask; | |
| 132 | - } | |
| 133 | - | |
| 134 | - private IotOtaTaskDO initOtaUpgradeTask(IotOtaTaskCreateReqVO createReqVO, Long productId) { | |
| 135 | - IotOtaTaskDO upgradeTask = BeanUtils.toBean(createReqVO, IotOtaTaskDO.class); | |
| 136 | - upgradeTask.setDeviceTotalCount(Convert.toLong(CollUtil.size(createReqVO.getDeviceIds()))) | |
| 137 | - .setStatus(IotOtaTaskStatusEnum.IN_PROGRESS.getStatus()); | |
| 138 | - | |
| 139 | - if (Objects.equals(createReqVO.getDeviceScope(), IotOtaTaskDeviceScopeEnum.ALL.getScope())) { | |
| 140 | - List<IotDeviceDO> deviceList = deviceService.getDeviceListByProductId(productId); | |
| 141 | - upgradeTask.setDeviceTotalCount((long) deviceList.size()); | |
| 142 | -// upgradeTask.setDeviceIds( | |
| 143 | -// deviceList.stream().map(IotDeviceDO::getId).collect(Collectors.toList())); | |
| 153 | + throw exception(OTA_TASK_NOT_EXISTS); | |
| 144 | 154 | } |
| 145 | 155 | return upgradeTask; |
| 146 | 156 | } | ... | ... |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/rule/data/IotDataRuleServiceImpl.java
| ... | ... | @@ -121,7 +121,7 @@ public class IotDataRuleServiceImpl implements IotDataRuleService { |
| 121 | 121 | convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getProductId)); |
| 122 | 122 | |
| 123 | 123 | // 2. 校验设备 |
| 124 | - deviceService.validateDevicesExist(convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getDeviceId, | |
| 124 | + deviceService.validateDeviceListExists(convertSet(sourceConfigs, IotDataRuleDO.SourceConfig::getDeviceId, | |
| 125 | 125 | config -> ObjUtil.notEqual(config.getDeviceId(), IotDeviceDO.DEVICE_ID_ALL))); |
| 126 | 126 | |
| 127 | 127 | // 3. 校验物模型存在 | ... | ... |