ソースを参照

[fix]:iot home count

alwayssuper 5 ヶ月 前
コミット
8daa2131ba

+ 23 - 5
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/statistics/IotStatisticsController.java

@@ -1,12 +1,12 @@
 package cn.iocoder.yudao.module.iot.controller.admin.statistics;
 
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.product.IotProductRespVO;
 import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
+import cn.iocoder.yudao.module.iot.enums.device.IotDeviceStateEnum;
 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
+import cn.iocoder.yudao.module.iot.service.device.data.IotDeviceLogService;
 import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService;
 import cn.iocoder.yudao.module.iot.service.product.IotProductService;
-import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.annotation.Resource;
@@ -16,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.time.LocalDateTime;
-import java.util.List;
 
 
 @Tag(name = "管理后台 - IoT 数据统计")
@@ -34,21 +33,40 @@ public class IotStatisticsController {
     @Resource
     private IotProductService iotProductService;
 
+    @Resource
+    private IotDeviceLogService iotDeviceLogService;
+
 
     @GetMapping("/count")
-    @Operation(summary = "获取IOT首页的数据统计", description = "主要用于IOT首页的数据统计")
-    public CommonResult<IotStatisticsRespVO> getSimpleProductList(){
+    @Operation(summary = "获取IOT首页的数据统计", description = "用于IOT首页的数据统计")
+    public CommonResult<IotStatisticsRespVO> getIotCount(){
         IotStatisticsRespVO iotStatisticsRespVO = new IotStatisticsRespVO();
         // 获取总数
         iotStatisticsRespVO.setCategoryTotal(iotProductCategoryService.getProductCategoryCount(null));
         iotStatisticsRespVO.setProductTotal(iotProductService.getProductCount(null));
         iotStatisticsRespVO.setDeviceTotal(iotDeviceService.getDeviceCount(null));
+        iotStatisticsRespVO.setReportTotal(iotDeviceLogService.getDeviceLogCount(null));
 
         // 获取今日新增数量
         LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
         iotStatisticsRespVO.setCategoryTodayTotal(iotProductCategoryService.getProductCategoryCount(todayStart));
         iotStatisticsRespVO.setProductTodayTotal(iotProductService.getProductCount(todayStart));
         iotStatisticsRespVO.setDeviceTodayTotal(iotDeviceService.getDeviceCount(todayStart));
+        iotStatisticsRespVO.setReportTodayTotal(iotDeviceLogService.getDeviceLogCount(todayStart));
+
+        // 获取各个品类下设备数量统计
+        iotStatisticsRespVO.setDeviceStatsOfCategory(
+            iotProductCategoryService.getDeviceCountsOfProductCategory()
+        );
+
+        // 获取设备状态数量统计
+        iotStatisticsRespVO.setOnlineTotal(iotDeviceService.getDeviceCountByState(IotDeviceStateEnum.ONLINE.getState()));
+        iotStatisticsRespVO.setOfflineTotal(iotDeviceService.getDeviceCountByState(IotDeviceStateEnum.OFFLINE.getState()));
+        iotStatisticsRespVO.setNeverOnlineTotal(iotDeviceService.getDeviceCountByState(IotDeviceStateEnum.INACTIVE.getState()));
+
+        // 获取设备上下行消息数量统计
+        iotStatisticsRespVO.setDeviceUpMessageStats(iotDeviceLogService.getDeviceLogUpCountByHour(null,null,null));
+        iotStatisticsRespVO.setDeviceDownMessageStats(iotDeviceLogService.getDeviceLogDownCountByHour(null,null,null));
 
         return CommonResult.success(iotStatisticsRespVO);
     }

+ 36 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceLogMapper.java

@@ -1,6 +1,7 @@
 package cn.iocoder.yudao.module.iot.dal.tdengine;
 
 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
 import cn.iocoder.yudao.module.iot.framework.tdengine.core.annotation.TDengineDS;
 import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
@@ -8,6 +9,9 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
+import java.time.LocalDateTime;
+import java.util.List;
+
 /**
  * 设备日志 {@link IotDeviceLogDO} Mapper 接口
  */
@@ -46,4 +50,36 @@ public interface IotDeviceLogMapper {
     IPage<IotDeviceLogDO> selectPage(IPage<IotDeviceLogDO> page,
                                      @Param("reqVO") IotDeviceLogPageReqVO reqVO);
 
+    /**
+     * 统计设备日志数量
+     *
+     * @param createTime 创建时间,如果为空,则统计所有日志数量
+     * @return 日志数量
+     */
+    Long selectCountByCreateTime(@Param("createTime") Long createTime);
+
+    /**
+     * 获得每个小时设备上行消息数量统计
+     *
+     * @param deviceKey 设备标识
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 每小时消息数量统计
+     */
+    List<IotStatisticsRespVO.TimeData> selectDeviceLogUpCountByHour(@Param("deviceKey") String deviceKey,
+                                                                    @Param("startTime") Long startTime,
+                                                                    @Param("endTime") Long endTime);
+
+    /**
+     * 获得每个小时设备下行消息数量统计
+     *
+     * @param deviceKey 设备标识
+     * @param startTime 开始时间
+     * @param endTime 结束时间
+     * @return 每小时消息数量统计
+     */
+    List<IotStatisticsRespVO.TimeData> selectDeviceLogDownCountByHour(@Param("deviceKey") String deviceKey,
+                                                                      @Param("startTime") Long startTime,
+                                                                      @Param("endTime") Long endTime);
+
 }

+ 16 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/IotDeviceService.java

@@ -134,6 +134,22 @@ public interface IotDeviceService {
      */
     List<IotDeviceDO> getDeviceListByState(Integer state);
 
+    /**
+     * 根据产品ID获取设备列表
+     *
+     * @param productId 产品ID,用于查询特定产品的设备列表
+     * @return 返回与指定产品ID关联的设备列表,列表中的每个元素为IotDeviceDO对象
+     */
+    List<IotDeviceDO> getDeviceListByProductId(Long productId);
+
+    /**
+     * 根据设备ID列表获取设备信息列表
+     *
+     * @param deviceIdList 设备ID列表,包含需要查询的设备ID
+     * @return 返回与设备ID列表对应的设备信息列表,列表中的每个元素为IotDeviceDO对象
+     */
+    List<IotDeviceDO> getDeviceListByIdList(List<Long> deviceIdList);
+
     /**
      * 基于产品编号,获得设备数量
      *

+ 33 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDeviceLogService.java

@@ -2,8 +2,13 @@ package cn.iocoder.yudao.module.iot.service.device.data;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * IoT 设备日志数据 Service 接口
@@ -34,4 +39,32 @@ public interface IotDeviceLogService {
      */
     PageResult<IotDeviceLogDO> getDeviceLogPage(IotDeviceLogPageReqVO pageReqVO);
 
+    /**
+     * 获得设备日志数量
+     *
+     * @param createTime 创建时间,如果为空,则统计所有日志数量
+     * @return 日志数量
+     */
+    Long getDeviceLogCount(LocalDateTime createTime);
+
+    /**
+     * 获得每个小时设备上行消息数量统计
+     *
+     * @param deviceKey 设备标识,如果为空,则统计所有设备
+     * @param startTime 开始时间,如果为空,则不限制开始时间
+     * @param endTime 结束时间,如果为空,则不限制结束时间
+     * @return 每小时消息数量统计列表
+     */
+    List<IotStatisticsRespVO.TimeData> getDeviceLogUpCountByHour(String deviceKey, Long startTime, Long endTime);
+
+    /**
+     * 获得每个小时设备下行消息数量统计
+     *
+     * @param deviceKey 设备标识,如果为空,则统计所有设备
+     * @param startTime 开始时间,如果为空,则不限制开始时间
+     * @param endTime 结束时间,如果为空,则不限制结束时间
+     * @return 每小时消息数量统计列表
+     */
+    List<IotStatisticsRespVO.TimeData> getDeviceLogDownCountByHour( String deviceKey, Long startTime, Long endTime);
+
 }

+ 39 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/data/IotDeviceLogServiceImpl.java

@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.iot.controller.admin.device.vo.data.IotDeviceLogPageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceLogDO;
 import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceLogMapper;
 import cn.iocoder.yudao.module.iot.mq.message.IotDeviceMessage;
@@ -16,6 +17,11 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * IoT 设备日志数据 Service 实现类
  *
@@ -63,4 +69,37 @@ public class IotDeviceLogServiceImpl implements IotDeviceLogService {
         }
     }
 
+    @Override
+    public Long getDeviceLogCount(LocalDateTime createTime) {
+        Long time = null;
+        if (createTime != null) {
+            time = createTime.toInstant(ZoneOffset.UTC).toEpochMilli();
+        }
+        return deviceLogMapper.selectCountByCreateTime(time);
+    }
+
+    @Override
+    public List<IotStatisticsRespVO.TimeData> getDeviceLogUpCountByHour(String deviceKey, Long startTime, Long endTime) {
+        try {
+            return deviceLogMapper.selectDeviceLogUpCountByHour(deviceKey, startTime, endTime);
+        } catch (Exception exception) {
+            if (exception.getMessage().contains("Table does not exist")) {
+                return new ArrayList<>();
+            }
+            throw exception;
+        }
+    }
+
+    @Override
+    public List<IotStatisticsRespVO.TimeData> getDeviceLogDownCountByHour(String deviceKey, Long startTime, Long endTime) {
+        try {
+            return deviceLogMapper.selectDeviceLogDownCountByHour(deviceKey, startTime, endTime);
+        } catch (Exception exception) {
+            if (exception.getMessage().contains("Table does not exist")) {
+                return new ArrayList<>();
+            }
+            throw exception;
+        }
+    }
+
 }

