Sfoglia il codice sorgente

feat(pressure): 新增消防压力数据统计与分析功能

- 实现消防压力设备数据的平均值计算
- 添加按天统计最大、最小、平均压力值功能
- 实现各类报警次数统计功能
- 添加压力地理分布数据查询
- 实现GPRS信号与压力稳定性分析功能- 新增消防压力数据实体类及数据库映射
- 创建压力数据服务接口及实现类
- 添加压力数据控制器提供REST API接口- 实现MyBatis Mapper接口及XML映射文件
- 添加Swagger注解支持接口文档生成
林仔 8 mesi fa
parent
commit
be852798bc

+ 66 - 0
pipe-network-service/zksy-admin/src/main/java/com/zksy/web/controller/base/pressure/FirefightingPressureController.java

@@ -0,0 +1,66 @@
+package com.zksy.web.controller.base.pressure;
+
+import com.zksy.base.pressure.service.FirefightingPressureService;
+import com.zksy.common.core.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.aspectj.weaver.loadtime.Aj;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+@Api(tags = "消防压力设备数据")
+@RestController
+@RequestMapping("/api/pressure")
+public class FirefightingPressureController {
+
+    @Autowired
+    private FirefightingPressureService firefightingPressureService;
+
+    /**
+     * 1. 获取某时间段的平均压力
+     */
+    @GetMapping("/average")
+    @ApiOperation(value = "获取某时间段的平均压力")
+    public AjaxResult getAveragePressure(@RequestParam String startTime, @RequestParam String endTime) {
+        return AjaxResult.success(firefightingPressureService.getAveragePressure(startTime, endTime));
+    }
+
+    /**
+     * 2. 按天统计最大、最小、平均值
+     */
+    @GetMapping("/daily-stats")
+    @ApiOperation(value = "按天统计最大、最小、平均值")
+    public AjaxResult getDailyStats(@RequestParam String startTime,@RequestParam String endTime) {
+        return AjaxResult.success(firefightingPressureService.getDailyStats(startTime, endTime));
+    }
+
+    /**
+     * 3. 统计各类报警次数
+     */
+    @GetMapping("/alarm-counts")
+    @ApiOperation(value = "统计各类报警次数")
+    public AjaxResult getAlarmCounts(@RequestParam String startTime, @RequestParam String endTime) {
+        return AjaxResult.success(firefightingPressureService.getAlarmCounts(startTime, endTime));
+    }
+
+    /**
+     * 4. 压力地理分布
+     */
+    @GetMapping("/distribution")
+    @ApiOperation(value = "压力地理分布")
+    public AjaxResult getPressureDistribution(@RequestParam String startTime, @RequestParam String endTime) {
+        return AjaxResult.success(firefightingPressureService.getPressureDistribution(startTime, endTime));
+    }
+
+    /**
+     * 5. GPRS信号与压力稳定性分析
+     */
+    @GetMapping("/signal-vs-pressure")
+    @ApiOperation(value = "GPRS信号 pressuresability")
+    public AjaxResult getSignalVsPressure(@RequestParam String startTime, @RequestParam String endTime) {
+        return AjaxResult.success(firefightingPressureService.getSignalVsPressure(startTime, endTime));
+    }
+}

+ 139 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/environment/service/impl/ERealTimeDataServiceImpl.java

