Commit 0f0ebda4692da2044ca6b27c44de5de45e5e91da

Authored by alwayssuper
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&lt;IotDeviceDO&gt; { @@ -81,4 +84,18 @@ public interface IotDeviceMapper extends BaseMapperX&lt;IotDeviceDO&gt; {
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&lt;IotProductDO&gt; { @@ -37,10 +37,5 @@ public interface IotProductMapper extends BaseMapperX&lt;IotProductDO&gt; {
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