From 94fee0b511279679b43e210878d3d36e5a14384b Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 30 九月 2025 09:14:10 +0800
Subject: [PATCH] 2025.9.30 1. 新增走航任务统计功能

---
 src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt |  289 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 288 insertions(+), 1 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
index a94c014..53989b5 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
@@ -1,19 +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.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.util.*
 import javax.persistence.Column
+import javax.persistence.GeneratedValue
+import javax.persistence.GenerationType
 import javax.persistence.Id
+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")
@@ -62,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")
@@ -101,6 +116,278 @@
             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(onEach: (BaseRealTimeData) -> Unit = {  }): BaseRealTimeData {
+    if (isEmpty()) {
+        return BaseRealTimeData()
+    }
+    //椋庡悜閲囩敤鍗曚綅鐭㈤噺娉曟眰鍙栧潎鍊�
+    var u = .0//涓滆タ鏂逛綅鍒嗛噺鎬诲拰
+    var v = .0//鍗楀寳鏂逛綅鍒嗛噺鎬诲拰
+    var c = 0//椋庡悜鏁版嵁璁℃暟
+
+    //闄ら鍚戝鐨勫叾浠栧洜瀛愰噰鐢ㄧ畻鏈钩鍧囨硶姹傚彇鍧囧��
+    val tmpList = mutableListOf<AvgPair>()
+    repeat(18) {
+        tmpList.add(AvgPair(0f, 0))
+    }
+
+    forEach {
+        onEach(it)
+        //椋庡悜
+        it.windDirection?.let { w ->
+            val r = Math.toRadians(w.toDouble())
+            u += sin(r)
+            v += cos(r)
+            c++
+        }
+        //鍏朵綑鍥犲瓙
+        tmpList[0].apply {
+            it.latitude?.let {
+                t += it.toFloat()
+                this.c++
+            }
+        }
+        tmpList[1].apply {
+            it.longitude?.let {
+                t += it.toFloat()
+                this.c++
+            }
+        }
+        tmpList[2].apply {
+            it.altitude?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[3].apply {
+            it.no2?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[4].apply {
+            it.co?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[5].apply {
+            it.h2s?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[6].apply {
+            it.so2?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[7].apply {
+            it.o3?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[8].apply {
+            it.pm25?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[9].apply {
+            it.pm10?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[10].apply {
+            it.temperature?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[11].apply {
+            it.humidity?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[12].apply {
+            it.voc?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[13].apply {
+            it.noi?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[14].apply {
+            it.velocity?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[15].apply {
+            it.windSpeed?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[16].apply {
+            it.height?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[17].apply {
+            it.no?.let {
+                t += it
+                this.c++
+            }
+        }
+    }
+
+    return RealTimeDataGridMin().apply {
+        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
+        latitude = tmpList[0].avg().toBigDecimal()
+        longitude = tmpList[1].avg().toBigDecimal()
+        altitude = tmpList[2].avg()
+        no2 = tmpList[3].avg()
+        co = tmpList[4].avg()
+        h2s = tmpList[5].avg()
+        so2 = tmpList[6].avg()
+        o3 = tmpList[7].avg()
+        pm25 = tmpList[8].avg()
+        pm10 = tmpList[9].avg()
+        temperature = tmpList[10].avg()
+        humidity = tmpList[11].avg()
+        voc = tmpList[12].avg()
+        noi = tmpList[13].avg()
+        velocity = tmpList[14].avg()
+        windSpeed = tmpList[15].avg()
+        height = tmpList[16].avg()
+        no = tmpList[17].avg()
+
+        if (c != 0) {
+            val avgU = u / c
+            val avgV = v / c
+            var a = atan(avgU / avgV)
+            a = Math.toDegrees(a)
+            /**
+             * avgU>0;avgV>0: 鐪熷疄瑙掑害澶勪簬绗竴璞¢檺锛屼慨姝e�间负+0掳
+             * avgU>0;avgV<0: 鐪熷疄瑙掑害澶勪簬绗簩璞¢檺锛屼慨姝e�间负+180掳
+             * avgU<0;avgV<0: 鐪熷疄瑙掑害澶勪簬绗笁璞¢檺锛屼慨姝e�间负+180掳
+             * avgU<0;avgV>0: 鐪熷疄瑙掑害澶勪簬绗洓璞¢檺锛屼慨姝e�间负+360掳
+             */
+            a += if (avgV > 0) {
+                if (avgU > 0) 0 else 360
+            } else {
+                180
+            }
+            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
 }
\ No newline at end of file

--
Gitblit v1.9.3