+ 4 - 4
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryService.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.iot.service.product;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO;
 import jakarta.validation.Valid;
 
@@ -92,12 +93,11 @@ public interface IotProductCategoryService {
      */
     Long getProductCategoryCount(LocalDateTime createTime);
 
-
     /**
-     * 获得各产品分类下属的设备总数
+     * 获得各个品类下设备数量统计
      *
-     * @return 产品分类名称和各产品分类下属的设备总数
+     * @return 品类设备统计列表
      */
-    Map<String,Integer> getDeviceCountsOfProductCategoryMap();
+    List<IotStatisticsRespVO.DataItem> getDeviceCountsOfProductCategory();
 
 }

+ 14 - 3
yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductCategoryServiceImpl.java

@@ -5,11 +5,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategoryPageReqVO;
 import cn.iocoder.yudao.module.iot.controller.admin.product.vo.category.IotProductCategorySaveReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductCategoryDO;
 import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
 import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductCategoryMapper;
 import cn.iocoder.yudao.module.iot.service.device.IotDeviceService;
+import cn.iocoder.yudao.module.iot.service.product.IotProductCategoryService;
 import jakarta.annotation.Resource;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -19,6 +21,7 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_CATEGORY_NOT_EXISTS;
@@ -101,7 +104,7 @@ public class IotProductCategoryServiceImpl implements IotProductCategoryService
     }
 
     @Override
