Commit d70c6986d588f09e2c4784c2e3dbbc6714f299bb
1 parent
6a06f520
feat:【IoT 物联网】设备消息统计的代码优化
Showing
15 changed files
with
173 additions
and
247 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/DateIntervalEnum.java
| @@ -16,6 +16,7 @@ import java.util.Arrays; | @@ -16,6 +16,7 @@ import java.util.Arrays; | ||
| 16 | @AllArgsConstructor | 16 | @AllArgsConstructor |
| 17 | public enum DateIntervalEnum implements ArrayValuable<Integer> { | 17 | public enum DateIntervalEnum implements ArrayValuable<Integer> { |
| 18 | 18 | ||
| 19 | + HOUR(0, "小时"), // 特殊:字典里,暂时不会有这个枚举!!!因为大多数情况下,用不到这个间隔 | ||
| 19 | DAY(1, "天"), | 20 | DAY(1, "天"), |
| 20 | WEEK(2, "周"), | 21 | WEEK(2, "周"), |
| 21 | MONTH(3, "月"), | 22 | MONTH(3, "月"), |
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
| @@ -8,6 +8,7 @@ import cn.hutool.core.lang.Assert; | @@ -8,6 +8,7 @@ import cn.hutool.core.lang.Assert; | ||
| 8 | import cn.hutool.core.util.StrUtil; | 8 | import cn.hutool.core.util.StrUtil; |
| 9 | import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; | 9 | import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; |
| 10 | 10 | ||
| 11 | +import java.sql.Timestamp; | ||
| 11 | import java.time.*; | 12 | import java.time.*; |
| 12 | import java.time.format.DateTimeFormatter; | 13 | import java.time.format.DateTimeFormatter; |
| 13 | import java.time.format.DateTimeParseException; | 14 | import java.time.format.DateTimeParseException; |
| @@ -16,8 +17,7 @@ import java.time.temporal.TemporalAdjusters; | @@ -16,8 +17,7 @@ import java.time.temporal.TemporalAdjusters; | ||
| 16 | import java.util.ArrayList; | 17 | import java.util.ArrayList; |
| 17 | import java.util.List; | 18 | import java.util.List; |
| 18 | 19 | ||
| 19 | -import static cn.hutool.core.date.DatePattern.UTC_MS_WITH_XXX_OFFSET_PATTERN; | ||
| 20 | -import static cn.hutool.core.date.DatePattern.createFormatter; | 20 | +import static cn.hutool.core.date.DatePattern.*; |
| 21 | 21 | ||
| 22 | /** | 22 | /** |
| 23 | * 时间工具类,用于 {@link java.time.LocalDateTime} | 23 | * 时间工具类,用于 {@link java.time.LocalDateTime} |
| @@ -90,6 +90,21 @@ public class LocalDateTimeUtils { | @@ -90,6 +90,21 @@ public class LocalDateTimeUtils { | ||
| 90 | * @param time 指定时间 | 90 | * @param time 指定时间 |
| 91 | * @return 是否 | 91 | * @return 是否 |
| 92 | */ | 92 | */ |
| 93 | + public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, Timestamp time) { | ||
| 94 | + if (startTime == null || endTime == null || time == null) { | ||
| 95 | + return false; | ||
| 96 | + } | ||
| 97 | + return LocalDateTimeUtil.isIn(LocalDateTimeUtil.of(time), startTime, endTime); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + /** | ||
| 101 | + * 判指定断时间,是否在该时间范围内 | ||
| 102 | + * | ||
| 103 | + * @param startTime 开始时间 | ||
| 104 | + * @param endTime 结束时间 | ||
| 105 | + * @param time 指定时间 | ||
| 106 | + * @return 是否 | ||
| 107 | + */ | ||
| 93 | public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, String time) { | 108 | public static boolean isBetween(LocalDateTime startTime, LocalDateTime endTime, String time) { |
| 94 | if (startTime == null || endTime == null || time == null) { | 109 | if (startTime == null || endTime == null || time == null) { |
| 95 | return false; | 110 | return false; |
| @@ -234,6 +249,11 @@ public class LocalDateTimeUtils { | @@ -234,6 +249,11 @@ public class LocalDateTimeUtils { | ||
| 234 | // 2. 循环,生成时间范围 | 249 | // 2. 循环,生成时间范围 |
| 235 | List<LocalDateTime[]> timeRanges = new ArrayList<>(); | 250 | List<LocalDateTime[]> timeRanges = new ArrayList<>(); |
| 236 | switch (intervalEnum) { | 251 | switch (intervalEnum) { |
| 252 | + case HOUR: | ||
| 253 | + while (startTime.isBefore(endTime)) { | ||
| 254 | + timeRanges.add(new LocalDateTime[]{startTime, startTime.plusHours(1).minusNanos(1)}); | ||
| 255 | + startTime = startTime.plusHours(1); | ||
| 256 | + } | ||
| 237 | case DAY: | 257 | case DAY: |
| 238 | while (startTime.isBefore(endTime)) { | 258 | while (startTime.isBefore(endTime)) { |
| 239 | timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)}); | 259 | timeRanges.add(new LocalDateTime[]{startTime, startTime.plusDays(1).minusNanos(1)}); |
| @@ -297,6 +317,8 @@ public class LocalDateTimeUtils { | @@ -297,6 +317,8 @@ public class LocalDateTimeUtils { | ||
| 297 | 317 | ||
| 298 | // 2. 循环,生成时间范围 | 318 | // 2. 循环,生成时间范围 |
| 299 | switch (intervalEnum) { | 319 | switch (intervalEnum) { |
| 320 | + case HOUR: | ||
| 321 | + return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATETIME_MINUTE_PATTERN); | ||
| 300 | case DAY: | 322 | case DAY: |
| 301 | return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN); | 323 | return LocalDateTimeUtil.format(startTime, DatePattern.NORM_DATE_PATTERN); |
| 302 | case WEEK: | 324 | case WEEK: |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/IotStatisticsController.http
0 → 100644
| 1 | +### 请求 /iot/statistics/get-device-message-summary-by-date 接口(小时) | ||
| 2 | +GET {{baseUrl}}/iot/statistics/get-device-message-summary-by-date?interval=0×[0]=2025-06-13 00:00:00×[1]=2025-06-14 23:59:59 | ||
| 3 | +Content-Type: application/json | ||
| 4 | +tenant-id: {{adminTenantId}} | ||
| 5 | +Authorization: Bearer {{token}} | ||
| 6 | + | ||
| 7 | +### 请求 /iot/statistics/get-device-message-summary-by-date 接口(天) | ||
| 8 | +GET {{baseUrl}}/iot/statistics/get-device-message-summary-by-date?interval=1×[0]=2025-06-13 00:00:00×[1]=2025-06-14 23:59:59 | ||
| 9 | +Content-Type: application/json | ||
| 10 | +tenant-id: {{adminTenantId}} | ||
| 11 | +Authorization: Bearer {{token}} |
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; | ||
| 5 | -import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsReqVO; | 4 | +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; |
| 5 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryByDateRespVO; | ||
| 6 | import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO; | 7 | import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsSummaryRespVO; |
| 7 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; | 8 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; |
| 8 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; | 9 | import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; |
| 9 | -import cn.iocoder.yudao.module.iot.service.device.property.IotDeviceLogService; | 10 | +import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; |
| 10 | import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; | 11 | import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService; |
| 11 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 12 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 12 | import io.swagger.v3.oas.annotations.Operation; | 13 | import io.swagger.v3.oas.annotations.Operation; |
| @@ -19,9 +20,10 @@ import org.springframework.web.bind.annotation.RequestMapping; | @@ -19,9 +20,10 @@ import org.springframework.web.bind.annotation.RequestMapping; | ||
| 19 | import org.springframework.web.bind.annotation.RestController; | 20 | import org.springframework.web.bind.annotation.RestController; |
| 20 | 21 | ||
| 21 | import java.time.LocalDateTime; | 22 | import java.time.LocalDateTime; |
| 23 | +import java.util.List; | ||
| 22 | import java.util.Map; | 24 | import java.util.Map; |
| 23 | 25 | ||
| 24 | -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.*; | 26 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 25 | 27 | ||
| 26 | @Tag(name = "管理后台 - IoT 数据统计") | 28 | @Tag(name = "管理后台 - IoT 数据统计") |
| 27 | @RestController | 29 | @RestController |
| @@ -36,24 +38,23 @@ public class IotStatisticsController { | @@ -36,24 +38,23 @@ public class IotStatisticsController { | ||
| 36 | @Resource | 38 | @Resource |
| 37 | private IotProductService productService; | 39 | private IotProductService productService; |
| 38 | @Resource | 40 | @Resource |
| 39 | - private IotDeviceLogService deviceLogService; | 41 | + private IotDeviceMessageService deviceMessageService; |
| 40 | 42 | ||
| 41 | @GetMapping("/get-summary") | 43 | @GetMapping("/get-summary") |
| 42 | - @Operation(summary = "获取 IoT 数据统计") | ||
| 43 | - public CommonResult<IotStatisticsSummaryRespVO> getIotStatisticsSummary(){ | 44 | + @Operation(summary = "获取全局的数据统计") |
| 45 | + public CommonResult<IotStatisticsSummaryRespVO> getStatisticsSummary(){ | ||
| 44 | IotStatisticsSummaryRespVO respVO = new IotStatisticsSummaryRespVO(); | 46 | IotStatisticsSummaryRespVO respVO = new IotStatisticsSummaryRespVO(); |
| 45 | // 1.1 获取总数 | 47 | // 1.1 获取总数 |
| 46 | respVO.setProductCategoryCount(productCategoryService.getProductCategoryCount(null)); | 48 | respVO.setProductCategoryCount(productCategoryService.getProductCategoryCount(null)); |
| 47 | respVO.setProductCount(productService.getProductCount(null)); | 49 | respVO.setProductCount(productService.getProductCount(null)); |
| 48 | respVO.setDeviceCount(deviceService.getDeviceCount(null)); | 50 | respVO.setDeviceCount(deviceService.getDeviceCount(null)); |
| 49 | - respVO.setDeviceMessageCount(deviceLogService.getDeviceLogCount(null)); | 51 | + respVO.setDeviceMessageCount(deviceMessageService.getDeviceMessageCount(null)); |
| 50 | // 1.2 获取今日新增数量 | 52 | // 1.2 获取今日新增数量 |
| 51 | - // TODO @super:使用 LocalDateTimeUtils.getToday() | ||
| 52 | - LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0); | 53 | + LocalDateTime todayStart = LocalDateTimeUtils.getToday(); |
| 53 | respVO.setProductCategoryTodayCount(productCategoryService.getProductCategoryCount(todayStart)); | 54 | respVO.setProductCategoryTodayCount(productCategoryService.getProductCategoryCount(todayStart)); |
| 54 | respVO.setProductTodayCount(productService.getProductCount(todayStart)); | 55 | respVO.setProductTodayCount(productService.getProductCount(todayStart)); |
| 55 | respVO.setDeviceTodayCount(deviceService.getDeviceCount(todayStart)); | 56 | respVO.setDeviceTodayCount(deviceService.getDeviceCount(todayStart)); |
| 56 | - respVO.setDeviceMessageTodayCount(deviceLogService.getDeviceLogCount(todayStart)); | 57 | + respVO.setDeviceMessageTodayCount(deviceMessageService.getDeviceMessageCount(todayStart)); |
| 57 | 58 | ||
| 58 | // 2. 获取各个品类下设备数量统计 | 59 | // 2. 获取各个品类下设备数量统计 |
| 59 | respVO.setProductCategoryDeviceCounts(productCategoryService.getProductCategoryDeviceCountMap()); | 60 | respVO.setProductCategoryDeviceCounts(productCategoryService.getProductCategoryDeviceCountMap()); |
| @@ -66,14 +67,11 @@ public class IotStatisticsController { | @@ -66,14 +67,11 @@ public class IotStatisticsController { | ||
| 66 | return success(respVO); | 67 | return success(respVO); |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | - // TODO @super:要不干掉 IotStatisticsReqVO 参数,直接使用 @RequestParam 接收,简单一些。 | ||
| 70 | - @GetMapping("/get-log-summary") | ||
| 71 | - @Operation(summary = "获取 IoT 设备上下行消息数据统计") | ||
| 72 | - public CommonResult<IotStatisticsDeviceMessageSummaryRespVO> getIotStatisticsDeviceMessageSummary( | ||
| 73 | - @Valid IotStatisticsReqVO reqVO) { | ||
| 74 | - return success(new IotStatisticsDeviceMessageSummaryRespVO() | ||
| 75 | - .setDownstreamCounts(deviceLogService.getDeviceLogUpCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())) | ||
| 76 | - .setDownstreamCounts((deviceLogService.getDeviceLogDownCountByHour(null, reqVO.getStartTime(), reqVO.getEndTime())))); | 70 | + @GetMapping("/get-device-message-summary-by-date") |
| 71 | + @Operation(summary = "获取设备消息的数据统计") | ||
| 72 | + public CommonResult<List<IotStatisticsDeviceMessageSummaryByDateRespVO>> getDeviceMessageSummaryByDate( | ||
| 73 | + @Valid IotStatisticsDeviceMessageReqVO reqVO) { | ||
| 74 | + return success(deviceMessageService.getDeviceMessageSummaryByDate(reqVO)); | ||
| 77 | } | 75 | } |
| 78 | 76 | ||
| 79 | } | 77 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsDeviceMessageReqVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; | ||
| 4 | +import cn.iocoder.yudao.framework.common.validation.InEnum; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.constraints.Size; | ||
| 7 | +import lombok.Data; | ||
| 8 | +import org.springframework.format.annotation.DateTimeFormat; | ||
| 9 | + | ||
| 10 | +import java.time.LocalDateTime; | ||
| 11 | + | ||
| 12 | +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; | ||
| 13 | + | ||
| 14 | +@Schema(description = "管理后台 - IoT 设备消息数量统计 Response VO") | ||
| 15 | +@Data | ||
| 16 | +public class IotStatisticsDeviceMessageReqVO { | ||
| 17 | + | ||
| 18 | + @Schema(description = "时间间隔类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") | ||
| 19 | + @InEnum(value = DateIntervalEnum.class, message = "时间间隔类型,必须是 {value}") | ||
| 20 | + private Integer interval; | ||
| 21 | + | ||
| 22 | + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.NOT_REQUIRED) | ||
| 23 | + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) | ||
| 24 | + @Size(min = 2, max = 2, message = "请选择时间范围") | ||
| 25 | + private LocalDateTime[] times; | ||
| 26 | + | ||
| 27 | +} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsDeviceMessageSummaryByDateRespVO.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 | +@Schema(description = "管理后台 - IoT 设备消息数量统计 Response VO") | ||
| 7 | +@Data | ||
| 8 | +public class IotStatisticsDeviceMessageSummaryByDateRespVO { | ||
| 9 | + | ||
| 10 | + @Schema(description = "时间轴", requiredMode = Schema.RequiredMode.REQUIRED, example = "202401") | ||
| 11 | + private String time; | ||
| 12 | + | ||
| 13 | + @Schema(description = "上行消息数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") | ||
| 14 | + private Integer upstreamCount; | ||
| 15 | + | ||
| 16 | + @Schema(description = "上行消息数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") | ||
| 17 | + private Integer downstreamCount; | ||
| 18 | + | ||
| 19 | +} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsDeviceMessageSummaryRespVO.java deleted
| 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 | - | ||
| 13 | - @Schema(description = "每小时上行数据数量统计") | ||
| 14 | - private List<Map<Long, Integer>> upstreamCounts; | ||
| 15 | - | ||
| 16 | - @Schema(description = "每小时下行数据数量统计") | ||
| 17 | - private List<Map<Long, Integer>> downstreamCounts; | ||
| 18 | - | ||
| 19 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/vo/IotStatisticsReqVO.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.controller.admin.statistics.vo; | ||
| 2 | - | ||
| 3 | -import io.swagger.v3.oas.annotations.media.Schema; | ||
| 4 | -import jakarta.validation.constraints.NotNull; | ||
| 5 | -import lombok.Data; | ||
| 6 | - | ||
| 7 | -@Schema(description = "管理后台 - IoT 统计 Request VO") | ||
| 8 | -@Data | ||
| 9 | -public class IotStatisticsReqVO { | ||
| 10 | - | ||
| 11 | - // TODO @super:前端传递的时候,还是通过 startTime 和 endTime 传递。后端转成 Long | ||
| 12 | - | ||
| 13 | - @Schema(description = "查询起始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1658486600000") | ||
| 14 | - @NotNull(message = "查询起始时间不能为空") | ||
| 15 | - private Long startTime; | ||
| 16 | - | ||
| 17 | - @Schema(description = "查询结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "1758486600000") | ||
| 18 | - @NotNull(message = "查询结束时间不能为空") | ||
| 19 | - private Long endTime; | ||
| 20 | - | ||
| 21 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceMessageMapper.java
| @@ -57,20 +57,10 @@ public interface IotDeviceMessageMapper { | @@ -57,20 +57,10 @@ public interface IotDeviceMessageMapper { | ||
| 57 | */ | 57 | */ |
| 58 | Long selectCountByCreateTime(@Param("createTime") Long createTime); | 58 | Long selectCountByCreateTime(@Param("createTime") Long createTime); |
| 59 | 59 | ||
| 60 | - // TODO @super:1)上行、下行,不写在 mapper 里,而是通过参数传递,这样,selectDeviceLogUpCountByHour、selectDeviceLogDownCountByHour 可以合并; | ||
| 61 | - // TODO @super:2)不能只基于 identifier 来计算,而是要 type + identifier 成对 | ||
| 62 | /** | 60 | /** |
| 63 | - * 查询每个小时设备上行消息数量 | 61 | + * 按照时间范围(小时),统计设备的消息数量 |
| 64 | */ | 62 | */ |
| 65 | - List<Map<String, Object>> selectDeviceLogUpCountByHour(@Param("deviceId") Long deviceId, | ||
| 66 | - @Param("startTime") Long startTime, | ||
| 67 | - @Param("endTime") Long endTime); | ||
| 68 | - | ||
| 69 | - /** | ||
| 70 | - * 查询每个小时设备下行消息数量 | ||
| 71 | - */ | ||
| 72 | - List<Map<String, Object>> selectDeviceLogDownCountByHour(@Param("deviceId") Long deviceId, | ||
| 73 | - @Param("startTime") Long startTime, | ||
| 74 | - @Param("endTime") Long endTime); | 63 | + List<Map<String, Object>> selectDeviceMessageCountGroupByDate(@Param("startTime") Long startTime, |
| 64 | + @Param("endTime") Long endTime); | ||
| 75 | 65 | ||
| 76 | } | 66 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceServiceImpl.java
| @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.device; | @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.iot.service.device; | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.util.IdUtil; | 4 | import cn.hutool.core.util.IdUtil; |
| 5 | import cn.hutool.core.util.ObjUtil; | 5 | import cn.hutool.core.util.ObjUtil; |
| 6 | -import cn.hutool.core.util.RandomUtil; | ||
| 7 | import cn.hutool.core.util.StrUtil; | 6 | import cn.hutool.core.util.StrUtil; |
| 8 | import cn.hutool.extra.spring.SpringUtil; | 7 | import cn.hutool.extra.spring.SpringUtil; |
| 9 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 8 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| @@ -15,6 +14,7 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | @@ -15,6 +14,7 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | ||
| 15 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; | 14 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.device.*; |
| 16 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; | 15 | import cn.iocoder.yudao.module.iot.core.biz.dto.IotDeviceAuthReqDTO; |
| 17 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; | 16 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; |
| 17 | +import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; | ||
| 18 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 18 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 19 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; | 19 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceGroupDO; |
| 20 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; | 20 | import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; |
| @@ -22,7 +22,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; | @@ -22,7 +22,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.device.IotDeviceMapper; | ||
| 22 | import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; | 22 | import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; |
| 23 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; | 23 | import cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum; |
| 24 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; | 24 | import cn.iocoder.yudao.module.iot.service.product.IotProductService; |
| 25 | -import cn.iocoder.yudao.module.iot.core.util.IotDeviceAuthUtils; | ||
| 26 | import jakarta.annotation.Resource; | 25 | import jakarta.annotation.Resource; |
| 27 | import jakarta.validation.ConstraintViolationException; | 26 | import jakarta.validation.ConstraintViolationException; |
| 28 | import lombok.extern.slf4j.Slf4j; | 27 | import lombok.extern.slf4j.Slf4j; |
| @@ -322,15 +321,6 @@ public class IotDeviceServiceImpl implements IotDeviceService { | @@ -322,15 +321,6 @@ public class IotDeviceServiceImpl implements IotDeviceService { | ||
| 322 | } | 321 | } |
| 323 | 322 | ||
| 324 | /** | 323 | /** |
| 325 | - * 生成 deviceKey | ||
| 326 | - * | ||
| 327 | - * @return 生成的 deviceKey | ||
| 328 | - */ | ||
| 329 | - private String generateDeviceKey() { | ||
| 330 | - return RandomUtil.randomString(16); | ||
| 331 | - } | ||
| 332 | - | ||
| 333 | - /** | ||
| 334 | * 生成 deviceSecret | 324 | * 生成 deviceSecret |
| 335 | * | 325 | * |
| 336 | * @return 生成的 deviceSecret | 326 | * @return 生成的 deviceSecret |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java
| @@ -2,10 +2,16 @@ package cn.iocoder.yudao.module.iot.service.device.message; | @@ -2,10 +2,16 @@ package cn.iocoder.yudao.module.iot.service.device.message; | ||
| 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.message.IotDeviceMessagePageReqVO; | 4 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; |
| 5 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageReqVO; | ||
| 6 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryByDateRespVO; | ||
| 5 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 7 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| 6 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; | 8 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; |
| 7 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; | 9 | import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; |
| 8 | 10 | ||
| 11 | +import javax.annotation.Nullable; | ||
| 12 | +import java.time.LocalDateTime; | ||
| 13 | +import java.util.List; | ||
| 14 | + | ||
| 9 | /** | 15 | /** |
| 10 | * IoT 设备消息 Service 接口 | 16 | * IoT 设备消息 Service 接口 |
| 11 | * | 17 | * |
| @@ -57,4 +63,21 @@ public interface IotDeviceMessageService { | @@ -57,4 +63,21 @@ public interface IotDeviceMessageService { | ||
| 57 | */ | 63 | */ |
| 58 | PageResult<IotDeviceMessageDO> getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO); | 64 | PageResult<IotDeviceMessageDO> getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO); |
| 59 | 65 | ||
| 66 | + /** | ||
| 67 | + * 获得设备消息数量 | ||
| 68 | + * | ||
| 69 | + * @param createTime 创建时间,如果为空,则统计所有消息数量 | ||
| 70 | + * @return 消息数量 | ||
| 71 | + */ | ||
| 72 | + Long getDeviceMessageCount(@Nullable LocalDateTime createTime); | ||
| 73 | + | ||
| 74 | + /** | ||
| 75 | + * 获取设备消息的数据统计 | ||
| 76 | + * | ||
| 77 | + * @param reqVO 统计请求 | ||
| 78 | + * @return 设备消息的数据统计 | ||
| 79 | + */ | ||
| 80 | + List<IotStatisticsDeviceMessageSummaryByDateRespVO> getDeviceMessageSummaryByDate( | ||
| 81 | + IotStatisticsDeviceMessageReqVO reqVO); | ||
| 82 | + | ||
| 60 | } | 83 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java
| 1 | package cn.iocoder.yudao.module.iot.service.device.message; | 1 | package cn.iocoder.yudao.module.iot.service.device.message; |
| 2 | 2 | ||
| 3 | +import cn.hutool.core.date.LocalDateTimeUtil; | ||
| 4 | +import cn.hutool.core.map.MapUtil; | ||
| 3 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 4 | import cn.hutool.extra.spring.SpringUtil; | 6 | import cn.hutool.extra.spring.SpringUtil; |
| 5 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 7 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; | ||
| 7 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; | 10 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 8 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; | 11 | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| 9 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; | 12 | import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; |
| 13 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageReqVO; | ||
| 14 | +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryByDateRespVO; | ||
| 10 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; | 15 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; |
| 11 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; | 16 | import cn.iocoder.yudao.module.iot.core.enums.IotDeviceStateEnum; |
| 12 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; | 17 | import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; |
| @@ -26,9 +31,13 @@ import org.springframework.scheduling.annotation.Async; | @@ -26,9 +31,13 @@ import org.springframework.scheduling.annotation.Async; | ||
| 26 | import org.springframework.stereotype.Service; | 31 | import org.springframework.stereotype.Service; |
| 27 | import org.springframework.validation.annotation.Validated; | 32 | import org.springframework.validation.annotation.Validated; |
| 28 | 33 | ||
| 34 | +import java.sql.Timestamp; | ||
| 29 | import java.time.LocalDateTime; | 35 | import java.time.LocalDateTime; |
| 36 | +import java.util.List; | ||
| 37 | +import java.util.Map; | ||
| 30 | 38 | ||
| 31 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 39 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 40 | +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; | ||
| 32 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL; | 41 | import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_DOWNSTREAM_FAILED_SERVER_ID_NULL; |
| 33 | 42 | ||
| 34 | /** | 43 | /** |
| @@ -47,19 +56,19 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | @@ -47,19 +56,19 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | ||
| 47 | private IotDevicePropertyService devicePropertyService; | 56 | private IotDevicePropertyService devicePropertyService; |
| 48 | 57 | ||
| 49 | @Resource | 58 | @Resource |
| 50 | - private IotDeviceMessageMapper deviceLogMapper; | 59 | + private IotDeviceMessageMapper deviceMessageMapper; |
| 51 | 60 | ||
| 52 | @Resource | 61 | @Resource |
| 53 | private IotDeviceMessageProducer deviceMessageProducer; | 62 | private IotDeviceMessageProducer deviceMessageProducer; |
| 54 | 63 | ||
| 55 | @Override | 64 | @Override |
| 56 | public void defineDeviceMessageStable() { | 65 | public void defineDeviceMessageStable() { |
| 57 | - if (StrUtil.isNotEmpty(deviceLogMapper.showSTable())) { | 66 | + if (StrUtil.isNotEmpty(deviceMessageMapper.showSTable())) { |
| 58 | log.info("[defineDeviceMessageStable][设备消息超级表已存在,创建跳过]"); | 67 | log.info("[defineDeviceMessageStable][设备消息超级表已存在,创建跳过]"); |
| 59 | return; | 68 | return; |
| 60 | } | 69 | } |
| 61 | log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建开始...]"); | 70 | log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建开始...]"); |
| 62 | - deviceLogMapper.createSTable(); | 71 | + deviceMessageMapper.createSTable(); |
| 63 | log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建成功]"); | 72 | log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建成功]"); |
| 64 | } | 73 | } |
| 65 | 74 | ||
| @@ -74,7 +83,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | @@ -74,7 +83,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | ||
| 74 | if (messageDO.getData() != null) { | 83 | if (messageDO.getData() != null) { |
| 75 | messageDO.setData(JsonUtils.toJsonString(messageDO.getData())); | 84 | messageDO.setData(JsonUtils.toJsonString(messageDO.getData())); |
| 76 | } | 85 | } |
| 77 | - deviceLogMapper.insert(messageDO); | 86 | + deviceMessageMapper.insert(messageDO); |
| 78 | } | 87 | } |
| 79 | 88 | ||
| 80 | @Override | 89 | @Override |
| @@ -192,7 +201,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | @@ -192,7 +201,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | ||
| 192 | @Override | 201 | @Override |
| 193 | public PageResult<IotDeviceMessageDO> getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO) { | 202 | public PageResult<IotDeviceMessageDO> getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO) { |
| 194 | try { | 203 | try { |
| 195 | - IPage<IotDeviceMessageDO> page = deviceLogMapper.selectPage( | 204 | + IPage<IotDeviceMessageDO> page = deviceMessageMapper.selectPage( |
| 196 | new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO); | 205 | new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO); |
| 197 | return new PageResult<>(page.getRecords(), page.getTotal()); | 206 | return new PageResult<>(page.getRecords(), page.getTotal()); |
| 198 | } catch (Exception exception) { | 207 | } catch (Exception exception) { |
| @@ -203,6 +212,33 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | @@ -203,6 +212,33 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { | ||
| 203 | } | 212 | } |
| 204 | } | 213 | } |
| 205 | 214 | ||
| 215 | + @Override | ||
| 216 | + public Long getDeviceMessageCount(LocalDateTime createTime) { | ||
| 217 | + return deviceMessageMapper.selectCountByCreateTime(createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null); | ||
| 218 | + } | ||
| 219 | + | ||
| 220 | + @Override | ||
| 221 | + public List<IotStatisticsDeviceMessageSummaryByDateRespVO> getDeviceMessageSummaryByDate( | ||
| 222 | + IotStatisticsDeviceMessageReqVO reqVO) { | ||
| 223 | + // 1. 按小时统计,获取分项统计数据 | ||
| 224 | + List<Map<String, Object>> countList = deviceMessageMapper.selectDeviceMessageCountGroupByDate( | ||
| 225 | + LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[0]), LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[1])); | ||
| 226 | + | ||
| 227 | + // 2. 按照日期间隔,合并数据 | ||
| 228 | + List<LocalDateTime[]> timeRanges = LocalDateTimeUtils.getDateRangeList(reqVO.getTimes()[0], reqVO.getTimes()[1], reqVO.getInterval()); | ||
| 229 | + return convertList(timeRanges, times -> { | ||
| 230 | + Integer upstreamCount = countList.stream() | ||
| 231 | + .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], (Timestamp) vo.get("time"))) | ||
| 232 | + .mapToInt(value -> MapUtil.getInt(value, "upstream_count")).sum(); | ||
| 233 | + Integer downstreamCount = countList.stream() | ||
| 234 | + .filter(vo -> LocalDateTimeUtils.isBetween(times[0], times[1], (Timestamp) vo.get("time"))) | ||
| 235 | + .mapToInt(value -> MapUtil.getInt(value, "downstream_count")).sum(); | ||
| 236 | + return new IotStatisticsDeviceMessageSummaryByDateRespVO() | ||
| 237 | + .setTime(LocalDateTimeUtils.formatDateRange(times[0], times[1], reqVO.getInterval())) | ||
| 238 | + .setUpstreamCount(upstreamCount).setDownstreamCount(downstreamCount); | ||
| 239 | + }); | ||
| 240 | + } | ||
| 241 | + | ||
| 206 | private IotDeviceMessageServiceImpl getSelf() { | 242 | private IotDeviceMessageServiceImpl getSelf() { |
| 207 | return SpringUtil.getBean(getClass()); | 243 | return SpringUtil.getBean(getClass()); |
| 208 | } | 244 | } |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDeviceLogService.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.service.device.property; | ||
| 2 | - | ||
| 3 | -import javax.annotation.Nullable; | ||
| 4 | -import java.time.LocalDateTime; | ||
| 5 | -import java.util.List; | ||
| 6 | -import java.util.Map; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * IoT 设备消息数据 Service 接口 | ||
| 10 | - * | ||
| 11 | - * @author alwayssuper | ||
| 12 | - */ | ||
| 13 | -public interface IotDeviceLogService { | ||
| 14 | - | ||
| 15 | - /** | ||
| 16 | - * 获得设备消息数量 | ||
| 17 | - * | ||
| 18 | - * @param createTime 创建时间,如果为空,则统计所有消息数量 | ||
| 19 | - * @return 消息数量 | ||
| 20 | - */ | ||
| 21 | - Long getDeviceLogCount(@Nullable LocalDateTime createTime); | ||
| 22 | - | ||
| 23 | - // TODO @super:deviceKey 是不是用不上哈? | ||
| 24 | - /** | ||
| 25 | - * 获得每个小时设备上行消息数量统计 | ||
| 26 | - * | ||
| 27 | - * @param deviceKey 设备标识 | ||
| 28 | - * @param startTime 开始时间 | ||
| 29 | - * @param endTime 结束时间 | ||
| 30 | - * @return key: 时间戳, value: 消息数量 | ||
| 31 | - */ | ||
| 32 | - List<Map<Long, Integer>> getDeviceLogUpCountByHour(@Nullable String deviceKey, | ||
| 33 | - @Nullable Long startTime, | ||
| 34 | - @Nullable Long endTime); | ||
| 35 | - | ||
| 36 | - /** | ||
| 37 | - * 获得每个小时设备下行消息数量统计 | ||
| 38 | - * | ||
| 39 | - * @param deviceKey 设备标识 | ||
| 40 | - * @param startTime 开始时间 | ||
| 41 | - * @param endTime 结束时间 | ||
| 42 | - * @return key: 时间戳, value: 消息数量 | ||
| 43 | - */ | ||
| 44 | - List<Map<Long, Integer>> getDeviceLogDownCountByHour(@Nullable String deviceKey, | ||
| 45 | - @Nullable Long startTime, | ||
| 46 | - @Nullable Long endTime); | ||
| 47 | - | ||
| 48 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDeviceLogServiceImpl.java deleted
| 1 | -package cn.iocoder.yudao.module.iot.service.device.property; | ||
| 2 | - | ||
| 3 | -import cn.hutool.core.date.LocalDateTimeUtil; | ||
| 4 | -import cn.hutool.core.map.MapUtil; | ||
| 5 | -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper; | ||
| 6 | -import jakarta.annotation.Resource; | ||
| 7 | -import lombok.extern.slf4j.Slf4j; | ||
| 8 | -import org.springframework.stereotype.Service; | ||
| 9 | -import org.springframework.validation.annotation.Validated; | ||
| 10 | - | ||
| 11 | -import java.sql.Timestamp; | ||
| 12 | -import java.time.LocalDateTime; | ||
| 13 | -import java.util.List; | ||
| 14 | -import java.util.Map; | ||
| 15 | -import java.util.stream.Collectors; | ||
| 16 | - | ||
| 17 | -/** | ||
| 18 | - * IoT 设备日志数据 Service 实现类 | ||
| 19 | - * | ||
| 20 | - * @author alwayssuper | ||
| 21 | - */ | ||
| 22 | -@Service | ||
| 23 | -@Slf4j | ||
| 24 | -@Validated | ||
| 25 | -public class IotDeviceLogServiceImpl implements IotDeviceLogService { | ||
| 26 | - | ||
| 27 | - @Resource | ||
| 28 | - private IotDeviceMessageMapper deviceLogMapper; | ||
| 29 | - | ||
| 30 | - @Override | ||
| 31 | - public Long getDeviceLogCount(LocalDateTime createTime) { | ||
| 32 | - return deviceLogMapper.selectCountByCreateTime(createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - // TODO @super:加一个参数,Boolean upstream:true 上行,false 下行,null 不过滤 | ||
| 36 | - @Override | ||
| 37 | - public List<Map<Long, Integer>> getDeviceLogUpCountByHour(String deviceKey, Long startTime, Long endTime) { | ||
| 38 | - // TODO @super:不能只基于数据库统计。因为有一些小时,可能出现没数据的情况,导致前端展示的图是不全的。可以参考 CrmStatisticsCustomerService 来实现 | ||
| 39 | - // TODO @芋艿:这里实现,需要调整 | ||
| 40 | - List<Map<String, Object>> list = deviceLogMapper.selectDeviceLogUpCountByHour(0L, startTime, endTime); | ||
| 41 | - return list.stream() | ||
| 42 | - .map(map -> { | ||
| 43 | - // 从Timestamp获取时间戳 | ||
| 44 | - Timestamp timestamp = (Timestamp) map.get("time"); | ||
| 45 | - Long timeMillis = timestamp.getTime(); | ||
| 46 | - // 消息数量转换 | ||
| 47 | - Integer count = ((Number) map.get("data")).intValue(); | ||
| 48 | - return MapUtil.of(timeMillis, count); | ||
| 49 | - }) | ||
| 50 | - .collect(Collectors.toList()); | ||
| 51 | - } | ||
| 52 | - | ||
| 53 | - // TODO @super:getDeviceLogDownCountByHour 融合到 getDeviceLogUpCountByHour | ||
| 54 | - @Override | ||
| 55 | - public List<Map<Long, Integer>> getDeviceLogDownCountByHour(String deviceKey, Long startTime, Long endTime) { | ||
| 56 | - // TODO @芋艿:这里实现,需要调整 | ||
| 57 | - List<Map<String, Object>> list = deviceLogMapper.selectDeviceLogDownCountByHour(0L, startTime, endTime); | ||
| 58 | - return list.stream() | ||
| 59 | - .map(map -> { | ||
| 60 | - Timestamp timestamp = (Timestamp) map.get("time"); | ||
| 61 | - Long timeMillis = timestamp.getTime(); | ||
| 62 | - Integer count = ((Number) map.get("data")).intValue(); | ||
| 63 | - return MapUtil.of(timeMillis, count); | ||
| 64 | - }) | ||
| 65 | - .collect(Collectors.toList()); | ||
| 66 | - } | ||
| 67 | - | ||
| 68 | -} |
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceMessageMapper.xml
| @@ -69,45 +69,12 @@ | @@ -69,45 +69,12 @@ | ||
| 69 | </where> | 69 | </where> |
| 70 | </select> | 70 | </select> |
| 71 | 71 | ||
| 72 | - <select id="selectDeviceLogUpCountByHour" resultType="java.util.Map"> | 72 | + <select id="selectDeviceMessageCountGroupByDate" resultType="java.util.Map"> |
| 73 | SELECT | 73 | SELECT |
| 74 | - TIMETRUNCATE(ts, 1h) as time, | ||
| 75 | - COUNT(*) as data | ||
| 76 | - FROM | ||
| 77 | - <choose> | ||
| 78 | - <when test="deviceId != null"> | ||
| 79 | - device_message_${deviceId} | ||
| 80 | - </when> | ||
| 81 | - <otherwise> | ||
| 82 | - device_message | ||
| 83 | - </otherwise> | ||
| 84 | - </choose> | ||
| 85 | - <where> | ||
| 86 | - <if test="startTime != null"> | ||
| 87 | - AND ts >= #{startTime} | ||
| 88 | - </if> | ||
| 89 | - <if test="endTime != null"> | ||
| 90 | - AND ts <= #{endTime} | ||
| 91 | - </if> | ||
| 92 | - AND upstream = true | ||
| 93 | - </where> | ||
| 94 | - GROUP BY TIMETRUNCATE(ts, 1h) | ||
| 95 | - ORDER BY time ASC | ||
| 96 | - </select> | ||
| 97 | - | ||
| 98 | - <select id="selectDeviceLogDownCountByHour" resultType="java.util.Map"> | ||
| 99 | - SELECT | ||
| 100 | - TIMETRUNCATE(ts, 1h) as time, | ||
| 101 | - COUNT(*) as data | ||
| 102 | - FROM | ||
| 103 | - <choose> | ||
| 104 | - <when test="deviceId != null"> | ||
| 105 | - device_message_${deviceId} | ||
| 106 | - </when> | ||
| 107 | - <otherwise> | ||
| 108 | - device_message | ||
| 109 | - </otherwise> | ||
| 110 | - </choose> | 74 | + TIMETRUNCATE(ts, 1h) AS time, |
| 75 | + SUM(CASE WHEN upstream = true THEN 1 ELSE 0 END) AS upstream_count, | ||
| 76 | + SUM(CASE WHEN upstream = false THEN 1 ELSE 0 END) AS downstream_count | ||
| 77 | + FROM device_message | ||
| 111 | <where> | 78 | <where> |
| 112 | <if test="startTime != null"> | 79 | <if test="startTime != null"> |
| 113 | AND ts >= #{startTime} | 80 | AND ts >= #{startTime} |
| @@ -115,10 +82,8 @@ | @@ -115,10 +82,8 @@ | ||
| 115 | <if test="endTime != null"> | 82 | <if test="endTime != null"> |
| 116 | AND ts <= #{endTime} | 83 | AND ts <= #{endTime} |
| 117 | </if> | 84 | </if> |
| 118 | - AND upstream = false | ||
| 119 | </where> | 85 | </where> |
| 120 | - GROUP BY TIMETRUNCATE(ts, 1h) | ||
| 121 | - ORDER BY time ASC | 86 | + GROUP BY time |
| 122 | </select> | 87 | </select> |
| 123 | 88 | ||
| 124 | </mapper> | 89 | </mapper> |
| 125 | \ No newline at end of file | 90 | \ No newline at end of file |