@@ -0,0 +1,139 @@
+package com.zksy.base.environment.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.base.environment.domain.ERealTimeData;
+import com.zksy.base.environment.mapper.ERealTimeDataMapper;
+import com.zksy.base.environment.service.ERealTimeDataService;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+* @author Administrator
+* @description 针对表【e_real_time_data(环境实时数据)】的数据库操作Service实现
+* @createDate 2025-08-27 10:30:48
+*/
+@Service
+public class ERealTimeDataServiceImpl extends ServiceImpl<ERealTimeDataMapper, ERealTimeData>
+        implements ERealTimeDataService {
+
+    @Override
+    public ERealTimeData getLatestByDeviceNode(Integer deviceId, Integer nodeId) {
+        return lambdaQuery()
+                .eq(ERealTimeData::getDeviceId, deviceId)
+                .eq(ERealTimeData::getNodeId, nodeId)
+                .orderByDesc(ERealTimeData::getCreateTime)
+                .last("limit 1")
+                .one();
+    }
+
+    @Override
+    public Map<String, Object> getDailyStats(Integer deviceId, Integer nodeId, LocalDate date) {
+        LocalDateTime start = date.atStartOfDay();
+        LocalDateTime end = start.plusDays(1);
+
+        List<ERealTimeData> list = lambdaQuery()
+                .eq(ERealTimeData::getDeviceId, deviceId)
+                .eq(ERealTimeData::getNodeId, nodeId)
+                .between(ERealTimeData::getCreateTime, start, end)
+                .list();
+
+        Map<String, Object> result = new HashMap<>();
+        if (list.isEmpty()) {
+            result.put("avgValue", 0);
+            result.put("maxValue", 0);
+            result.put("minValue", 0);
+            result.put("records", Collections.emptyList());
+            return result;
+        }
+
+        List<Double> valueList = list.stream().map(this::getNodeValue).collect(Collectors.toList());
+
+        result.put("avgValue", valueList.stream().mapToDouble(Double::doubleValue).average().orElse(0));
+        result.put("maxValue", valueList.stream().mapToDouble(Double::doubleValue).max().orElse(0));
+        result.put("minValue", valueList.stream().mapToDouble(Double::doubleValue).min().orElse(0));
+
+        List<Map<String, Object>> records = list.stream().map(d -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("time", d.getCreateTime());
+            map.put("value", getNodeValue(d));
+            return map;
+        }).collect(Collectors.toList());
+        result.put("records", records);
+
+        return result;
+    }
+
+    @Override
+    public List<Map<String, Object>> getTrend(Integer deviceId, Integer nodeId, LocalDateTime start, LocalDateTime end) {
+        return lambdaQuery()
+                .eq(ERealTimeData::getDeviceId, deviceId)
+                .eq(ERealTimeData::getNodeId, nodeId)
+                .between(ERealTimeData::getCreateTime, start, end)
+                .orderByAsc(ERealTimeData::getCreateTime)
+                .list()
+                .stream()
+                .map(d -> {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put("time", d.getCreateTime());
+                    map.put("value", getNodeValue(d));
+                    return map;
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<Map<String, Object>> getAlarms(Integer deviceId, Integer nodeId, LocalDateTime start, LocalDateTime end,
+                                               Double threshold) {
+        List<ERealTimeData> list = lambdaQuery()
+                .eq(ERealTimeData::getDeviceId, deviceId)
+                .eq(ERealTimeData::getNodeId, nodeId)
+                .between(ERealTimeData::getCreateTime, start, end)
+                .list();
+
+        if (threshold != null) {
+            list = list.stream().filter(d -> getNodeValue(d) > threshold).collect(Collectors.toList());
+        }
+
+        return list.stream().map(d -> {
+            Map<String, Object> map = new HashMap<>();
+            map.put("time", d.getCreateTime());
+            map.put("value", getNodeValue(d));
+            return map;
+        }).collect(Collectors.toList());
+    }
+
+    // 工具方法:根据节点类型获取实际值
+    private Double getNodeValue(ERealTimeData data) {
+        if (data.getNodeId() == null) return 0d;
+
+        switch (data.getNodeId()) {
+            case 1: // 悬浮物
+                try {
+                    return data.getFloatValue() == null ? 0d : Double.parseDouble(data.getFloatValue());
+                } catch (NumberFormatException e) {
+                    return 0d;
+                }
+            case 2: // COD
+            case 3: // 氨氮
+            case 4: // 电导率
+            case 5: // PH
+                return data.getHum() == null ? 0d : data.getHum().doubleValue();
+            default:
+                return 0d;
+        }
+    }
+}
+
+
+
+

+ 165 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/pressure/domain/FirefightingPressure.java

@@ -0,0 +1,165 @@
+package com.zksy.base.pressure.domain;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+/**
+ * 消防压力表
+ * @TableName firefighting_pressure
+ */
+@Data
+public class FirefightingPressure implements Serializable {
+    /**
+     * 主键
+     */
+    private String id;
+
+    /**
+     * 中心站地址
+     */
+    private String centralStation;
+
+    /**
+     * 遥测站地址
+     */
+    private String telemeteringStation;
+
+    /**
+     * 密码
+     */
+    private String password;
+
+    /**
+     * 功能码
+     */
+    private String functionCode;
+
+    /**
+     * 流水号
+     */
+    private String serialNumber;
+
+    /**
+     * 发报时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime sendingTime;
+
+    /**
+     * 观测时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime observedTime;
+
+    /**
+     * GPRS信号质量
+     */
+    private Double gprsSignal;
+
+    /**
+     * 主机电池电压
+     */
+    private Double hostVoltage;
+
+    /**
+     * 经度
+     */
+    private BigDecimal longitude;
+
+    /**
+     * 纬度
+     */
+    private BigDecimal latitude;
+
+    /**
+     * 压力值
+     */
+    private Double pressureValue;
+
+    /**
+     * 保留
+     */
+    private Integer d31D12;
+
+    /**
+     * 压力变幅报警
+     */
+    private Integer d14;
+
+    /**
+     * 压力下下限报警
+     */
+    private Integer d13;
+
+    /**
+     * 压力上上限报警
+     */
+    private Integer d12;
+
+    /**
+     * 压力下线报警
+     */
+    private Integer d11;
+
+    /**
+     * 压力上限报警
+     */
+    private Integer d10;
+
+    /**
+     * 传感器状态
+     */
+    private Integer d9;
+
+    /**
+     * 保留
+     */
+    private Integer d8;
+
+    /**
+     * 保留
+     */
+    private Integer d7;
+
+    /**
+     * 保留
+     */
+    private Integer d6;
+
+    /**
+     * 保留(6245保留,6242产品的取水报警),1-报警0-正常
+     */
+    private Integer d5;
+
+    /**
+     * 保留
+     */
+    private Integer d4;
+
+    /**
+     * 保留
+     */
+    private Integer d3;
+
+    /**
+     * 保留(6245保留,6242产品的取旋转报警),1-报警0-正常
+     */
+    private Integer d2;
+
+    /**
+     * 倾斜报警1-报警,0-正常
+     */
+    private Integer d1;
+
+    /**
+     * 保留
+     */
+    private Integer d0;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private LocalDateTime createTime;
+}

+ 23 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/pressure/mapper/FirefightingPressureMapper.java

@@ -0,0 +1,23 @@
+package com.zksy.base.pressure.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zksy.base.pressure.domain.FirefightingPressure;
+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 FirefightingPressureMapper extends BaseMapper<FirefightingPressure> {
+
+    List<Map<String, Object>> getDailyPressureStats(@Param("startTime") LocalDateTime startTime,
+                                                    @Param("endTime") LocalDateTime endTime);
+
+    List<Map<String, Object>> getPressureDistribution(@Param("startTime") LocalDateTime startTime,
+                                                      @Param("endTime") LocalDateTime endTime);
+
+    List<Map<String, Object>> getSignalVsPressure(@Param("startTime") LocalDateTime startTime,
+                                                  @Param("endTime") LocalDateTime endTime);
+}

+ 22 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/pressure/service/FirefightingPressureService.java

@@ -0,0 +1,22 @@
+package com.zksy.base.pressure.service;
+
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.zksy.base.pressure.domain.FirefightingPressure;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+public interface FirefightingPressureService extends IService<FirefightingPressure> {
+
+    Double getAveragePressure(String startTime, String endTime);
+
+    List<Map<String, Object>> getDailyStats(String startTime, String endTime);
+
+    Map<String, Long> getAlarmCounts(String startTime, String endTime);
+
+    List<Map<String, Object>> getPressureDistribution(String startTime, String endTime);
+
+    List<Map<String, Object>> getSignalVsPressure(String startTime, String endTime);
+}

+ 73 - 0
pipe-network-service/zksy-system/src/main/java/com/zksy/base/pressure/service/impl/FirefightingPressureServiceImpl.java

@@ -0,0 +1,73 @@
+package com.zksy.base.pressure.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zksy.base.pressure.domain.FirefightingPressure;
+import com.zksy.base.pressure.mapper.FirefightingPressureMapper;
+import com.zksy.base.pressure.service.FirefightingPressureService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+@Service
+public class FirefightingPressureServiceImpl extends ServiceImpl<FirefightingPressureMapper, FirefightingPressure>
+        implements FirefightingPressureService {
+    @Autowired
+    private FirefightingPressureMapper firefightingPressureMapper;
+    private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    private LocalDateTime parse(String time) {
+        return LocalDateTime.parse(time, FORMATTER);
+    }
+
+    @Override
+    public Double getAveragePressure(String startTime, String endTime) {
+        LocalDateTime start = parse(startTime);
+        LocalDateTime end = parse(endTime);
+        List<Double> values = this.lambdaQuery()
+                .between(FirefightingPressure::getObservedTime, start, end)
+                .select(FirefightingPressure::getPressureValue)
+                .list()
+                .stream()
+                .map(FirefightingPressure::getPressureValue)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toList());
+        return values.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
+    }
+
+    @Override
+    public List<Map<String, Object>> getDailyStats(String startTime, String endTime) {
+        return firefightingPressureMapper.getDailyPressureStats(parse(startTime), parse(endTime));
+    }
+
+    @Override
+    public Map<String, Long> getAlarmCounts(String startTime, String endTime) {
+        List<FirefightingPressure> list = this.lambdaQuery()
+                .between(FirefightingPressure::getObservedTime, parse(startTime), parse(endTime))
+                .list();
+
+        Map<String, Long> result = new HashMap<>();
+        result.put("pressureHigh", list.stream().filter(x -> x.getD10() != null && x.getD10() == 1).count());
+        result.put("pressureLow", list.stream().filter(x -> x.getD11() != null && x.getD11() == 1).count());
+        result.put("pressureHighHigh", list.stream().filter(x -> x.getD12() != null && x.getD12() == 1).count());
+        result.put("pressureLowLow", list.stream().filter(x -> x.getD13() != null && x.getD13() == 1).count());
+        result.put("tilt", list.stream().filter(x -> x.getD1() != null && x.getD1() == 1).count());
+        return result;
+    }
+
+    @Override
+    public List<Map<String, Object>> getPressureDistribution(String startTime, String endTime) {
+        return firefightingPressureMapper.getPressureDistribution(parse(startTime), parse(endTime));
+    }
+
+    @Override
+    public List<Map<String, Object>> getSignalVsPressure(String startTime, String endTime) {
+        return firefightingPressureMapper.getSignalVsPressure(parse(startTime), parse(endTime));
+    }
+}

+ 86 - 0
pipe-network-service/zksy-system/src/main/resources/mapper/base/pressure/FirefightingPressureMapper.xml

@@ -0,0 +1,86 @@
+<?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.pressure.mapper.FirefightingPressureMapper">
+
+    <resultMap id="BaseResultMap" type="com.zksy.base.pressure.domain.FirefightingPressure">
+        <id property="id" column="id" jdbcType="VARCHAR"/>
+        <result property="centralStation" column="central_station" jdbcType="VARCHAR"/>
+        <result property="telemeteringStation" column="telemetering_station" jdbcType="VARCHAR"/>
+        <result property="password" column="password" jdbcType="VARCHAR"/>
+        <result property="functionCode" column="function_code" jdbcType="VARCHAR"/>
+        <result property="serialNumber" column="serial_number" jdbcType="VARCHAR"/>
+        <result property="sendingTime" column="sending_time" jdbcType="TIMESTAMP"/>
+        <result property="observedTime" column="observed_time" jdbcType="TIMESTAMP"/>
+        <result property="gprsSignal" column="gprs_signal" jdbcType="DOUBLE"/>
+        <result property="hostVoltage" column="host_voltage" jdbcType="DOUBLE"/>
+        <result property="longitude" column="longitude" jdbcType="DECIMAL"/>
+        <result property="latitude" column="latitude" jdbcType="DECIMAL"/>
+        <result property="pressureValue" column="pressure_value" jdbcType="DOUBLE"/>
+        <result property="d31D12" column="D31_D12" jdbcType="TINYINT"/>
+        <result property="d14" column="D14" jdbcType="TINYINT"/>
+        <result property="d13" column="D13" jdbcType="TINYINT"/>
+        <result property="d12" column="D12" jdbcType="TINYINT"/>
+        <result property="d11" column="D11" jdbcType="TINYINT"/>
+        <result property="d10" column="D10" jdbcType="TINYINT"/>
+        <result property="d9" column="D9" jdbcType="TINYINT"/>
+        <result property="d8" column="D8" jdbcType="TINYINT"/>
+        <result property="d7" column="D7" jdbcType="TINYINT"/>
+        <result property="d6" column="D6" jdbcType="TINYINT"/>
+        <result property="d5" column="D5" jdbcType="TINYINT"/>
+        <result property="d4" column="D4" jdbcType="TINYINT"/>
+        <result property="d3" column="D3" jdbcType="TINYINT"/>
+        <result property="d2" column="D2" jdbcType="TINYINT"/>
+        <result property="d1" column="D1" jdbcType="TINYINT"/>
+        <result property="d0" column="D0" jdbcType="TINYINT"/>
+        <result property="createTime" column="createTime" jdbcType="TIMESTAMP"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,central_station,telemetering_station,
+        password,function_code,serial_number,
+        sending_time,observed_time,gprs_signal,
+        host_voltage,longitude,latitude,
+        pressure_value,D31_D12,D14,
+        D13,D12,D11,
+        D10,D9,D8,
+        D7,D6,D5,
+        D4,D3,D2,
+        D1,D0
+    </sql>
+
+    <!-- 按天统计压力(保留两位小数) -->
+    <select id="getDailyPressureStats" resultType="map">
+        SELECT DATE(observed_time) as date,
+            ROUND(MAX(pressure_value), 2) as maxPressure,
+            ROUND(MIN(pressure_value), 2) as minPressure,
+            ROUND(AVG(pressure_value), 2) as avgPressure
+        FROM firefighting_pressure
+        WHERE observed_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY DATE(observed_time)
+        ORDER BY date
+    </select>
+
+    <!-- 压力地理分布(保留两位小数) -->
+    <select id="getPressureDistribution" resultType="map">
+        SELECT telemetering_station,
+               longitude,
+               latitude,
+               ROUND(AVG(pressure_value), 2) as avgPressure
+        FROM firefighting_pressure
+        WHERE observed_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY telemetering_station, longitude, latitude
+    </select>
+
+    <!-- 信号质量 vs 压力(保留两位小数) -->
+    <select id="getSignalVsPressure" resultType="map">
+        SELECT ROUND(gprs_signal) as signalLevel,
+               ROUND(AVG(pressure_value), 2) as avgPressure,
+               ROUND(STDDEV(pressure_value), 2) as pressureStdDev
+        FROM firefighting_pressure
+        WHERE observed_time BETWEEN #{startTime} AND #{endTime}
+        GROUP BY ROUND(gprs_signal)
+        ORDER BY signalLevel
+    </select>
+</mapper>