-    public Map<String, Integer> getDeviceCountsOfProductCategoryMap() {
+    public List<IotStatisticsRespVO.DataItem> getDeviceCountsOfProductCategory() {
         // 1. 获取所有数据
         List<IotProductCategoryDO> categoryList = productCategoryMapper.selectList();
         List<IotProductDO> productList = productService.getProductList();
@@ -137,8 +140,16 @@ public class IotProductCategoryServiceImpl implements IotProductCategoryService
                 categoryDeviceCountMap.merge(categoryName, 1, Integer::sum);
             }
         }
-        
-        return categoryDeviceCountMap;
+
+        // 3. 转换为 DataItem 列表
+        return categoryDeviceCountMap.entrySet().stream()
+                .map(entry -> {
+                    IotStatisticsRespVO.DataItem dataItem = new IotStatisticsRespVO.DataItem();
+                    dataItem.setName(entry.getKey());
+                    dataItem.setValue(entry.getValue());
+                    return dataItem;
+                })
+                .collect(Collectors.toList());
     }
 
 }

+ 64 - 0
yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDeviceLogMapper.xml

@@ -55,4 +55,68 @@
         ORDER BY ts DESC
     </select>
 
+    <select id="selectCountByCreateTime" resultType="Long">
+        SELECT COUNT(*)
+        FROM device_log
+        <where>
+            <if test="createTime != null">
+                AND ts >= #{createTime}
+            </if>
+        </where>
+    </select>
+
+    <select id="selectDeviceLogUpCountByHour" resultType="cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO$TimeData">
+        SELECT 
+            TIMETRUNCATE(ts, 1h) as time,
+            COUNT(*) as data 
+        FROM 
+        <choose>
+            <when test="deviceKey != null and deviceKey != ''">
+                device_log_${deviceKey}
+            </when>
+            <otherwise>
+                device_log
+            </otherwise>
+        </choose>
+        <where>
+            <if test="startTime != null">
+                AND ts >= #{startTime}
+            </if>
+            <if test="endTime != null">
+                AND ts &lt;= #{endTime}
+            </if>
+            AND (
+                 identifier IN ('online', 'offline', 'pull', 'progress', 'report', 'register', 'register_sub')
+            )
+        </where>
+        GROUP BY TIMETRUNCATE(ts, 1h)
+        ORDER BY time ASC
+    </select>
+
+    <select id="selectDeviceLogDownCountByHour" resultType="cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsRespVO$TimeData">
+        SELECT 
+            TIMETRUNCATE(ts, 1h) as time,
+            COUNT(*) as data 
+        FROM 
+        <choose>
+            <when test="deviceKey != null and deviceKey != ''">
+                device_log_${deviceKey}
+            </when>
+            <otherwise>
+                device_log
+            </otherwise>
+        </choose>
+        <where>
+            <if test="startTime != null">
+                AND ts >= #{startTime}
+            </if>
+            <if test="endTime != null">
+                AND ts &lt;= #{endTime}
+            </if>
+            AND identifier IN ('set', 'get', 'upgrade', 'unregister_sub', 'topology_add')
+        </where>
+        GROUP BY TIMETRUNCATE(ts, 1h)
+        ORDER BY time ASC
+    </select>
+
 </mapper>