feiyu02
2025-09-30 94fee0b511279679b43e210878d3d36e5a14384b
src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
@@ -1,24 +1,31 @@
package com.flightfeather.uav.domain.entity
import com.flightfeather.uav.biz.dataprocess.AvgPair
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.dataprocess.AvgPair
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.lightshare.bean.FactorStatistics
import com.flightfeather.uav.socket.bean.AirData
import com.flightfeather.uav.socket.eunm.FactorType
import java.io.Serializable
import java.math.BigDecimal
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.util.*
import javax.persistence.Column
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import kotlin.math.*
import kotlin.math.atan
import kotlin.math.cos
import kotlin.math.round
import kotlin.math.sin
/**
 * 实时监测数据基类
 */
open class BaseRealTimeData {
open class BaseRealTimeData : Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Int? = null
    @Column(name = "device_code")
@@ -67,6 +74,9 @@
    @Column(name = "NOI")
    var noi: Float? = null
    @Column(name = "NO")
    var no: Float? = null
    var velocity: Float? = null
    @Column(name = "wind_speed")
@@ -106,11 +116,41 @@
            add(AirData().apply { setData(FactorType.WIND_SPEED, windSpeed) })
            add(AirData().apply { setData(FactorType.WIND_DIRECTION, windDirection) })
            add(AirData().apply { setData(FactorType.HEIGHT, height) })
            add(AirData().apply { setData(FactorType.NO, no) })
        }
    }
    fun getByFactorType(type: FactorType?): Float? {
        return when (type) {
            FactorType.NO2 -> no2
            FactorType.CO -> co
            FactorType.H2S -> h2s
            FactorType.SO2 -> so2
            FactorType.O3 -> o3
            FactorType.PM25 -> pm25
            FactorType.PM10 -> pm10
            FactorType.TEMPERATURE -> temperature
            FactorType.HUMIDITY -> humidity
            FactorType.VOC -> voc
            FactorType.NOI -> noi
            FactorType.LNG -> longitude?.toFloat()
            FactorType.LAT -> latitude?.toFloat()
            FactorType.VELOCITY -> velocity
//            FactorType.TIME -> dataTime?.time?.toFloat()
            FactorType.WIND_SPEED -> windSpeed
            FactorType.WIND_DIRECTION -> windDirection
            FactorType.HEIGHT -> height
            FactorType.NO -> no
            else -> null
        }
    }
}
fun List<BaseRealTimeData>.avg(): RealTimeDataGridMin {
fun List<BaseRealTimeData>.avg(onEach: (BaseRealTimeData) -> Unit = {  }): BaseRealTimeData {
    if (isEmpty()) {
        return BaseRealTimeData()
    }
    //风向采用单位矢量法求取均值
    var u = .0//东西方位分量总和
    var v = .0//南北方位分量总和
@@ -118,13 +158,14 @@
    //除风向外的其他因子采用算术平均法求取均值
    val tmpList = mutableListOf<AvgPair>()
    repeat(17) {
    repeat(18) {
        tmpList.add(AvgPair(0f, 0))
    }
    forEach {
        onEach(it)
        //风向
        it.windDirection?.let {w ->
        it.windDirection?.let { w ->
            val r = Math.toRadians(w.toDouble())
            u += sin(r)
            v += cos(r)
@@ -233,10 +274,18 @@
                this.c++
            }
        }
        tmpList[17].apply {
            it.no?.let {
                t += it
                this.c++
            }
        }
    }
    return RealTimeDataGridMin().apply {
        val time = LocalDateTime.ofInstant(get(0).dataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0)
        val time = LocalDateTime
            .ofInstant(get(0).dataTime?.toInstant() ?: Date().toInstant(), ZoneId.systemDefault())
            .withSecond(0)
        deviceCode = get(0).deviceCode
        dataTime = Date.from(time.atZone(ZoneId.systemDefault()).toInstant())
        createTime = dataTime
@@ -257,6 +306,7 @@
        velocity = tmpList[14].avg()
        windSpeed = tmpList[15].avg()
        height = tmpList[16].avg()
        no = tmpList[17].avg()
        if (c != 0) {
            val avgU = u / c
@@ -277,4 +327,67 @@
            windDirection = round(a.toFloat())
        }
    }
}
/**
 * 计算实时监测数据列表的统计信息
 * 为每种环境因子计算最小值、最大值和平均值
 *
 * @return 包含各环境因子统计信息的FactorStatistics列表
 *         每个FactorStatistics对象包含因子类型、最小值、最大值和平均值
 */
fun List<BaseRealTimeData>.calDataStatistics(): List<FactorStatistics> {
    // 初始化各环境因子的统计对象列表
    val statistics = mutableListOf<FactorStatistics>()
    listOf(
        FactorType.NO2,
        FactorType.CO,
        FactorType.H2S,
        FactorType.SO2,
        FactorType.O3,
        FactorType.PM25,
        FactorType.PM10,
        FactorType.VOC,
        FactorType.NOI,
        FactorType.VELOCITY,
        FactorType.WIND_SPEED,
        FactorType.HEIGHT,
        FactorType.NO
    ).forEach { statistics.add(FactorStatistics(it)) }
    // 计算平均值并同时更新各因子的最小值和最大值
    val avgData = avg { item ->
        // 更新每个因子的最小和最大值
        statistics[0].updateMinAndMaxValue(item.no2)
        statistics[1].updateMinAndMaxValue(item.co)
        statistics[2].updateMinAndMaxValue(item.h2s)
        statistics[3].updateMinAndMaxValue(item.so2)
        statistics[4].updateMinAndMaxValue(item.o3)
        statistics[5].updateMinAndMaxValue(item.pm25)
        statistics[6].updateMinAndMaxValue(item.pm10)
        statistics[7].updateMinAndMaxValue(item.voc)
        statistics[8].updateMinAndMaxValue(item.noi)
        statistics[9].updateMinAndMaxValue(item.velocity)
        statistics[10].updateMinAndMaxValue(item.windSpeed)
        statistics[11].updateMinAndMaxValue(item.height)
        statistics[12].updateMinAndMaxValue(item.no)
    }
    // 将计算得到的平均值设置到对应的统计对象中
    statistics[0].avgValue = avgData.no2 ?: 0f
    statistics[1].avgValue = avgData.co ?: 0f
    statistics[2].avgValue = avgData.h2s ?: 0f
    statistics[3].avgValue = avgData.so2 ?: 0f
    statistics[4].avgValue = avgData.o3 ?: 0f
    statistics[5].avgValue = avgData.pm25 ?: 0f
    statistics[6].avgValue = avgData.pm10 ?: 0f
    statistics[7].avgValue = avgData.voc ?: 0f
    statistics[8].avgValue = avgData.noi ?: 0f
    statistics[9].avgValue = avgData.velocity ?: 0f
    statistics[10].avgValue = avgData.windSpeed ?: 0f
    statistics[11].avgValue = avgData.height ?: 0f
    statistics[12].avgValue = avgData.no ?: 0f
    return statistics
}