Ver Fonte

feat(manhole): 添加井盖数据管理功能

- 新增井盖数据实体类 ManholeData,包含设备监测相关字段
- 创建井盖数据控制器 ManholeDataController,提供 REST API 接口
- 实现井盖数据服务层 ManholeDataService 和具体业务逻辑
- 配置 MyBatis 数据访问层和 XML 映射文件
- 添加分页查询、设备统计、报警趋势分析等功能
- 实现温度趋势统计、报警数据查询等可视化接口
- 提供设备最新数据获取和整体统计功能
林仔 há 1 mês atrás
pai
commit
4f6137eb6d

+ 168 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/base/manhole/ManholeDataController.java

@@ -0,0 +1,168 @@
+package com.zksy.web.controller.base.manhole;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zksy.base.manhole.domain.ManholeData;
+import com.zksy.base.manhole.service.ManholeDataService;
+import com.zksy.common.annotation.Anonymous;
+import com.zksy.common.core.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 井盖数据统计分析接口
+ */
+@RestController
+@RequestMapping("/api/manhole/data")
+@Api(tags = "井盖数据接口")
+@Anonymous
+public class ManholeDataController {
+
+    @Autowired
+    private ManholeDataService manholeDataService;
+
+    /**
+     * 分页查询井盖数据
+     */
+    @GetMapping("/page")
+    @ApiOperation("分页查询井盖数据")
+    public AjaxResult queryPage(
+            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam(value = "每页大小", defaultValue = "10") @RequestParam(defaultValue = "10") Integer pageSize,
+            @ApiParam(value = "IMEI卡号") @RequestParam(required = false) String imeiCardNumber,
+            @ApiParam(value = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        try {
+            Page<ManholeData> page = new Page<>(pageNum, pageSize);
+            IPage<ManholeData> resultPage = manholeDataService.queryPage(page, imeiCardNumber, startTime, endTime);
+            return AjaxResult.success("查询成功", resultPage);
+        } catch (Exception e) {
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 按设备统计井盖数据
+     */
+    @GetMapping("/visualization/stat/device")
+    @ApiOperation("按设备统计井盖数据")
+    public AjaxResult statManholeByDevice(
+            @ApiParam(value = "开始时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        try {
+            List<Map<String, Object>> data = manholeDataService.statManholeByDevice(startTime, endTime);
+            return AjaxResult.success("统计成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 按小时统计报警趋势
+     */
+    @GetMapping("/visualization/stat/alarmTrend")
+    @ApiOperation("按小时统计报警趋势")
+    public AjaxResult statAlarmTrendByHour(
+            @ApiParam(value = "IMEI卡号", required = true) @RequestParam String imeiCardNumber,
+            @ApiParam(value = "开始时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        try {
+            List<Map<String, Object>> data = manholeDataService.statAlarmTrendByHour(imeiCardNumber, startTime, endTime);
+            return AjaxResult.success("统计成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 按小时统计温度趋势
+     */
+    @GetMapping("/visualization/stat/temperatureTrend")
+    @ApiOperation("按小时统计温度趋势")
+    public AjaxResult statTemperatureTrendByHour(
+            @ApiParam(value = "IMEI卡号", required = true) @RequestParam String imeiCardNumber,
+            @ApiParam(value = "开始时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        try {
+            List<Map<String, Object>> data = manholeDataService.statTemperatureTrendByHour(imeiCardNumber, startTime, endTime);
+            return AjaxResult.success("统计成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询报警数据(各种报警状态的数据)
+     */
+    @GetMapping("/visualization/alarm")
+    @ApiOperation("查询报警数据")
+    public AjaxResult queryAlarmData(
+            @ApiParam(value = "IMEI卡号") @RequestParam(required = false) String imeiCardNumber,
+            @ApiParam(value = "开始时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间") @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime,
+            @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam(value = "每页大小", defaultValue = "10") @RequestParam(defaultValue = "10") Integer pageSize) {
+        try {
+            Page<ManholeData> page = new Page<>(pageNum, pageSize);
+            IPage<ManholeData> resultPage = manholeDataService.queryAlarmData(page, imeiCardNumber, startTime, endTime);
+            return AjaxResult.success("查询成功", resultPage);
+        } catch (Exception e) {
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取设备最新监测数据
+     */
+    @GetMapping("/latest")
+    @ApiOperation("获取设备最新监测数据")
+    public AjaxResult getLatestDataByImei(@ApiParam(value = "IMEI卡号", required = true) @RequestParam String imeiCardNumber) {
+        try {
+            Map<String, Object> data = manholeDataService.getLatestDataByImei(imeiCardNumber);
+            if (data == null || data.isEmpty()) {
+                return AjaxResult.warn("未查询到该设备的最新数据", null);
+            }
+            return AjaxResult.success("查询成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取所有井盖设备IMEI卡号
+     */
+    @GetMapping("/devices")
+    @ApiOperation("获取所有井盖设备IMEI卡号")
+    public AjaxResult getAllImeiCardNumbers() {
+        try {
+            List<String> data = manholeDataService.getAllImeiCardNumbers();
+            return AjaxResult.success("查询成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("查询失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 获取整体统计数据
+     */
+    @GetMapping("/visualization/stat/overall")
+    @ApiOperation("获取整体统计数据")
+    public AjaxResult getOverallStatistics(
+            @ApiParam(value = "开始时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime startTime,
+            @ApiParam(value = "结束时间", required = true) @RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime endTime) {
+        try {
+            Map<String, Object> data = manholeDataService.getOverallStatistics(startTime, endTime);
+            return AjaxResult.success("统计成功", data);
+        } catch (Exception e) {
+            return AjaxResult.error("统计失败:" + e.getMessage());
+        }
+    }
+}

+ 69 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/manhole/domain/ManholeData.java

@@ -0,0 +1,69 @@
+package com.zksy.base.manhole.domain;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+@Data
+@TableName("jg_device_data")
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value = "读取井盖数据")
+public class ManholeData {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    @ApiModelProperty(value = "版本号")
+    private String versionNumber;
+
+    @ApiModelProperty(value = "电池电量")
+    private String batteryLevel;
+
+    @ApiModelProperty(value = "上传时间")
+    private String uploadTime;
+
+    @ApiModelProperty(value = "温度值")
+    private String temperatureValue;
+
+    @ApiModelProperty(value = "信号量")
+    private String signalStrength;
+
+    @ApiModelProperty(value = "报警状态(0正常,1报警)")
+    private String alarmStatus;
+
+    @ApiModelProperty(value = "角度报警阈值")
+    private String angleAlarmThreshold;
+
+    @ApiModelProperty(value = "倾斜角度")
+    private String tiltAngle;
+
+    @ApiModelProperty(value = "激活状态")
+    private String activationStatus;
+
+    @ApiModelProperty(value = "水浸报警状态(0正常,1报警)")
+    private String waterInfiltrationAlarmStatus;
+
+    @ApiModelProperty(value = "水位报警状态(0正常,1报警)")
+    private String waterLevelAlarmStatus;
+
+    @ApiModelProperty(value = "SIM 卡号")
+    private String simCardNumber;
+
+    @ApiModelProperty(value = "IMEI 卡号")
+    private String imeiCardNumber;
+
+    @ApiModelProperty(value = "原始数据")
+    private String originalData;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+}

+ 32 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/manhole/mapper/ManholeDataMapper.java

@@ -0,0 +1,32 @@
+package com.zksy.base.manhole.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.base.manhole.domain.ManholeData;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+@Mapper
+public interface ManholeDataMapper extends BaseMapper<ManholeData> {
+    
+    List<Map<String, Object>> statManholeByDevice(@Param("startTime") LocalDateTime startTime, 
+                                                    @Param("endTime") LocalDateTime endTime);
+    
+    List<Map<String, Object>> statAlarmTrendByHour(@Param("imeiCardNumber") String imeiCardNumber,
+                                                      @Param("startTime") LocalDateTime startTime, 
+                                                      @Param("endTime") LocalDateTime endTime);
+    
+    List<Map<String, Object>> statTemperatureTrendByHour(@Param("imeiCardNumber") String imeiCardNumber,
+                                                           @Param("startTime") LocalDateTime startTime, 
+                                                           @Param("endTime") LocalDateTime endTime);
+    
+    List<String> getAllImeiCardNumbers();
+    
+    Map<String, Object> getLatestDataByImei(@Param("imeiCardNumber") String imeiCardNumber);
+    
+    Map<String, Object> getOverallStatistics(@Param("startTime") LocalDateTime startTime, 
+                                                @Param("endTime") LocalDateTime endTime);
+}

+ 29 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/manhole/service/ManholeDataService.java

@@ -0,0 +1,29 @@
+package com.zksy.base.manhole.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.base.manhole.domain.ManholeData;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+public interface ManholeDataService extends IService<ManholeData> {
+    
+    IPage<ManholeData> queryPage(Page<ManholeData> page, String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime);
+    
+    List<Map<String, Object>> statManholeByDevice(LocalDateTime startTime, LocalDateTime endTime);
+    
+    List<Map<String, Object>> statAlarmTrendByHour(String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime);
+    
+    List<Map<String, Object>> statTemperatureTrendByHour(String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime);
+    
+    List<String> getAllImeiCardNumbers();
+    
+    Map<String, Object> getLatestDataByImei(String imeiCardNumber);
+    
+    Map<String, Object> getOverallStatistics(LocalDateTime startTime, LocalDateTime endTime);
+    
+    IPage<ManholeData> queryAlarmData(Page<ManholeData> page, String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime);
+}

+ 93 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/manhole/service/impl/ManholeDataServiceImpl.java

@@ -0,0 +1,93 @@
+package com.zksy.base.manhole.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.base.manhole.domain.ManholeData;
+import com.zksy.base.manhole.mapper.ManholeDataMapper;
+import com.zksy.base.manhole.service.ManholeDataService;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @version 1.0
+ * @project dh-server-micro
+ * @description
+ * @date 2025/2/20 10:55:03
+ */
+@Service
+public class ManholeDataServiceImpl extends ServiceImpl<ManholeDataMapper, ManholeData> implements ManholeDataService {
+
+    @Override
+    public IPage<ManholeData> queryPage(Page<ManholeData> page, String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime) {
+        LambdaQueryWrapper<ManholeData> wrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.hasText(imeiCardNumber)) {
+            wrapper.eq(ManholeData::getImeiCardNumber, imeiCardNumber);
+        }
+        if (startTime != null) {
+            wrapper.ge(ManholeData::getCreateTime, startTime);
+        }
+        if (endTime != null) {
+            wrapper.le(ManholeData::getCreateTime, endTime);
+        }
+        wrapper.orderByDesc(ManholeData::getCreateTime);
+        return this.page(page, wrapper);
+    }
+
+    @Override
+    public List<Map<String, Object>> statManholeByDevice(LocalDateTime startTime, LocalDateTime endTime) {
+        return baseMapper.statManholeByDevice(startTime, endTime);
+    }
+
+    @Override
+    public List<Map<String, Object>> statAlarmTrendByHour(String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime) {
+        return baseMapper.statAlarmTrendByHour(imeiCardNumber, startTime, endTime);
+    }
+
+    @Override
+    public List<Map<String, Object>> statTemperatureTrendByHour(String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime) {
+        return baseMapper.statTemperatureTrendByHour(imeiCardNumber, startTime, endTime);
+    }
+
+    @Override
+    public List<String> getAllImeiCardNumbers() {
+        return baseMapper.getAllImeiCardNumbers();
+    }
+
+    @Override
+    public Map<String, Object> getLatestDataByImei(String imeiCardNumber) {
+        return baseMapper.getLatestDataByImei(imeiCardNumber);
+    }
+
+    @Override
+    public Map<String, Object> getOverallStatistics(LocalDateTime startTime, LocalDateTime endTime) {
+        return baseMapper.getOverallStatistics(startTime, endTime);
+    }
+
+    @Override
+    public IPage<ManholeData> queryAlarmData(Page<ManholeData> page, String imeiCardNumber, LocalDateTime startTime, LocalDateTime endTime) {
+        LambdaQueryWrapper<ManholeData> wrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.hasText(imeiCardNumber)) {
+            wrapper.eq(ManholeData::getImeiCardNumber, imeiCardNumber);
+        }
+        if (startTime != null) {
+            wrapper.ge(ManholeData::getCreateTime, startTime);
+        }
+        if (endTime != null) {
+            wrapper.le(ManholeData::getCreateTime, endTime);
+        }
+        wrapper.and(w -> w.eq(ManholeData::getAlarmStatus, "1")
+                .or()
+                .eq(ManholeData::getWaterInfiltrationAlarmStatus, "1")
+                .or()
+                .eq(ManholeData::getWaterLevelAlarmStatus, "1"));
+        wrapper.orderByDesc(ManholeData::getCreateTime);
+        return this.page(page, wrapper);
+    }
+}

+ 120 - 0
pipe-network-service/zksy-system/src/main/resources/mapper/base/manhole/ManholeDataMapper.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.zksy.base.manhole.mapper.ManholeDataMapper">
+
+    <resultMap id="BaseResultMap" type="com.zksy.base.manhole.domain.ManholeData">
+        <id property="id" column="id" jdbcType="VARCHAR"/>
+        <result property="versionNumber" column="version_number" jdbcType="VARCHAR"/>
+        <result property="batteryLevel" column="battery_level" jdbcType="VARCHAR"/>
+        <result property="uploadTime" column="upload_time" jdbcType="VARCHAR"/>
+        <result property="temperatureValue" column="temperature_value" jdbcType="VARCHAR"/>
+        <result property="signalStrength" column="signal_strength" jdbcType="VARCHAR"/>
+        <result property="alarmStatus" column="alarm_status" jdbcType="VARCHAR"/>
+        <result property="angleAlarmThreshold" column="angle_alarm_threshold" jdbcType="VARCHAR"/>
+        <result property="tiltAngle" column="tilt_angle" jdbcType="VARCHAR"/>
+        <result property="activationStatus" column="activation_status" jdbcType="VARCHAR"/>
+        <result property="waterInfiltrationAlarmStatus" column="water_infiltration_alarm_status" jdbcType="VARCHAR"/>
+        <result property="waterLevelAlarmStatus" column="water_level_alarm_status" jdbcType="VARCHAR"/>
+        <result property="simCardNumber" column="sim_card_number" jdbcType="VARCHAR"/>
+        <result property="imeiCardNumber" column="imei_card_number" jdbcType="VARCHAR"/>
+        <result property="originalData" column="original_data" jdbcType="VARCHAR"/>
+        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id, version_number, battery_level, upload_time, temperature_value, 
+        signal_strength, alarm_status, angle_alarm_threshold, tilt_angle, 
+        activation_status, water_infiltration_alarm_status, water_level_alarm_status, 
+        sim_card_number, imei_card_number, original_data, create_time
+    </sql>
+
+    <select id="statManholeByDevice" resultType="java.util.Map">
+        SELECT 
+            imei_card_number as imeiCardNumber,
+            COUNT(*) as dataCount,
+            SUM(CASE WHEN alarm_status = '1' THEN 1 ELSE 0 END) as alarmCount,
+            SUM(CASE WHEN water_infiltration_alarm_status = '1' THEN 1 ELSE 0 END) as waterInfiltrationCount,
+            SUM(CASE WHEN water_level_alarm_status = '1' THEN 1 ELSE 0 END) as waterLevelCount,
+            AVG(CAST(temperature_value AS DECIMAL(10,2))) as avgTemperature,
+            AVG(CAST(tilt_angle AS DECIMAL(10,2))) as avgTiltAngle
+        FROM jg_device_data
+        WHERE create_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY imei_card_number
+        ORDER BY dataCount DESC
+    </select>
+
+    <select id="statAlarmTrendByHour" resultType="java.util.Map">
+        SELECT 
+            DATE_FORMAT(create_time, '%Y-%m-%d %H:00:00') as hourTime,
+            COUNT(*) as dataCount,
+            SUM(CASE WHEN alarm_status = '1' THEN 1 ELSE 0 END) as alarmCount,
+            SUM(CASE WHEN water_infiltration_alarm_status = '1' THEN 1 ELSE 0 END) as waterInfiltrationCount,
+            SUM(CASE WHEN water_level_alarm_status = '1' THEN 1 ELSE 0 END) as waterLevelCount
+        FROM jg_device_data
+        WHERE imei_card_number = #{imeiCardNumber}
+          AND create_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY DATE_FORMAT(create_time, '%Y-%m-%d %H')
+        ORDER BY hourTime
+    </select>
+
+    <select id="statTemperatureTrendByHour" resultType="java.util.Map">
+        SELECT 
+            DATE_FORMAT(create_time, '%Y-%m-%d %H:00:00') as hourTime,
+            AVG(CAST(temperature_value AS DECIMAL(10,2))) as avgTemperature,
+            AVG(CAST(tilt_angle AS DECIMAL(10,2))) as avgTiltAngle,
+            AVG(CAST(battery_level AS DECIMAL(10,2))) as avgBatteryLevel
+        FROM jg_device_data
+        WHERE imei_card_number = #{imeiCardNumber}
+          AND create_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY DATE_FORMAT(create_time, '%Y-%m-%d %H')
+        ORDER BY hourTime
+    </select>
+
+    <select id="getAllImeiCardNumbers" resultType="java.lang.String">
+        SELECT DISTINCT imei_card_number 
+        FROM jg_device_data 
+        WHERE imei_card_number IS NOT NULL 
+          AND imei_card_number != ''
+        ORDER BY imei_card_number
+    </select>
+
+    <select id="getLatestDataByImei" resultType="java.util.Map">
+        SELECT 
+            id,
+            version_number as versionNumber,
+            battery_level as batteryLevel,
+            upload_time as uploadTime,
+            temperature_value as temperatureValue,
+            signal_strength as signalStrength,
+            alarm_status as alarmStatus,
+            angle_alarm_threshold as angleAlarmThreshold,
+            tilt_angle as tiltAngle,
+            activation_status as activationStatus,
+            water_infiltration_alarm_status as waterInfiltrationAlarmStatus,
+            water_level_alarm_status as waterLevelAlarmStatus,
+            sim_card_number as simCardNumber,
+            imei_card_number as imeiCardNumber,
+            create_time as createTime
+        FROM jg_device_data
+        WHERE imei_card_number = #{imeiCardNumber}
+        ORDER BY create_time DESC
+        LIMIT 1
+    </select>
+
+    <select id="getOverallStatistics" resultType="java.util.Map">
+        SELECT 
+            COUNT(*) as totalDataCount,
+            COUNT(DISTINCT imei_card_number) as deviceCount,
+            SUM(CASE WHEN alarm_status = '1' THEN 1 ELSE 0 END) as totalAlarmCount,
+            SUM(CASE WHEN water_infiltration_alarm_status = '1' THEN 1 ELSE 0 END) as waterInfiltrationCount,
+            SUM(CASE WHEN water_level_alarm_status = '1' THEN 1 ELSE 0 END) as waterLevelCount,
+            AVG(CAST(temperature_value AS DECIMAL(10,2))) as avgTemperature,
+            AVG(CAST(tilt_angle AS DECIMAL(10,2))) as avgTiltAngle,
+            AVG(CAST(battery_level AS DECIMAL(10,2))) as avgBatteryLevel
+        FROM jg_device_data
+        WHERE create_time BETWEEN #{startTime} AND #{endTime}
+    </select>
+
+</mapper>