Commit 0f0ebda4692da2044ca6b27c44de5de45e5e91da
1 parent
6e1ec8b3
[fix]:iot home count
Showing
17 changed files
with
217 additions
and
209 deletions
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/IotStatisticsController.java
| 1 | package cn.iocoder.yudao.module.iot.controller.admin.statistics; | 1 | package cn.iocoder.yudao.module.iot.controller.admin.statistics; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO; | ||
| 4 | import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO; | 5 | import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO; |
| 5 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | 6 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO; |
| 6 | import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; | 7 | import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; |
| 7 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | 8 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 8 | import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; | 9 | import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService; |
| @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -18,6 +19,7 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 18 | import org.springframework.web.bind.annotation.RestController; | 19 | import org.springframework.web.bind.annotation.RestController; |
| 19 | 20 | ||
| 20 | import java.time.LocalDateTime; | 21 | import java.time.LocalDateTime; |
| 22 | +import java.util.Map; | ||
| 21 | 23 | ||
| 22 | @Tag(name = "管理后台 - IoT 数据统计") | 24 | @Tag(name = "管理后台 - IoT 数据统计") |
| 23 | @RestController | 25 | @RestController |
| @@ -35,38 +37,41 @@ public class IotStatisticsController { | @@ -35,38 +37,41 @@ public class IotStatisticsController { | ||
| 35 | private IotDeviceLogService deviceLogService; | 37 | private IotDeviceLogService deviceLogService; |
| 36 | 38 | ||
| 37 | // TODO @super:description 非必要,可以不写哈 | 39 | // TODO @super:description 非必要,可以不写哈 |
| 38 | - @GetMapping("/main") | ||
| 39 | - @Operation(summary = "获取首页的数据统计", description = "用于IOT首页的数据统计") | ||
| 40 | - public CommonResult<IotStatisticsRespVO> getIotMainStats(@Valid IotStatisticsReqVO reqVO){ | ||
| 41 | - // TODO @super:新增 get-summary 接口,返回:总数、今日新增、数量、状态 | ||
| 42 | - IotStatisticsRespVO iotStatisticsRespVO = new IotStatisticsRespVO(); | 40 | + @GetMapping("/get-summary") |
| 41 | + @Operation(summary = "获取IOT数据统计") | ||
| 42 | + public CommonResult<IotStatisticsSummaryRespVO> getIotStatisticsSummary(){ | ||
| 43 | + IotStatisticsSummaryRespVO respVO = new IotStatisticsSummaryRespVO(); | ||
| 43 | // 获取总数 | 44 | // 获取总数 |
| 44 | - iotStatisticsRespVO.setCategoryTotal(productCategoryService.getProductCategoryCount(null)); | ||
| 45 | - iotStatisticsRespVO.setProductTotal(productService.getProductCount(null)); | ||
| 46 | - iotStatisticsRespVO.setDeviceTotal(deviceService.getDeviceCount(null)); | ||
| 47 | - iotStatisticsRespVO.setReportTotal(deviceLogService.getDeviceLogCount(null)); | 45 | + respVO.setProductCategoryCount(productCategoryService.getProductCategoryCount(null)); |
| 46 | + respVO.setProductCount(productService.getProductCount(null)); | ||
| 47 | + respVO.setDeviceCount(deviceService.getDeviceCount(null)); | ||
| 48 | + respVO.setDeviceMessageCount(deviceLogService.getDeviceLogCount(null)); | ||
| 48 | 49 | ||
| 49 | // 获取今日新增数量 | 50 | // 获取今日新增数量 |
| 50 | LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); | 51 | LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); |
| 51 | - iotStatisticsRespVO.setCategoryTodayTotal(productCategoryService.getProductCategoryCount(todayStart)); | ||
| 52 | - iotStatisticsRespVO.setProductTodayTotal(productService.getProductCount(todayStart)); | ||
| 53 | - iotStatisticsRespVO.setDeviceTodayTotal(deviceService.getDeviceCount(todayStart)); | ||
| 54 | - iotStatisticsRespVO.setReportTodayTotal(deviceLogService.getDeviceLogCount(todayStart)); | 52 | + respVO.setProductCategoryTodayCount(productCategoryService.getProductCategoryCount(todayStart)); |
| 53 | + respVO.setProductTodayCount(productService.getProductCount(todayStart)); | ||
| 54 | + respVO.setDeviceTodayCount(deviceService.getDeviceCount(todayStart)); | ||
| 55 | + respVO.setDeviceMessageTodayCount(deviceLogService.getDeviceLogCount(todayStart)); | ||
| 55 | 56 | ||
| 56 | // 获取各个品类下设备数量统计 | 57 | // 获取各个品类下设备数量统计 |
| 57 | - iotStatisticsRespVO.setDeviceStatsOfCategory( | ||
| 58 | - productCategoryService.getDeviceCountsOfProductCategory() | ||
| 59 | - ); | 58 | + respVO.setProductCategoryDeviceCounts(productCategoryService.getProductCategoryDeviceCountMap()); |
| 60 | 59 | ||
| 61 | // 获取设备状态数量统计 | 60 | // 获取设备状态数量统计 |
| 62 | - iotStatisticsRespVO.setOnlineTotal(deviceService.getDeviceCountByState(IotDeviceStateEnum.ONLINE.getState())); | ||
| 63 | - iotStatisticsRespVO.setOfflineTotal(deviceService.getDeviceCountByState(IotDeviceStateEnum.OFFLINE.getState())); | ||
| 64 | - iotStatisticsRespVO.setNeverOnlineTotal(deviceService.getDeviceCountByState(IotDeviceStateEnum.INACTIVE.getState())); | 61 | + Map<Integer, Long> deviceCountMap = deviceService.getDeviceCountMapByState(); |
| 62 | + respVO.setDeviceOnlineCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.ONLINE.getState(), 0L)); | ||
| 63 | + respVO.setDeviceOfflineCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.OFFLINE.getState(), 0L)); | ||
| 64 | + respVO.setDeviceInactiveCount(deviceCountMap.getOrDefault(IotDeviceStateEnum.INACTIVE.getState(), 0L)); | ||
| 65 | 65 | ||
| 66 | - // TODO @super:新增 get-log-summary 接口,返回 | 66 | + return CommonResult.success(respVO); |
| 67 | + } | ||
| 68 | + @GetMapping("/get-log-summary") | ||
| 69 | + @Operation(summary = "获取IOT上下行消息数据统计") | ||
| 70 | + public CommonResult<IotStatisticsDeviceMessageSummaryRespVO> getIotStatisticsDeviceMessageSummary(@Valid IotStatisticsReqVO reqVO){ | ||
| 67 | // 根据传入时间范围获取设备上下行消息数量统计 | 71 | // 根据传入时间范围获取设备上下行消息数量统计 |
| 68 | - iotStatisticsRespVO.setDeviceUpMessageStats(deviceLogService.getDeviceLogUpCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())); | ||
| 69 | - iotStatisticsRespVO.setDeviceDownMessageStats(deviceLogService.getDeviceLogDownCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())); | 72 | + IotStatisticsDeviceMessageSummaryRespVO iotStatisticsRespVO = new IotStatisticsDeviceMessageSummaryRespVO(); |
| 73 | + iotStatisticsRespVO.setUpstreamCounts(deviceLogService.getDeviceLogUpCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())); | ||
| 74 | + iotStatisticsRespVO.setDownstreamCounts(deviceLogService.getDeviceLogDownCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())); | ||
| 70 | 75 | ||
| 71 | return CommonResult.success(iotStatisticsRespVO); | 76 | return CommonResult.success(iotStatisticsRespVO); |
| 72 | } | 77 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsDeviceMessageSummaryRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo; | ||
| 2 | + | ||
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | +import lombok.Data; | ||
| 5 | + | ||
| 6 | +import java.util.List; | ||
| 7 | +import java.util.Map; | ||
| 8 | + | ||
| 9 | +@Schema(description = "管理后台 - Iot 上下行消息数量统计 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class IotStatisticsDeviceMessageSummaryRespVO { | ||
| 12 | + @Schema(description = "每小时上行数据数量统计") | ||
| 13 | + private List<Map<Long, Integer>> upstreamCounts; | ||
| 14 | + | ||
| 15 | + @Schema(description = "每小时下行数据数量统计") | ||
| 16 | + private List<Map<Long, Integer>> downstreamCounts; | ||
| 17 | + | ||
| 18 | + // TODO @super:如果只有这两个字段,使用 KeyValue 这个键值对 | ||
| 19 | +} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsReqVO.java
| @@ -11,12 +11,12 @@ public class IotStatisticsReqVO { | @@ -11,12 +11,12 @@ public class IotStatisticsReqVO { | ||
| 11 | // TODO @supper:times 直接传递哈; | 11 | // TODO @supper:times 直接传递哈; |
| 12 | // TODO 2super:private 不要丢了 | 12 | // TODO 2super:private 不要丢了 |
| 13 | 13 | ||
| 14 | - @Schema(description = "查询起始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") | 14 | + @Schema(description = "查询起始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1658486600000") |
| 15 | @NotNull(message = "查询起始时间不能为空") | 15 | @NotNull(message = "查询起始时间不能为空") |
| 16 | - Long startTime; | 16 | + private Long startTime; |
| 17 | 17 | ||
| 18 | - @Schema(description = "查询结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "177") | 18 | + @Schema(description = "查询结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1758486600000") |
| 19 | @NotNull(message = "查询结束时间不能为空") | 19 | @NotNull(message = "查询结束时间不能为空") |
| 20 | - Long endTime; | 20 | + private Long endTime; |
| 21 | 21 | ||
| 22 | } | 22 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsRespVO.java renamed to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsSummaryRespVO.java
| @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo; | @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo; | ||
| 3 | import io.swagger.v3.oas.annotations.media.Schema; | 3 | import io.swagger.v3.oas.annotations.media.Schema; |
| 4 | import lombok.Data; | 4 | import lombok.Data; |
| 5 | 5 | ||
| 6 | -import java.util.List; | 6 | +import java.util.Map; |
| 7 | 7 | ||
| 8 | // TODO @super:Total 全部改成 Count | 8 | // TODO @super:Total 全部改成 Count |
| 9 | // TODO @super:IotStatisticsSummaryRespVO | 9 | // TODO @super:IotStatisticsSummaryRespVO |
| @@ -12,90 +12,58 @@ import java.util.List; | @@ -12,90 +12,58 @@ import java.util.List; | ||
| 12 | */ | 12 | */ |
| 13 | @Schema(description = "管理后台 - Iot 统计 Response VO") | 13 | @Schema(description = "管理后台 - Iot 统计 Response VO") |
| 14 | @Data | 14 | @Data |
| 15 | -public class IotStatisticsRespVO { | 15 | +public class IotStatisticsSummaryRespVO { |
| 16 | 16 | ||
| 17 | // TODO @super:productCategory 哈 | 17 | // TODO @super:productCategory 哈 |
| 18 | @Schema(description = "品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 18 | @Schema(description = "品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 19 | - private long categoryTotal; | 19 | + private long productCategoryCount; |
| 20 | 20 | ||
| 21 | @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | 21 | @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") |
| 22 | - private long productTotal; | 22 | + private long productCount; |
| 23 | 23 | ||
| 24 | @Schema(description = "设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | 24 | @Schema(description = "设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 25 | - private long deviceTotal; | 25 | + private long deviceCount; |
| 26 | 26 | ||
| 27 | // TODO @super:deviceMessageCount;设备消息数量 | 27 | // TODO @super:deviceMessageCount;设备消息数量 |
| 28 | @Schema(description = "上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") | 28 | @Schema(description = "上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") |
| 29 | - private long reportTotal; | 29 | + private long deviceMessageCount; |
| 30 | 30 | ||
| 31 | // TODO @super:productCategory 哈 | 31 | // TODO @super:productCategory 哈 |
| 32 | @Schema(description = "今日新增品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | 32 | @Schema(description = "今日新增品类数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") |
| 33 | - private long categoryTodayTotal; | 33 | + private long productCategoryTodayCount; |
| 34 | 34 | ||
| 35 | @Schema(description = "今日新增产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | 35 | @Schema(description = "今日新增产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") |
| 36 | - private long productTodayTotal; | 36 | + private long productTodayCount; |
| 37 | 37 | ||
| 38 | @Schema(description = "今日新增设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | 38 | @Schema(description = "今日新增设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") |
| 39 | - private long deviceTodayTotal; | 39 | + private long deviceTodayCount; |
| 40 | 40 | ||
| 41 | // TODO @super:deviceMessageCount;今日设备消息数量 | 41 | // TODO @super:deviceMessageCount;今日设备消息数量 |
| 42 | @Schema(description = "今日新增上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") | 42 | @Schema(description = "今日新增上报数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000") |
| 43 | - private long reportTodayTotal; | 43 | + private long deviceMessageTodayCount; |
| 44 | 44 | ||
| 45 | // TODO @super:deviceOnlineCount | 45 | // TODO @super:deviceOnlineCount |
| 46 | 46 | ||
| 47 | @Schema(description = "在线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") | 47 | @Schema(description = "在线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") |
| 48 | - private long onlineTotal; | 48 | + private long deviceOnlineCount; |
| 49 | 49 | ||
| 50 | // TODO @super:deviceOfflineCount | 50 | // TODO @super:deviceOfflineCount |
| 51 | 51 | ||
| 52 | @Schema(description = "离线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15") | 52 | @Schema(description = "离线数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15") |
| 53 | - private long offlineTotal; | 53 | + private long deviceOfflineCount; |
| 54 | 54 | ||
| 55 | // TODO @super:deviceInactivECount | 55 | // TODO @super:deviceInactivECount |
| 56 | 56 | ||
| 57 | @Schema(description = "待激活设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") | 57 | @Schema(description = "待激活设备数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") |
| 58 | - private long neverOnlineTotal; | 58 | + private long deviceInactiveCount; |
| 59 | 59 | ||
| 60 | // TODO @super:1)类型改成 Map,key 分类名、value 设备数量;2)deviceStatsOfCategory => productCategoryDeviceCounts | 60 | // TODO @super:1)类型改成 Map,key 分类名、value 设备数量;2)deviceStatsOfCategory => productCategoryDeviceCounts |
| 61 | @Schema(description = "按品类统计的设备数量") | 61 | @Schema(description = "按品类统计的设备数量") |
| 62 | - private List<DataItem> deviceStatsOfCategory; | 62 | + private Map<String, Integer> productCategoryDeviceCounts; |
| 63 | 63 | ||
| 64 | // TODO @super:貌似界面里,用不到这个字段??? | 64 | // TODO @super:貌似界面里,用不到这个字段??? |
| 65 | - @Schema(description = "上报数据数量统计") | ||
| 66 | - private List<TimeData> reportDataStats; | ||
| 67 | 65 | ||
| 68 | - // TODO @super:deviceUpMessageStats、deviceDownMessageStats 单独抽到 IotStatisticsDeviceMessageSummaryRespVO,然后里面属性就是 upstreamCounts、downstreamCounts | ||
| 69 | - | ||
| 70 | - @Schema(description = "上行数据数量统计") | ||
| 71 | - private List<TimeData> deviceUpMessageStats; | ||
| 72 | - | ||
| 73 | - @Schema(description = "下行数据数量统计") | ||
| 74 | - private List<TimeData> deviceDownMessageStats; | ||
| 75 | - | ||
| 76 | - // TODO @super:如果只有这两个字段,使用 KeyValue 这个键值对 | ||
| 77 | - @Schema(description = "时间数据") | ||
| 78 | - @Data | ||
| 79 | - public static class TimeData { | ||
| 80 | - | ||
| 81 | - @Schema(description = "时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1646092800000") | ||
| 82 | - private long time; | ||
| 83 | - | ||
| 84 | - @Schema(description = "数据值", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") | ||
| 85 | - private Object data; | ||
| 86 | 66 | ||
| 87 | - } | ||
| 88 | - | ||
| 89 | - @Schema(description = "数据项") | ||
| 90 | - @Data | ||
| 91 | - public static class DataItem { | ||
| 92 | - | ||
| 93 | - @Schema(description = "数据项名", requiredMode = Schema.RequiredMode.REQUIRED, example = "智能家居") | ||
| 94 | - private String name; | ||
| 95 | - | ||
| 96 | - @Schema(description = "数据项值", requiredMode = Schema.RequiredMode.REQUIRED, example = "50") | ||
| 97 | - private Object value; | ||
| 98 | - | ||
| 99 | - } | 67 | + // TODO @super:deviceUpMessageStats、deviceDownMessageStats 单独抽到 IotStatisticsDeviceMessageSummaryRespVO,然后里面属性就是 upstreamCounts、downstreamCounts |
| 100 | 68 | ||
| 101 | } | 69 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/device/IotDeviceMapper.java
| @@ -8,10 +8,13 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePa | @@ -8,10 +8,13 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.IotDevicePa | ||
| 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 9 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| 10 | import org.apache.ibatis.annotations.Mapper; | 10 | import org.apache.ibatis.annotations.Mapper; |
| 11 | +import org.apache.ibatis.annotations.Param; | ||
| 11 | 12 | ||
| 12 | import javax.annotation.Nullable; | 13 | import javax.annotation.Nullable; |
| 13 | import java.time.LocalDateTime; | 14 | import java.time.LocalDateTime; |
| 14 | import java.util.List; | 15 | import java.util.List; |
| 16 | +import java.util.Map; | ||
| 17 | +import java.util.stream.Collectors; | ||
| 15 | 18 | ||
| 16 | /** | 19 | /** |
| 17 | * IoT 设备 Mapper | 20 | * IoT 设备 Mapper |
| @@ -81,4 +84,18 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> { | @@ -81,4 +84,18 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> { | ||
| 81 | .eqIfPresent(IotDeviceDO::getState, state)); | 84 | .eqIfPresent(IotDeviceDO::getState, state)); |
| 82 | } | 85 | } |
| 83 | 86 | ||
| 87 | + /** | ||
| 88 | + * 查询指定产品下各状态的设备数量 | ||
| 89 | + * | ||
| 90 | + * @return 设备数量统计列表 | ||
| 91 | + */ | ||
| 92 | + List<Map<String, Object>> selectDeviceCountMapByProductId(); | ||
| 93 | + | ||
| 94 | + /** | ||
| 95 | + * 查询各个状态下的设备数量 | ||
| 96 | + * | ||
| 97 | + * @return 设备数量统计列表 | ||
| 98 | + */ | ||
| 99 | + List<Map<String, Object>> selectDeviceCountGroupByState(); | ||
| 100 | + | ||
| 84 | } | 101 | } |
| 85 | \ No newline at end of file | 102 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
| @@ -37,10 +37,5 @@ public interface IotProductMapper extends BaseMapperX<IotProductDO> { | @@ -37,10 +37,5 @@ public interface IotProductMapper extends BaseMapperX<IotProductDO> { | ||
| 37 | .geIfPresent(IotProductDO::getCreateTime, createTime)); | 37 | .geIfPresent(IotProductDO::getCreateTime, createTime)); |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | - default List<IotProductDO> selectListByCategoryId(Long categoryId) { | ||
| 41 | - return selectList(new LambdaQueryWrapperX<IotProductDO>() | ||
| 42 | - .eq(IotProductDO::getCategoryId, categoryId) | ||
| 43 | - .orderByDesc(IotProductDO::getId)); | ||
| 44 | - } | ||
| 45 | 40 | ||
| 46 | } | 41 | } |
| 47 | \ No newline at end of file | 42 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogMapper.java
| 1 | package cn.iocoder.yudao.module.iot.dal.tdengine; | 1 | package cn.iocoder.yudao.module.iot.dal.tdengine; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; | 3 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; |
| 4 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | ||
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; | 4 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; |
| 6 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; | 5 | import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS; |
| 7 | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; | 6 | import com.baomidou.mybatisplus.annotation.InterceptorIgnore; |
| @@ -10,6 +9,7 @@ import org.apache.ibatis.annotations.Mapper; | @@ -10,6 +9,7 @@ import org.apache.ibatis.annotations.Mapper; | ||
| 10 | import org.apache.ibatis.annotations.Param; | 9 | import org.apache.ibatis.annotations.Param; |
| 11 | 10 | ||
| 12 | import java.util.List; | 11 | import java.util.List; |
| 12 | +import java.util.Map; | ||
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | * 设备日志 {@link IotDeviceLogDO} Mapper 接口 | 15 | * 设备日志 {@link IotDeviceLogDO} Mapper 接口 |
| @@ -60,27 +60,17 @@ public interface IotDeviceLogMapper { | @@ -60,27 +60,17 @@ public interface IotDeviceLogMapper { | ||
| 60 | // TODO @super:1)上行、下行,不写在 mapper 里,而是通过参数传递,这样,selectDeviceLogUpCountByHour、selectDeviceLogDownCountByHour 可以合并; | 60 | // TODO @super:1)上行、下行,不写在 mapper 里,而是通过参数传递,这样,selectDeviceLogUpCountByHour、selectDeviceLogDownCountByHour 可以合并; |
| 61 | // TODO @super:2)不能只基于 identifier 来计算,而是要 type + identifier 成对 | 61 | // TODO @super:2)不能只基于 identifier 来计算,而是要 type + identifier 成对 |
| 62 | /** | 62 | /** |
| 63 | - * 获得每个小时设备上行消息数量统计 | ||
| 64 | - * | ||
| 65 | - * @param deviceKey 设备标识 | ||
| 66 | - * @param startTime 开始时间 | ||
| 67 | - * @param endTime 结束时间 | ||
| 68 | - * @return 每小时消息数量统计 | 63 | + * 查询每个小时设备上行消息数量 |
| 69 | */ | 64 | */ |
| 70 | - List<IotStatisticsRespVO.TimeData> selectDeviceLogUpCountByHour(@Param("deviceKey") String deviceKey, | ||
| 71 | - @Param("startTime") Long startTime, | ||
| 72 | - @Param("endTime") Long endTime); | 65 | + List<Map<String, Object>> selectDeviceLogUpCountByHour(@Param("deviceKey") String deviceKey, |
| 66 | + @Param("startTime") Long startTime, | ||
| 67 | + @Param("endTime") Long endTime); | ||
| 73 | 68 | ||
| 74 | /** | 69 | /** |
| 75 | - * 获得每个小时设备下行消息数量统计 | ||
| 76 | - * | ||
| 77 | - * @param deviceKey 设备标识 | ||
| 78 | - * @param startTime 开始时间 | ||
| 79 | - * @param endTime 结束时间 | ||
| 80 | - * @return 每小时消息数量统计 | 70 | + * 查询每个小时设备下行消息数量 |
| 81 | */ | 71 | */ |
| 82 | - List<IotStatisticsRespVO.TimeData> selectDeviceLogDownCountByHour(@Param("deviceKey") String deviceKey, | ||
| 83 | - @Param("startTime") Long startTime, | ||
| 84 | - @Param("endTime") Long endTime); | 72 | + List<Map<String, Object>> selectDeviceLogDownCountByHour(@Param("deviceKey") String deviceKey, |
| 73 | + @Param("startTime") Long startTime, | ||
| 74 | + @Param("endTime") Long endTime); | ||
| 85 | 75 | ||
| 86 | } | 76 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java
| @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.service.device; | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.service.device; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; | 4 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; |
| 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 5 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 6 | +import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum; | ||
| 6 | import jakarta.validation.Valid; | 7 | import jakarta.validation.Valid; |
| 7 | import jakarta.validation.constraints.NotEmpty; | 8 | import jakarta.validation.constraints.NotEmpty; |
| 8 | 9 | ||
| @@ -10,6 +11,7 @@ import javax.annotation.Nullable; | @@ -10,6 +11,7 @@ import javax.annotation.Nullable; | ||
| 10 | import java.time.LocalDateTime; | 11 | import java.time.LocalDateTime; |
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 14 | +import java.util.Map; | ||
| 13 | 15 | ||
| 14 | /** | 16 | /** |
| 15 | * IoT 设备 Service 接口 | 17 | * IoT 设备 Service 接口 |
| @@ -111,7 +113,7 @@ public interface IotDeviceService { | @@ -111,7 +113,7 @@ public interface IotDeviceService { | ||
| 111 | IotDeviceDO getDeviceByDeviceKey(String deviceKey); | 113 | IotDeviceDO getDeviceByDeviceKey(String deviceKey); |
| 112 | 114 | ||
| 113 | /** | 115 | /** |
| 114 | - * ��得设备分页 | 116 | + * 获得设备分页 |
| 115 | * | 117 | * |
| 116 | * @param pageReqVO 分页查询 | 118 | * @param pageReqVO 分页查询 |
| 117 | * @return IoT 设备分页 | 119 | * @return IoT 设备分页 |
| @@ -194,13 +196,6 @@ public interface IotDeviceService { | @@ -194,13 +196,6 @@ public interface IotDeviceService { | ||
| 194 | */ | 196 | */ |
| 195 | Long getDeviceCount(@Nullable LocalDateTime createTime); | 197 | Long getDeviceCount(@Nullable LocalDateTime createTime); |
| 196 | 198 | ||
| 197 | - /** | ||
| 198 | - * 获得设备数量,基于状态 | ||
| 199 | - * | ||
| 200 | - * @param state 状态 | ||
| 201 | - * @return 设备数量 | ||
| 202 | - */ | ||
| 203 | - Long getDeviceCountByState(Integer state); | ||
| 204 | 199 | ||
| 205 | /** | 200 | /** |
| 206 | * 获得所有设备列表 | 201 | * 获得所有设备列表 |
| @@ -217,4 +212,19 @@ public interface IotDeviceService { | @@ -217,4 +212,19 @@ public interface IotDeviceService { | ||
| 217 | */ | 212 | */ |
| 218 | IotDeviceMqttConnectionParamsRespVO getMqttConnectionParams(Long deviceId); | 213 | IotDeviceMqttConnectionParamsRespVO getMqttConnectionParams(Long deviceId); |
| 219 | 214 | ||
| 215 | + /** | ||
| 216 | + * 获得各个产品下的设备数量 Map | ||
| 217 | + * | ||
| 218 | + * @return key: 产品编号, value: 设备数量 | ||
| 219 | + */ | ||
| 220 | + Map<Long, Integer> getDeviceCountMapByProductId(); | ||
| 221 | + | ||
| 222 | + /** | ||
| 223 | + * 获得各个状态下的设备数量 Map | ||
| 224 | + * | ||
| 225 | + * @return key: 设备状态枚举 {@link IotDeviceStateEnum} | ||
| 226 | + * value: 设备数量 | ||
| 227 | + */ | ||
| 228 | + Map<Integer, Long> getDeviceCountMapByState(); | ||
| 229 | + | ||
| 220 | } | 230 | } |
| 221 | \ No newline at end of file | 231 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| @@ -35,6 +35,7 @@ import org.springframework.validation.annotation.Validated; | @@ -35,6 +35,7 @@ import org.springframework.validation.annotation.Validated; | ||
| 35 | import javax.annotation.Nullable; | 35 | import javax.annotation.Nullable; |
| 36 | import java.time.LocalDateTime; | 36 | import java.time.LocalDateTime; |
| 37 | import java.util.*; | 37 | import java.util.*; |
| 38 | +import java.util.stream.Collectors; | ||
| 38 | 39 | ||
| 39 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 40 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 40 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | 41 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; |
| @@ -430,14 +431,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -430,14 +431,30 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 430 | } | 431 | } |
| 431 | 432 | ||
| 432 | // TODO @super:是不是 groupby 查询,更高效;不过 controller,还是要考虑 null 的情况;不过可以直接枚举 foreach 处理下 | 433 | // TODO @super:是不是 groupby 查询,更高效;不过 controller,还是要考虑 null 的情况;不过可以直接枚举 foreach 处理下 |
| 433 | - @Override | ||
| 434 | - public Long getDeviceCountByState(Integer state) { | ||
| 435 | - return deviceMapper.selectCountByState(state); | ||
| 436 | - } | ||
| 437 | 434 | ||
| 438 | @Override | 435 | @Override |
| 439 | public List<IotDeviceDO> getDeviceList() { | 436 | public List<IotDeviceDO> getDeviceList() { |
| 440 | return deviceMapper.selectList(); | 437 | return deviceMapper.selectList(); |
| 441 | } | 438 | } |
| 442 | 439 | ||
| 440 | + @Override | ||
| 441 | + public Map<Long, Integer> getDeviceCountMapByProductId() { | ||
| 442 | + // 查询结果转换成Map | ||
| 443 | + List<Map<String, Object>> list = deviceMapper.selectDeviceCountMapByProductId(); | ||
| 444 | + return list.stream().collect(Collectors.toMap( | ||
| 445 | + map -> Long.valueOf(map.get("key").toString()), | ||
| 446 | + map -> Integer.valueOf(map.get("value").toString()) | ||
| 447 | + )); | ||
| 448 | + } | ||
| 449 | + | ||
| 450 | + @Override | ||
| 451 | + public Map<Integer, Long> getDeviceCountMapByState() { | ||
| 452 | + // 查询结果转换成Map | ||
| 453 | + List<Map<String, Object>> list = deviceMapper.selectDeviceCountGroupByState(); | ||
| 454 | + return list.stream().collect(Collectors.toMap( | ||
| 455 | + map -> Integer.valueOf(map.get("key").toString()), | ||
| 456 | + map -> Long.valueOf(map.get("value").toString()) | ||
| 457 | + )); | ||
| 458 | + } | ||
| 459 | + | ||
| 443 | } | 460 | } |
| 444 | \ No newline at end of file | 461 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDeviceLogService.java
| @@ -2,13 +2,14 @@ package cn.iocoder.yudao.module.iot.service.device.data; | @@ -2,13 +2,14 @@ package cn.iocoder.yudao.module.iot.service.device.data; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; | 4 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; |
| 5 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | 5 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO; |
| 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; |
| 7 | import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; | 7 | import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; |
| 8 | 8 | ||
| 9 | import javax.annotation.Nullable; | 9 | import javax.annotation.Nullable; |
| 10 | import java.time.LocalDateTime; | 10 | import java.time.LocalDateTime; |
| 11 | import java.util.List; | 11 | import java.util.List; |
| 12 | +import java.util.Map; | ||
| 12 | 13 | ||
| 13 | /** | 14 | /** |
| 14 | * IoT 设备日志数据 Service 接口 | 15 | * IoT 设备日志数据 Service 接口 |
| @@ -50,25 +51,25 @@ public interface IotDeviceLogService { | @@ -50,25 +51,25 @@ public interface IotDeviceLogService { | ||
| 50 | /** | 51 | /** |
| 51 | * 获得每个小时设备上行消息数量统计 | 52 | * 获得每个小时设备上行消息数量统计 |
| 52 | * | 53 | * |
| 53 | - * @param deviceKey 设备标识,如果为空,则统计所有设备 | ||
| 54 | - * @param startTime 开始时间,如果为空,则不限制开始时间 | ||
| 55 | - * @param endTime 结束时间,如果为空,则不限制结束时间 | ||
| 56 | - * @return 每小时消息数量统计列表 | 54 | + * @param deviceKey 设备标识 |
| 55 | + * @param startTime 开始时间 | ||
| 56 | + * @param endTime 结束时间 | ||
| 57 | + * @return key: 时间戳, value: 消息数量 | ||
| 57 | */ | 58 | */ |
| 58 | - List<IotStatisticsRespVO.TimeData> getDeviceLogUpCountByHour(@Nullable String deviceKey, | ||
| 59 | - @Nullable Long startTime, | ||
| 60 | - @Nullable Long endTime); | 59 | + List<Map<Long, Integer>> getDeviceLogUpCountByHour(@Nullable String deviceKey, |
| 60 | + @Nullable Long startTime, | ||
| 61 | + @Nullable Long endTime); | ||
| 61 | 62 | ||
| 62 | /** | 63 | /** |
| 63 | * 获得每个小时设备下行消息数量统计 | 64 | * 获得每个小时设备下行消息数量统计 |
| 64 | * | 65 | * |
| 65 | - * @param deviceKey 设备标识,如果为空,则统计所有设备 | ||
| 66 | - * @param startTime 开始时间,如果为空,则不限制开始时间 | ||
| 67 | - * @param endTime 结束时间,如果为空,则不限制结束时间 | ||
| 68 | - * @return 每小时消息数量统计列表 | 66 | + * @param deviceKey 设备标识 |
| 67 | + * @param startTime 开始时间 | ||
| 68 | + * @param endTime 结束时间 | ||
| 69 | + * @return key: 时间戳, value: 消息数量 | ||
| 69 | */ | 70 | */ |
| 70 | - List<IotStatisticsRespVO.TimeData> getDeviceLogDownCountByHour(@Nullable String deviceKey, | ||
| 71 | - @Nullable Long startTime, | ||
| 72 | - @Nullable Long endTime); | 71 | + List<Map<Long, Integer>> getDeviceLogDownCountByHour(@Nullable String deviceKey, |
| 72 | + @Nullable Long startTime, | ||
| 73 | + @Nullable Long endTime); | ||
| 73 | 74 | ||
| 74 | } | 75 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDeviceLogServiceImpl.java
| 1 | package cn.iocoder.yudao.module.iot.service.device.data; | 1 | package cn.iocoder.yudao.module.iot.service.device.data; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.date.LocalDateTimeUtil; | ||
| 3 | import cn.hutool.core.util.IdUtil; | 4 | import cn.hutool.core.util.IdUtil; |
| 4 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 6 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 7 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 8 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; | 9 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO; |
| 9 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | 10 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryRespVO; |
| 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; | 11 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO; |
| 11 | import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogMapper; | 12 | import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogMapper; |
| 12 | import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; | 13 | import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage; |
| @@ -17,10 +18,11 @@ import lombok.extern.slf4j.Slf4j; | @@ -17,10 +18,11 @@ import lombok.extern.slf4j.Slf4j; | ||
| 17 | import org.springframework.stereotype.Service; | 18 | import org.springframework.stereotype.Service; |
| 18 | import org.springframework.validation.annotation.Validated; | 19 | import org.springframework.validation.annotation.Validated; |
| 19 | 20 | ||
| 21 | +import java.sql.Timestamp; | ||
| 20 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 21 | -import java.time.ZoneOffset; | ||
| 22 | -import java.util.ArrayList; | ||
| 23 | import java.util.List; | 23 | import java.util.List; |
| 24 | +import java.util.Map; | ||
| 25 | +import java.util.stream.Collectors; | ||
| 24 | 26 | ||
| 25 | /** | 27 | /** |
| 26 | * IoT 设备日志数据 Service 实现类 | 28 | * IoT 设备日志数据 Service 实现类 |
| @@ -71,37 +73,39 @@ public class IotDeviceLogServiceImpl implements IotDeviceLogService { | @@ -71,37 +73,39 @@ public class IotDeviceLogServiceImpl implements IotDeviceLogService { | ||
| 71 | 73 | ||
| 72 | @Override | 74 | @Override |
| 73 | public Long getDeviceLogCount(LocalDateTime createTime) { | 75 | public Long getDeviceLogCount(LocalDateTime createTime) { |
| 74 | - Long time = null; | ||
| 75 | - if (createTime != null) { | ||
| 76 | // todo @super:1)LocalDateTimeUtil.toEpochMilli(createTime);2)直接表达式,更简洁 time != null ? createTime.toInstant(ZoneOffset.UTC).toEpochMilli() : null; | 76 | // todo @super:1)LocalDateTimeUtil.toEpochMilli(createTime);2)直接表达式,更简洁 time != null ? createTime.toInstant(ZoneOffset.UTC).toEpochMilli() : null; |
| 77 | - time = createTime.toInstant(ZoneOffset.UTC).toEpochMilli(); | ||
| 78 | - } | ||
| 79 | - return deviceLogMapper.selectCountByCreateTime(time); | 77 | + return deviceLogMapper.selectCountByCreateTime(createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null); |
| 80 | } | 78 | } |
| 81 | 79 | ||
| 82 | // TODO @super:加一个参数,Boolean upstream:true 上行,false 下行,null 不过滤 | 80 | // TODO @super:加一个参数,Boolean upstream:true 上行,false 下行,null 不过滤 |
| 83 | @Override | 81 | @Override |
| 84 | - public List<IotStatisticsRespVO.TimeData> getDeviceLogUpCountByHour(String deviceKey, Long startTime, Long endTime) { | ||
| 85 | - try { | ||
| 86 | - return deviceLogMapper.selectDeviceLogUpCountByHour(deviceKey, startTime, endTime); | ||
| 87 | - } catch (Exception exception) { | ||
| 88 | - if (exception.getMessage().contains("Table does not exist")) { | ||
| 89 | - return new ArrayList<>(); | ||
| 90 | - } | ||
| 91 | - throw exception; | ||
| 92 | - } | 82 | + public List<Map<Long, Integer>> getDeviceLogUpCountByHour(String deviceKey, Long startTime, Long endTime) { |
| 83 | + List<Map<String, Object>> list = deviceLogMapper.selectDeviceLogUpCountByHour(deviceKey, startTime, endTime); | ||
| 84 | + return list.stream() | ||
| 85 | + .map(map -> { | ||
| 86 | + // 从Timestamp获取时间戳 | ||
| 87 | + Timestamp timestamp = (Timestamp) map.get("time"); | ||
| 88 | + Long timeMillis = timestamp.getTime(); | ||
| 89 | + // 消息数量转换 | ||
| 90 | + Integer count = ((Number) map.get("data")).intValue(); | ||
| 91 | + return Map.of(timeMillis, count); | ||
| 92 | + }) | ||
| 93 | + .collect(Collectors.toList()); | ||
| 93 | } | 94 | } |
| 94 | 95 | ||
| 95 | @Override | 96 | @Override |
| 96 | - public List<IotStatisticsRespVO.TimeData> getDeviceLogDownCountByHour(String deviceKey, Long startTime, Long endTime) { | ||
| 97 | - try { | ||
| 98 | - return deviceLogMapper.selectDeviceLogDownCountByHour(deviceKey, startTime, endTime); | ||
| 99 | - } catch (Exception exception) { | ||
| 100 | - if (exception.getMessage().contains("Table does not exist")) { | ||
| 101 | - return new ArrayList<>(); | ||
| 102 | - } | ||
| 103 | - throw exception; | ||
| 104 | - } | 97 | + public List<Map<Long, Integer>> getDeviceLogDownCountByHour(String deviceKey, Long startTime, Long endTime) { |
| 98 | + List<Map<String, Object>> list = deviceLogMapper.selectDeviceLogDownCountByHour(deviceKey, startTime, endTime); | ||
| 99 | + return list.stream() | ||
| 100 | + .map(map -> { | ||
| 101 | + // 从Timestamp获取时间戳 | ||
| 102 | + Timestamp timestamp = (Timestamp) map.get("time"); | ||
| 103 | + Long timeMillis = timestamp.getTime(); | ||
| 104 | + // 消息数量转换 | ||
| 105 | + Integer count = ((Number) map.get("data")).intValue(); | ||
| 106 | + return Map.of(timeMillis, count); | ||
| 107 | + }) | ||
| 108 | + .collect(Collectors.toList()); | ||
| 105 | } | 109 | } |
| 106 | 110 | ||
| 107 | } | 111 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.product; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.product; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; | 4 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; |
| 5 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; | 5 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; |
| 6 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | ||
| 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; | 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; |
| 8 | import jakarta.validation.Valid; | 7 | import jakarta.validation.Valid; |
| 9 | 8 | ||
| @@ -100,6 +99,6 @@ public interface IotProductCategoryService { | @@ -100,6 +99,6 @@ public interface IotProductCategoryService { | ||
| 100 | * | 99 | * |
| 101 | * @return 品类设备统计列表 | 100 | * @return 品类设备统计列表 |
| 102 | */ | 101 | */ |
| 103 | - List<IotStatisticsRespVO.DataItem> getDeviceCountsOfProductCategory(); | 102 | + Map<String, Integer> getProductCategoryDeviceCountMap(); |
| 104 | 103 | ||
| 105 | } | 104 | } |
| 106 | \ No newline at end of file | 105 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java
| @@ -5,8 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | @@ -5,8 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 5 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 6 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; | 6 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO; |
| 7 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; | 7 | import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO; |
| 8 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO; | ||
| 9 | -import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | ||
| 10 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO; |
| 11 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | 9 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| 12 | import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; | 10 | import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper; |
| @@ -16,11 +14,7 @@ import org.springframework.stereotype.Service; | @@ -16,11 +14,7 @@ import org.springframework.stereotype.Service; | ||
| 16 | import org.springframework.validation.annotation.Validated; | 14 | import org.springframework.validation.annotation.Validated; |
| 17 | 15 | ||
| 18 | import java.time.LocalDateTime; | 16 | import java.time.LocalDateTime; |
| 19 | -import java.util.Collection; | ||
| 20 | -import java.util.HashMap; | ||
| 21 | -import java.util.List; | ||
| 22 | -import java.util.Map; | ||
| 23 | -import java.util.stream.Collectors; | 17 | +import java.util.*; |
| 24 | 18 | ||
| 25 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; | 20 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS; |
| @@ -103,54 +97,30 @@ public class IotProductCategoryServiceImpl implements IotProductCategoryService | @@ -103,54 +97,30 @@ public class IotProductCategoryServiceImpl implements IotProductCategoryService | ||
| 103 | } | 97 | } |
| 104 | 98 | ||
| 105 | @Override | 99 | @Override |
| 106 | - public List<IotStatisticsRespVO.DataItem> getDeviceCountsOfProductCategory() { | 100 | + public Map<String, Integer> getProductCategoryDeviceCountMap() { |
| 107 | // 1. 获取所有数据 | 101 | // 1. 获取所有数据 |
| 108 | List<IotProductCategoryDO> categoryList = productCategoryMapper.selectList(); | 102 | List<IotProductCategoryDO> categoryList = productCategoryMapper.selectList(); |
| 109 | List<IotProductDO> productList = productService.getProductList(); | 103 | List<IotProductDO> productList = productService.getProductList(); |
| 110 | // TODO @super:不要 list 查询,返回内存,而是查询一个 Map<productId, count> | 104 | // TODO @super:不要 list 查询,返回内存,而是查询一个 Map<productId, count> |
| 111 | - List<IotDeviceDO> deviceList = deviceService.getDeviceList(); | 105 | + Map<Long, Integer> deviceCountMapByProductId = deviceService.getDeviceCountMapByProductId(); |
| 112 | 106 | ||
| 113 | // 2. 统计每个分类下的设备数量 | 107 | // 2. 统计每个分类下的设备数量 |
| 114 | Map<String, Integer> categoryDeviceCountMap = new HashMap<>(); | 108 | Map<String, Integer> categoryDeviceCountMap = new HashMap<>(); |
| 115 | - | 109 | + |
| 116 | // 2.1 初始化所有分类的计数为0 | 110 | // 2.1 初始化所有分类的计数为0 |
| 117 | for (IotProductCategoryDO category : categoryList) { | 111 | for (IotProductCategoryDO category : categoryList) { |
| 118 | categoryDeviceCountMap.put(category.getName(), 0); | 112 | categoryDeviceCountMap.put(category.getName(), 0); |
| 119 | - // TODO @super:直接这里面计算,不用多个循环。产品本身也不多,不用构建 Map,直接 filter 就好了 | ||
| 120 | - } | ||
| 121 | - | ||
| 122 | - // 2.2 构建产品ID到分类的映射 | ||
| 123 | - Map<Long, IotProductCategoryDO> productCategoryMap = new HashMap<>(); | ||
| 124 | - for (IotProductDO product : productList) { | ||
| 125 | - Long categoryId = product.getCategoryId(); | ||
| 126 | - IotProductCategoryDO category = categoryList.stream() | ||
| 127 | - .filter(c -> c.getId().equals(categoryId)) | ||
| 128 | - .findFirst() | ||
| 129 | - .orElse(null); | ||
| 130 | - if (category != null) { | ||
| 131 | - productCategoryMap.put(product.getId(), category); | ||
| 132 | - } | ||
| 133 | - } | ||
| 134 | - | ||
| 135 | - // 2.3 统计每个分类下的设备数量 | ||
| 136 | - for (IotDeviceDO device : deviceList) { | ||
| 137 | - Long productId = device.getProductId(); | ||
| 138 | - IotProductCategoryDO category = productCategoryMap.get(productId); | ||
| 139 | - if (category != null) { | ||
| 140 | - String categoryName = category.getName(); | ||
| 141 | - categoryDeviceCountMap.merge(categoryName, 1, Integer::sum); | 113 | + |
| 114 | + // 2.2 找到该分类下的所有产品,累加设备数量 | ||
| 115 | + for (IotProductDO product : productList) { | ||
| 116 | + if (Objects.equals(product.getCategoryId(), category.getId())) { | ||
| 117 | + Integer deviceCount = deviceCountMapByProductId.getOrDefault(product.getId(), 0); | ||
| 118 | + categoryDeviceCountMap.merge(category.getName(), deviceCount, Integer::sum); | ||
| 119 | + } | ||
| 142 | } | 120 | } |
| 143 | } | 121 | } |
| 144 | 122 | ||
| 145 | - // 3. 转换为 DataItem 列表 | ||
| 146 | - return categoryDeviceCountMap.entrySet().stream() | ||
| 147 | - .map(entry -> { | ||
| 148 | - IotStatisticsRespVO.DataItem dataItem = new IotStatisticsRespVO.DataItem(); | ||
| 149 | - dataItem.setName(entry.getKey()); | ||
| 150 | - dataItem.setValue(entry.getValue()); | ||
| 151 | - return dataItem; | ||
| 152 | - }) | ||
| 153 | - .collect(Collectors.toList()); | 123 | + return categoryDeviceCountMap; |
| 154 | } | 124 | } |
| 155 | 125 | ||
| 156 | } | 126 | } |
| 157 | \ No newline at end of file | 127 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
| @@ -102,13 +102,5 @@ public interface IotProductService { | @@ -102,13 +102,5 @@ public interface IotProductService { | ||
| 102 | */ | 102 | */ |
| 103 | Long getProductCount(@Nullable LocalDateTime createTime); | 103 | Long getProductCount(@Nullable LocalDateTime createTime); |
| 104 | 104 | ||
| 105 | - // TODO @super:用不到的,删除下哈 | ||
| 106 | - /** | ||
| 107 | - * 获得产品列表,基于分类编号 | ||
| 108 | - * | ||
| 109 | - * @param categoryId 分类编号 | ||
| 110 | - * @return 产品列表 | ||
| 111 | - */ | ||
| 112 | - List<IotProductDO> getProductListByCategoryId(Long categoryId); | ||
| 113 | 105 | ||
| 114 | } | 106 | } |
| 115 | \ No newline at end of file | 107 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
| @@ -143,9 +143,5 @@ public class IotProductServiceImpl implements IotProductService { | @@ -143,9 +143,5 @@ public class IotProductServiceImpl implements IotProductService { | ||
| 143 | return productMapper.selectCountByCreateTime(createTime); | 143 | return productMapper.selectCountByCreateTime(createTime); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | - @Override | ||
| 147 | - public List<IotProductDO> getProductListByCategoryId(Long categoryId) { | ||
| 148 | - return productMapper.selectListByCategoryId(categoryId); | ||
| 149 | - } | ||
| 150 | 146 | ||
| 151 | } | 147 | } |
| 152 | \ No newline at end of file | 148 | \ No newline at end of file |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogMapper.xml
| @@ -65,7 +65,7 @@ | @@ -65,7 +65,7 @@ | ||
| 65 | </where> | 65 | </where> |
| 66 | </select> | 66 | </select> |
| 67 | 67 | ||
| 68 | - <select id="selectDeviceLogUpCountByHour" resultType="cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO$TimeData"> | 68 | + <select id="selectDeviceLogUpCountByHour" resultType="java.util.Map"> |
| 69 | SELECT | 69 | SELECT |
| 70 | TIMETRUNCATE(ts, 1h) as time, | 70 | TIMETRUNCATE(ts, 1h) as time, |
| 71 | COUNT(*) as data | 71 | COUNT(*) as data |
| @@ -93,7 +93,7 @@ | @@ -93,7 +93,7 @@ | ||
| 93 | ORDER BY time ASC | 93 | ORDER BY time ASC |
| 94 | </select> | 94 | </select> |
| 95 | 95 | ||
| 96 | - <select id="selectDeviceLogDownCountByHour" resultType="cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO$TimeData"> | 96 | + <select id="selectDeviceLogDownCountByHour" resultType="java.util.Map"> |
| 97 | SELECT | 97 | SELECT |
| 98 | TIMETRUNCATE(ts, 1h) as time, | 98 | TIMETRUNCATE(ts, 1h) as time, |
| 99 | COUNT(*) as data | 99 | COUNT(*) as data |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceMapper.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | +<!DOCTYPE mapper | ||
| 3 | + PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" | ||
| 4 | + "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | ||
| 5 | +<mapper namespace="cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper"> | ||
| 6 | + | ||
| 7 | + <select id="selectDeviceCountGroupByState" resultType="java.util.Map"> | ||
| 8 | + SELECT | ||
| 9 | + state AS `key`, | ||
| 10 | + COUNT(1) AS `value` | ||
| 11 | + FROM iot_device | ||
| 12 | + WHERE deleted = 0 | ||
| 13 | + GROUP BY state | ||
| 14 | + </select> | ||
| 15 | + | ||
| 16 | + <select id="selectDeviceCountMapByProductId" resultType="java.util.Map"> | ||
| 17 | + SELECT | ||
| 18 | + product_id AS `key`, | ||
| 19 | + COUNT(1) AS `value` | ||
| 20 | + FROM iot_device | ||
| 21 | + WHERE deleted = 0 | ||
| 22 | + GROUP BY product_id | ||
| 23 | + </select> | ||
| 24 | + | ||
| 25 | +</mapper> | ||
| 0 | \ No newline at end of file | 26 | \ No newline at end of file |