From e731486b50c4ea6e2d28f302df449b4bd0b2be57 Mon Sep 17 00:00:00 2001
From: Riku <risaku@163.com>
Date: 星期一, 02 六月 2025 23:02:59 +0800
Subject: [PATCH] 1. 新增走航动态溯源功能

---
 src/main/kotlin/com/flightfeather/uav/socket/sender/WebSocketMessage.kt                   |   21 +
 src/test/kotlin/com/flightfeather/uav/biz/dataprocess/DataProcessTest.kt                  |   11 +
 src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSourceTest.kt         |   33 +++
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt            |  116 ++++++++++
 src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt            |    6 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt               |   24 +
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSource.kt             |   71 +++++
 src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt               |   18 -
 src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt                        |   29 ++
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt      |    9 
 src/main/kotlin/com/flightfeather/uav/socket/sender/MsgType.kt                            |   18 +
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt   |    2 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt |    4 
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt               |    2 
 src/main/kotlin/com/flightfeather/uav/socket/decoder/UnderwayWebSocketParser.kt           |   60 +++++
 src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt    |   11 
 src/main/kotlin/com/flightfeather/uav/lightshare/bean/SceneInfoVo.kt                      |   13 +
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt            |  199 ++++++++++++-----
 18 files changed, 545 insertions(+), 102 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
index 6a44390..1abfb01 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
@@ -20,7 +20,7 @@
                     it.startData = data
                 }
                 // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
-                if (!isContinue || needCut(it)) {
+                if (!isContinue || needCut(it, hasException[f])) {
                     recordException(s, it, data)
                 } else {
                     if (hasException[f] == true) {
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
new file mode 100644
index 0000000..cefe129
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
@@ -0,0 +1,116 @@
+package com.flightfeather.uav.biz.sourcetrace
+
+import com.flightfeather.uav.biz.FactorFilter
+import com.flightfeather.uav.biz.dataanalysis.BaseExceptionAnalysis
+import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig
+import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig
+import com.flightfeather.uav.biz.sourcetrace.exceptiontype.*
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedSummary
+import com.flightfeather.uav.common.utils.GsonUtils
+import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.domain.repository.SceneInfoRep
+import com.flightfeather.uav.socket.eunm.FactorType
+import com.flightfeather.uav.socket.sender.MsgType
+import com.flightfeather.uav.socket.sender.UnderwayWebSocketSender
+import java.util.*
+
+/**
+ * 姹℃煋绾跨储鎺у埗鍣�
+ * @date 2025/5/27
+ * @author feiyu02
+ */
+class SourceTraceController {
+
+
+    /**
+     * 5. 姹℃煋婧愮殑琚壂鎻忔鏁�
+     * 姣忎竴鍒婚挓瀵瑰巻鍙茬嚎绱㈣繘琛岀粺璁★紝鎻愬嚭浼氬晢寤鸿锛堢姹℃煋婧愯緝杩溿�佹薄鏌撴簮鏁伴噺銆佸嚭鐜版鏁帮級銆佽蛋鑸矾绾胯皟鏁村缓璁紙绂绘薄鏌撴簮杈冭繎銆佽蛋鑸建杩规湭鎺ヨ繎婧簮鍦烘櫙锛�
+     */
+
+    constructor(sceneInfoRep: SceneInfoRep, factorFilter: FactorFilter?) {
+        this.sceneInfoRep = sceneInfoRep
+        this.config = if (factorFilter != null)
+            RTExcWindLevelConfig(factorFilter)
+        else
+            RTExcWindLevelConfig(
+                FactorFilter.builder()
+//                .withMain(FactorType.NO2)
+                    .withMain(FactorType.CO)
+//                .withMain(FactorType.H2S)
+//                .withMain(FactorType.SO2)
+//                .withMain(FactorType.O3)
+                    .withMain(FactorType.PM25)
+                    .withMain(FactorType.PM10)
+                    .withMain(FactorType.VOC)
+                    .create()
+            )
+        pollutedSummary = PollutedSummary(config){ summaryCallback(it)}
+        newTask()
+    }
+
+    constructor(sceneInfoRep: SceneInfoRep) : this(sceneInfoRep, null)
+
+    private val pollutedSummary:PollutedSummary
+
+    private val sceneInfoRep: SceneInfoRep
+
+    private val config: RTExcWindLevelConfig
+
+    private val taskList = mutableListOf<BaseExceptionAnalysis<RTExcWindLevelConfig, PollutedClue>>()
+
+    fun initTask() {
+        taskList.clear()
+        newTask()
+        pollutedSummary.clear()
+    }
+
+    private fun newTask() {
+        taskList.apply {
+            add(RTExcWindLevel1(config) { exceptionCallback(it) }.also { it.init() })
+            add(RTExcWindLevel1_1(config) { exceptionCallback(it) }.also { it.init() })
+            add(RTExcWindLevel4(config) { exceptionCallback(it) }.also { it.init() })
+            add(RTExcWindLevel6(config) { exceptionCallback(it) }.also { it.init() })
+        }
+    }
+
+    /**
+     * 璁$畻鏂扮殑涓�鏉″疄鏃惰蛋鑸暟鎹�
+     */
+    fun addOneData(data: BaseRealTimeData) {
+        // 璁$畻寮傚父
+        taskList.forEach { it.onNextData(data) }
+        pollutedSummary.refreshLatestMonitorData(data)
+        // 闄愬畾鏃堕棿鍐呮病鏈夋柊鏁版嵁浼犲叆锛屽垯缁撴潫褰撳墠鐨勮绠�
+    }
+
+    /**
+     * 瓒呮椂澶勭悊锛岃緝闀挎椂闂存病鏈夋柊鏁版嵁杩涘叆锛岃繘琛屽垵濮嬪寲鎿嶄綔
+     */
+    private fun dealOnTimeout() {
+        val timer = Timer(true)
+        timer.schedule(object : TimerTask() {
+            override fun run() {
+                TODO("Not yet implemented")
+            }
+        }, 60 * 1000)
+        timer.cancel()
+    }
+
+    // 鏁版嵁绐佸彉寮傚父鍥炶皟
+    private fun exceptionCallback(ex: PollutedClue) {
+        // 婧簮姹℃煋婧愪俊鎭�
+        ex.searchScenes(sceneInfoRep)
+
+        // 璁板綍姹℃煋绾跨储
+        pollutedSummary.addClue(ex)
+
+        // 骞挎挱姹℃煋婧簮寮傚父缁撴灉
+        UnderwayWebSocketSender.broadcast(MsgType.PolClue.value, ex)
+    }
+
+    private fun summaryCallback(ex: PollutedSummary.AnalysisResult) {
+        // 骞挎挱姹℃煋婧簮寮傚父缁撴灉
+        UnderwayWebSocketSender.broadcast(MsgType.AnaResult.value, ex)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
index 9ca9419..1e08443 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
@@ -18,9 +18,9 @@
     )
 
     // 闄愬畾璺濈鍐咃紙鍗曚綅锛氱背锛�
-    var distanceLimit = 1000
+    var distanceLimit = 3000
     // 闄愬畾鏃堕棿鍐咃紙鍗曚綅锛氬垎閽燂級
-    var timeLimit = 2
+    var timeLimit = 3
 
     // 0 - 1绾ч
     var windLevelCondition1 = WindLevelCondition(
@@ -52,4 +52,9 @@
 
     // 婧簮鎵╂暎鍋忕Щ瑙掑害锛堝崟浣嶏細搴︼級
     var sourceTraceDegOffset = 120.0
+
+    // 瀹氭椂绾跨储鍒嗘瀽鏃堕棿闂撮殧(鍗曚綅锛氬垎閽�)
+    var analysisPeriod = 15
+    // 瀹氭椂鍒嗘瀽闂撮殧涓紝绔嬪嵆杩涜绾跨储鍒嗘瀽鐨勬渶灏忕嚎绱㈤噺(鍗曚綅锛氫釜)
+    var analysisCount = 3
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
index b1010a1..e1fe81d 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRTExcWindLevel.kt
@@ -39,6 +39,7 @@
 
     override fun judgeException(p: BaseRealTimeData?, n: BaseRealTimeData): MutableMap<FactorType, Boolean> {
         val res = mutableMapOf<FactorType, Boolean>()
+        println()
         config.factorFilter.mainList().forEach { f ->
             if (p?.getByFactorType(f) == null || n.getByFactorType(f) == null || n.windSpeed == null) {
                 res[f] = (false)
@@ -48,17 +49,20 @@
             val con = windLevelCondition
 
             if (n.windSpeed!! in con.windSpeed.first..con.windSpeed.second) {
+                println("椋庨�燂細${n.windSpeed}锛孾${con.windSpeed.first} - ${con.windSpeed.second}]")
                 val pValue = p.getByFactorType(f)!!
                 val nValue = n.getByFactorType(f)!!
                 // 璁$畻鍚庝竴涓暟鎹浉姣斾簬鍓嶄竴涓暟鎹殑鍙樺寲鐜�
                 val r = (nValue - pValue) / pValue
                 val b1 = r >= con.mutationRate.first
+                println("鍥犲瓙锛�${f.des}锛屽箙搴︼細${r}锛岄檺瀹氾細${con.mutationRate.first}锛�${b1}")
                 res[f] = b1
             } else {
                 res[f] = false
             }
         }
 
+
         return res
     }
 
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
index fac9ce7..6f7fd3c 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
@@ -91,7 +91,7 @@
         if (distanceRange.first == .0) {
             result.add(center)
         } else {
-            // 浠庡紑濮嬭搴﹀惊鐜绠楀潗鏍囩偣鍊肩粨鏉熻搴︼紝姝ラ暱1掳
+            // 浠庡紑濮嬭搴﹀惊鐜绠楀潗鏍囩偣鑷崇粨鏉熻搴︼紝姝ラ暱1掳
             var startDeg = sDeg
             while (startDeg <= eDeg) {
                 val p = MapUtil.getPointByLen(center, distanceRange.first, startDeg * PI / 180)
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt
index aa722b8..489e66a 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedData.kt
@@ -15,16 +15,6 @@
 class PollutedData() {
 
     /**
-     *
-     * 1. 杞1.5m/s鍙婁互涓嬶紝
-     * 	鍓嶅悗鍊间笂鍗囧箙搴﹀湪50%浠ヤ笂1娆★紝璁や负鏄复杩戝彂鐢�(50绫�)
-     * 	鍓嶅悗鍊间笂鍗囧箙搴﹀湪20%浠ヤ笂1娆★紝璁や负鏄繙璺濈鍙戠敓锛�50绫� - 500绫筹級
-     * 	1.5 m/s鍙婁互涓嬶紝闈欑ǔ澶╂皵锛屼复杩戝彂鐢�(50绫�)
-     * 2. 1.6 - 7.9 m/s锛屽墠鍚庡�间笂鍗囧箙搴﹀湪20%浠ヤ笂3娆★紝璁や负鏄繙璺濈鍙戠敓锛�50绫� - 1鍏噷锛�
-     * 3. 8 - 13.8 m/s 浠ヤ笂锛屽墠鍚庡�间笂鍗囧箙搴﹀湪10%浠ヤ笂3娆★紝璁や负鏄繙璺濈鍙戠敓(50绫� - 2鍏噷)
-     */
-
-    /**
      * 9. 鍏宠仈鍥犲瓙
      * 	a) pm2.5銆乸m10鐗瑰埆楂橈紝涓よ�呭湪鍚勬儏鍐典笅鍚屾灞曠ず锛宲m2.5鍗爌m10鐨勬瘮閲嶅彉鍖栵紝姣旈噸瓒婇珮锛岃秺鏈夊彲鑳芥槸椁愰ギ
      * 	b) pm10鐗瑰埆楂樸�乸m2.5杈冮珮锛屽ぇ棰楃矑鎵皹姹℃煋锛屽彧灞曠ずpm10锛宲m2.5鍗爌m10鐨勬瘮閲嶅彉鍖栵紝宸ュ湴涓轰富
@@ -62,6 +52,8 @@
             dataList.add(it)
             dataVoList.add(it.toDataVo())
         }
+
+        calPer()
     }
 
     var deviceCode: String? = null
@@ -86,6 +78,8 @@
 
     // 鍥犲瓙閲忕骇鍙樺寲骞呭害
     var percentage: Double? = null
+    // 鍥犲瓙閲忕骇骞冲潎鍙樺寲骞呭害
+    var avgPer: Double? = null
 
     // 鍙戠敓娆℃暟
     var times: Int? = null
@@ -93,4 +87,14 @@
     // 寮傚父鐩戞祴鏁版嵁
     var dataList: MutableList<BaseRealTimeData> = mutableListOf()
     var dataVoList: MutableList<DataVo> = mutableListOf()
+
+    private fun calPer() {
+        if (dataList.size < 2) return
+
+        var total = .0
+        for (i in 0 until dataList.size - 1) {
+            total += dataList[i].getByFactorType(selectedFactor!!.main)!!
+        }
+        avgPer = total / (dataList.size - 1)
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSource.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSource.kt
index 2dc6b58..c948fe3 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSource.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSource.kt
@@ -4,7 +4,13 @@
 import com.flightfeather.uav.common.utils.MapUtil
 import com.flightfeather.uav.domain.entity.SceneInfo
 import com.flightfeather.uav.domain.repository.SceneInfoRep
+import com.flightfeather.uav.lightshare.bean.AreaVo
+import com.flightfeather.uav.lightshare.bean.SceneInfoVo
+import com.flightfeather.uav.lightshare.eunm.SceneType
+import com.flightfeather.uav.socket.eunm.FactorType
+import org.springframework.beans.BeanUtils
 import org.springframework.web.context.ContextLoader
+import kotlin.math.min
 
 /**
  * 姹℃煋鏉ユ簮
@@ -20,7 +26,11 @@
      */
 
     // 婧簮浼佷笟
-    var sceneList:List<SceneInfo?>? = null
+    var sceneList:List<SceneInfoVo?>? = null
+
+    init {
+
+    }
 
     fun searchScenes(pollutedArea: PollutedArea, factor: FactorFilter.SelectedFactor) {
         ContextLoader.getCurrentWebApplicationContext()?.getBean(SceneInfoRep::class.java)?.run {
@@ -35,9 +45,10 @@
         // Fixme 2025.5.14: 姹℃煋婧愮殑鍧愭爣鏄珮寰峰湴鍥惧潗鏍囩郴锛堢伀鏄熷潗鏍囩郴锛夛紝鑰岃蛋鑸暟鎹槸WGS84鍧愭爣绯�
         // 鎸夌収鍖哄煙妫�绱㈠唴閮ㄦ薄鏌撴簮淇℃伅
         // 1. 棣栧厛鎸夌収鍥涜嚦鑼冨洿浠庢暟鎹簱鍒濇绛涢�夋薄鏌撴簮锛岄渶瑕佸厛灏嗗潗鏍囪浆鎹负gcj02锛堢伀鏄熷潗鏍囩郴锛夛紝鍥犱负姹℃煋婧愬満鏅俊鎭兘涓烘鍧愭爣绯�
-        val polygonTmp = pollutedArea.polygon!!.map {
-            MapUtil.gcj02ToWgs84(it)
-        }
+//        val polygonTmp = pollutedArea.polygon!!.map {
+//            MapUtil.gcj02ToWgs84(it)
+//        }
+        val polygonTmp = pollutedArea.polygon!!
         val fb = MapUtil.calFourBoundaries(polygonTmp)
         val sceneList = sceneInfoRep.findByCoordinateRange(fb)
         // 2. 鍐嶇簿纭垽鏂槸鍚﹀湪鍙嶅悜婧簮鍖哄煙澶氳竟褰㈠唴閮�
@@ -49,9 +60,57 @@
             }
         }
 
-        this.sceneList = result
+        findClosestStation(sceneInfoRep, result)
 
-        TODO("鎸夌収鎵�閫夌洃娴嬪洜瀛愮被鍨嬶紝鍖哄垎姹℃煋婧愮被鍨�")
 
+//        TODO("鎸夌収鎵�閫夌洃娴嬪洜瀛愮被鍨嬶紝鍖哄垎姹℃煋婧愮被鍨�")
+
+    }
+
+    /**
+     * 璁$畻鍙兘鐨勭浉鍏虫薄鏌撳満鏅被鍨�
+     */
+    private fun calFactorType(factor: FactorFilter.SelectedFactor) {
+//        when (factor.main) {
+//            FactorType.PM25 -> {}
+//
+//        }
+    }
+
+    /**
+     * 璁$畻鏈�杩戠殑鐩戞祴绔欑偣
+     */
+    private fun findClosestStation(sceneInfoRep: SceneInfoRep, sceneList: List<SceneInfo>) {
+        val res1 = sceneInfoRep.findByArea(AreaVo().apply {
+            sceneTypeId = SceneType.TYPE19.value.toString()
+        })
+
+        val res2 = sceneInfoRep.findByArea(AreaVo().apply {
+            sceneTypeId = SceneType.TYPE20.value.toString()
+        })
+        val res = res1.toMutableList().apply { addAll(res2) }
+
+        this.sceneList = sceneList.map {
+            var minLen = -1.0
+            var selectedRes: SceneInfo? = null
+            res.forEach { r->
+                val dis = MapUtil.getDistance(
+                    it.longitude.toDouble(),
+                    it.latitude.toDouble(),
+                    r!!.longitude.toDouble(),
+                    r.latitude.toDouble()
+                )
+                if (minLen < 0 || dis < minLen) {
+                    minLen = dis
+                    selectedRes = r
+                }
+            }
+            val vo = SceneInfoVo()
+            BeanUtils.copyProperties(it, vo)
+            vo.closestStation = selectedRes
+            vo.length = minLen
+
+            return@map vo
+        }
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
index 3070bcf..6ec9d46 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
@@ -1,16 +1,14 @@
 package com.flightfeather.uav.biz.sourcetrace.model
 
-import com.flightfeather.uav.biz.FactorFilter
-import com.flightfeather.uav.biz.dataanalysis.BaseExceptionAnalysis
-import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig
 import com.flightfeather.uav.biz.sourcetrace.config.RTExcWindLevelConfig
-import com.flightfeather.uav.biz.sourcetrace.exceptiontype.*
-import com.flightfeather.uav.common.utils.GsonUtils
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
-import com.flightfeather.uav.domain.repository.SceneInfoRep
-import com.flightfeather.uav.socket.eunm.FactorType
-import com.flightfeather.uav.socket.sender.UnderwayWebSocketSender
-import java.util.*
+import com.flightfeather.uav.domain.entity.SceneInfo
+import java.time.LocalDateTime
+import java.util.Timer
+import java.util.TimerTask
+
+// 寮傚父鏁版嵁鐢熸垚鍥炶皟绫�
+typealias NewPolluteSummaryCallback = (ex: PollutedSummary.AnalysisResult) -> Unit
 
 /**
  * 姹℃煋鎯呭喌姹囨��
@@ -18,7 +16,7 @@
  * @date 2025/5/27
  * @author feiyu02
  */
-class PollutedSummary {
+class PollutedSummary(private val config: RTExcWindLevelConfig, private val callback: NewPolluteSummaryCallback) {
 
 
     /**
@@ -26,75 +24,152 @@
      * 姣忎竴鍒婚挓瀵瑰巻鍙茬嚎绱㈣繘琛岀粺璁★紝鎻愬嚭浼氬晢寤鸿锛堢姹℃煋婧愯緝杩溿�佹薄鏌撴簮鏁伴噺銆佸嚭鐜版鏁帮級銆佽蛋鑸矾绾胯皟鏁村缓璁紙绂绘薄鏌撴簮杈冭繎銆佽蛋鑸建杩规湭鎺ヨ繎婧簮鍦烘櫙锛�
      */
 
-    constructor(sceneInfoRep: SceneInfoRep, factorFilter: FactorFilter?) {
-        this.sceneInfoRep = sceneInfoRep
-        this.config = if (factorFilter != null)
-            RTExcWindLevelConfig(factorFilter)
-        else
-            RTExcWindLevelConfig(
-                FactorFilter.builder()
-//                .withMain(FactorType.NO2)
-                    .withMain(FactorType.CO)
-//                .withMain(FactorType.H2S)
-//                .withMain(FactorType.SO2)
-//                .withMain(FactorType.O3)
-                    .withMain(FactorType.PM25)
-                    .withMain(FactorType.PM10)
-                    .withMain(FactorType.VOC)
-                    .create()
-            )
-        initTask()
+    /**
+     * 鍒嗘瀽缁撴灉
+     */
+    inner class AnalysisResult{
+        // 鎸夌収琚壂鎻忔鏁伴檷搴忔帓鍒楃殑姹℃煋婧愬垪琛�
+        var sortedSceneList: List<Pair<SceneInfo?, Int>>? = null
     }
 
-    constructor(sceneInfoRep: SceneInfoRep) : this(sceneInfoRep, null)
+    /**
+     * 瀹炴椂缁熻
+     */
+    inner class AnalysisStatistic {
+        // 鎸夌収琚壂鎻忔鏁伴檷搴忔帓鍒楃殑姹℃煋婧愬垪琛�
+        var sortedSceneList: List<Pair<SceneInfo?, Int>>? = null
+    }
 
-    // 姹℃煋绾跨储
-    var clueList = mutableListOf<PollutedClue>()
+    // 鏈�鏂板疄鏃惰蛋鑸洃娴嬫暟鎹�
+    val realTimeDataList = mutableListOf<BaseRealTimeData>()
 
-    private val sceneInfoRep: SceneInfoRep
+    // 鏈垎鏋愮殑姹℃煋绾跨储
+    val clueList = mutableListOf<PollutedClue>()
 
-    private val config: RTExcWindLevelConfig
+    // 宸插垎鏋愮殑姹℃煋绾跨储
+    private val historyClueList = mutableListOf<PollutedClue>()
 
-    private val taskList = mutableListOf<BaseExceptionAnalysis<RTExcWindLevelConfig, PollutedClue>>()
+    // 瀹氭椂姹℃煋鍒嗘瀽浠诲姟鎺у埗
+    private var analysisTimer: Timer? = null
 
-    fun initTask() {
-        taskList.clear()
-        taskList.apply {
-            add(RTExcWindLevel1(config) { exceptionCallback(it) }.also { it.init() })
-            add(RTExcWindLevel1_1(config) { exceptionCallback(it) }.also { it.init() })
-            add(RTExcWindLevel4(config) { exceptionCallback(it) }.also { it.init() })
-            add(RTExcWindLevel6(config) { exceptionCallback(it) }.also { it.init() })
+    // 瀹氭椂姹℃煋鍒嗘瀽浠诲姟
+    private val analysisOnTimeTask = object : TimerTask() {
+        override fun run() {
+            // 璁板綍浠诲姟杩愯鐘舵��
+            analysisTaskIsRunning = true
+            analysis()
+            // 璁板綍涓婁竴娆$殑浠诲姟缁撴潫鏃堕棿
+            lastAnalysisTime = LocalDateTime.now()
+            analysisTaskIsRunning = false
+        }
+    }
+
+    // 瀹氭椂姹℃煋鍒嗘瀽浠诲姟杩愯鐘舵��
+    private var analysisTaskIsRunning = false
+
+    // 涓婁竴娆″畾鏃舵薄鏌撳垎鏋愪换鍔$粨鏉熸椂闂�
+    private lateinit var lastAnalysisTime: LocalDateTime
+
+    init {
+        clear()
+    }
+
+    // 鏂板涓�鏉℃薄鏌撶嚎绱�
+    fun addClue(pollutedClue: PollutedClue) {
+        clueList.add(pollutedClue)
+//        realTimeSummary()
+        analysisOnClueCount()
+    }
+
+    // 鍒锋柊褰撳墠鏈�鏂扮殑璧拌埅鐩戞祴鏁版嵁
+    fun refreshLatestMonitorData(data: BaseRealTimeData) {
+//        realTimeDataList.clear()
+        realTimeDataList.add(data)
+    }
+
+    fun clear() {
+        realTimeDataList.clear()
+        clueList.clear()
+        historyClueList.clear()
+        analysisTimer?.cancel()
+        analysisTimer = null
+        analysisTaskIsRunning = false
+        lastAnalysisTime = LocalDateTime.now()
+        resetAnalysisOnTime()
+    }
+
+    /**
+     * 閲嶇疆瀹氭椂鍒嗘瀽绾跨储浠诲姟
+     */
+    private fun resetAnalysisOnTime() {
+        // 鍙栨秷鍘熸湁鐨勫垎鏋愪换鍔¤鏃�
+        analysisTimer?.cancel()
+        // 浠ュ綋鍓嶆椂闂翠负璧风偣锛岄噸鏂板紑濮嬫柊鐨勪竴杞瓑寰呰鏃�
+        analysisTimer = Timer()
+        val period = config.analysisPeriod * 60 * 1000L
+        analysisTimer?.schedule(analysisOnTimeTask, period, period)
+    }
+
+    /**
+     * 鍦ㄥ畾鏃舵薄鏌撶嚎绱㈠垎鏋愪换鍔$瓑寰呭懆鏈熸椂闂村唴锛岃嫢姹℃煋绾跨储閲忚秴杩囪瀹氬�硷紝鐩存帴瑙﹀彂鍒嗘瀽绾跨储浠诲姟
+     * 骞堕噸缃畾鏃跺垎鏋愪换鍔�
+     */
+    private fun analysisOnClueCount() {
+        if (clueList.size >= config.analysisCount && !analysisTaskIsRunning) {
+            analysisOnTimeTask.run()
+            resetAnalysisOnTime()
         }
     }
 
     /**
-     * 璁$畻鏂扮殑涓�鏉″疄鏃惰蛋鑸暟鎹�
+     * 瀹炴椂绾跨储缁熻
      */
-    fun addOneData(data: BaseRealTimeData) {
-        // 璁$畻寮傚父
-        taskList.forEach { it.onNextData(data) }
-        // 闄愬畾鏃堕棿鍐呮病鏈夋柊鏁版嵁浼犲叆锛屽垯缁撴潫褰撳墠鐨勮绠�
+    private fun realTimeSummary() {
+        val statistic = AnalysisStatistic()
+        // 鍏辨湁澶氬皯鐩稿叧姹℃煋婧愶紝鍝簺姹℃煋婧愯鎵弿娆℃暟杈冨
+        val sceneMap = mutableMapOf<String?, Pair<SceneInfo?, Int>>()
+        clueList.forEach {c->
+            c.pollutedSource?.sceneList?.forEach { s->
+                if (!sceneMap.containsKey(s?.guid)) {
+                    sceneMap[s?.guid] = s to 1
+                } else {
+                    sceneMap[s?.guid] = s to (sceneMap[s?.guid]?.second!! + 1)
+                }
+            }
+        }
+        val res = sceneMap.entries.sortedBy { it.value.second }
+        statistic.sortedSceneList = res.map { it.value }
     }
 
     /**
-     * 瓒呮椂澶勭悊锛岃緝闀挎椂闂存病鏈夋柊鏁版嵁杩涘叆锛岃繘琛屽垵濮嬪寲鎿嶄綔
+     * 绾跨储鍒嗘瀽
      */
-    private fun dealOnTimeout() {
-        val timer = Timer(true)
-        timer.schedule(object : TimerTask() {
-            override fun run() {
-                TODO("Not yet implemented")
+    private fun analysis() {
+        val result = AnalysisResult()
+        // 鍏辨湁澶氬皯鐩稿叧姹℃煋婧愶紝鍝簺姹℃煋婧愯鎵弿娆℃暟杈冨
+        val sceneMap = mutableMapOf<String?, Pair<SceneInfo?, Int>>()
+        clueList.forEach {c->
+            c.pollutedSource?.sceneList?.forEach { s->
+                if (!sceneMap.containsKey(s?.guid)) {
+                    sceneMap[s?.guid] = s to 1
+                } else {
+                    sceneMap[s?.guid] = s to (sceneMap[s?.guid]?.second!! + 1)
+                }
             }
-        }, 60 * 1000)
-        timer.cancel()
+        }
+        val res = sceneMap.entries.sortedBy { it.value.second }
+        result.sortedSceneList = res.map { it.value }
+
+        // 褰撳墠鐨勮蛋鑸暟鎹殑瀹氫綅鍜屾薄鏌撴簮璺濈鏄惁鏄�愭笎鎺ヨ繎锛岃嫢璧拌埅杩滅浜嗕富瑕佹薄鏌撴簮锛屾彁绀虹敤鎴疯皟鏁磋蛋鑸矾绾�
+
+
+        // 绾跨储鍒嗘瀽瀹屾垚鍚庯紝绉诲姩鑷冲巻鍙茬嚎绱㈠垪琛�
+        historyClueList.addAll(clueList)
+        clueList.clear()
+        realTimeDataList.clear()
+
+        callback(result)
+//        TODO()
     }
 
-    // 鏁版嵁绐佸彉寮傚父鍥炶皟
-    private fun exceptionCallback(ex: PollutedClue) {
-        // 婧簮姹℃煋婧愪俊鎭�
-        ex.searchScenes(sceneInfoRep)
-        clueList
-        // 骞挎挱姹℃煋婧簮寮傚父缁撴灉
-        UnderwayWebSocketSender.broadcast(GsonUtils.gson.toJson(ex))
-    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/SceneInfoVo.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/SceneInfoVo.kt
new file mode 100644
index 0000000..2353b04
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/SceneInfoVo.kt
@@ -0,0 +1,13 @@
+package com.flightfeather.uav.lightshare.bean
+
+import com.flightfeather.uav.domain.entity.SceneInfo
+
+class SceneInfoVo : SceneInfo() {
+
+    // 鏈�涓磋繎鐨勭洃娴嬬偣浣�
+    var closestStation: SceneInfo? = null
+
+    // 璺濈锛堝崟浣嶏細绫筹級锛�
+    var length: Double? = null
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt
new file mode 100644
index 0000000..594f4a7
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/SceneType.kt
@@ -0,0 +1,29 @@
+package com.flightfeather.uav.lightshare.eunm
+
+/**
+ * 鍦烘櫙绫诲瀷
+ * @date 2025/6/2
+ * @author feiyu02
+ */
+enum class SceneType(val value: Int, val des: String) {
+    TYPE1(1, "宸ュ湴"),
+    TYPE2(2, "鐮佸ご"),
+    TYPE3(3, "姘存偿鎼呮媽绔�"),
+    TYPE4(4, "宸ヤ笟浼佷笟"),
+    TYPE5(5, "椁愰ギ"),
+    TYPE6(6, "姹戒慨"),
+    TYPE7(7, "闄嶅皹鐐�"),
+    TYPE8(8, "绌烘皵璐ㄩ噺鐩戞祴鐐�"),
+    TYPE9(9, "閬撹矾鎵皹鐩戞祴鐐�"),
+    TYPE10(10, "閬撹矾"),
+    TYPE11(11, "娌虫祦鏂潰"),
+    TYPE12(12, "宸ヤ笟鍥尯"),
+    TYPE13(13, "鏃犲浐瀹氬満鏅�"),
+    TYPE14(14, "鍫嗗満"),
+    TYPE15(15, "瀹為獙瀹�"),
+    TYPE16(16, "绮惧搧灏忓尯"),
+    TYPE17(17, "鍔犳补绔�"),
+    TYPE18(18, "鍟嗕笟浣�"),
+    TYPE19(19, "鍥芥帶鐐�"),
+    TYPE20(20, "甯傛帶鐐�"),
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/decoder/UnderwayWebSocketParser.kt b/src/main/kotlin/com/flightfeather/uav/socket/decoder/UnderwayWebSocketParser.kt
new file mode 100644
index 0000000..46a2cc1
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/socket/decoder/UnderwayWebSocketParser.kt
@@ -0,0 +1,60 @@
+package com.flightfeather.uav.socket.decoder
+
+import com.flightfeather.uav.common.utils.GsonUtils
+import com.flightfeather.uav.socket.sender.WebSocketMessage
+import org.springframework.util.StringUtils
+
+object UnderwayWebSocketParser {
+
+    const val START_STR: String = "##"
+    const val SPLIT_STR: String = "&&"
+    const val END_STR: String = "%%"
+
+    /**
+     * 娑堟伅鏍煎紡鏍¢獙
+     * @param message 娑堟伅
+     * @return 鏍煎紡鏄惁鍚堣
+     */
+    private fun verificationMessage(message: String): Boolean {
+        if (message.isEmpty()) {
+            return false
+        }
+        if (!message.startsWith(START_STR)) {
+            return false
+        }
+        if (!message.endsWith(END_STR)) {
+            return false
+        }
+        return true
+    }
+
+    /**
+     * 瑙f瀽鍑虹被鍨嬪拰鍐呭
+     * @param message socket娑堟伅涓殑data瀛楁
+     * @return 瑙f瀽缁撴灉锛屽鏋滄牸寮忎笉姝g‘鍒欒繑鍥瀗ull
+     */
+    fun decodeMessage(message: String): WebSocketMessage {
+        if (!verificationMessage(message)) {
+            // 鍙戞尌涓�涓笉浼氳澶勭悊鐨勬秷鎭�
+            return WebSocketMessage(-1, "")
+        }
+        val webSocketMessage = WebSocketMessage()
+        val parts: Array<String> = message.substring(START_STR.length, message.length - END_STR.length)
+            .split(SPLIT_STR.toRegex())
+            .dropLastWhile { it.isEmpty() }.toTypedArray()
+        webSocketMessage.type = parts[0].toInt()
+        webSocketMessage.content = GsonUtils.gson.fromJson(parts[1], Any::class.java)
+
+        return webSocketMessage
+    }
+
+    /**
+     * 鐢熸垚鎸囧畾鏍煎紡鐨勬秷鎭瓧绗︿覆
+     * @return 鐢熸垚鐨勬秷鎭瓧绗︿覆
+     */
+    fun encodeMessage(webSocketMessage: WebSocketMessage): String {
+        return START_STR + webSocketMessage.type + SPLIT_STR +
+                GsonUtils.gson.toJson(webSocketMessage.content, webSocketMessage.content?.javaClass) +
+                END_STR
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt b/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt
index fef4d1a..23e7b70 100644
--- a/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt
+++ b/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt
@@ -1,16 +1,13 @@
 package com.flightfeather.uav.socket.handler
 
-import com.flightfeather.uav.biz.sourcetrace.RealTimeExceptionAnalysisController
-import com.flightfeather.uav.common.api2word.utils.JsonUtils
+import com.flightfeather.uav.biz.sourcetrace.SourceTraceController
 import com.flightfeather.uav.common.utils.GsonUtils
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import com.flightfeather.uav.domain.repository.SceneInfoRep
 import com.flightfeather.uav.lightshare.bean.DataVo
 import com.flightfeather.uav.socket.sender.UnderwayWebSocketSender
-import com.google.gson.JsonSyntaxException
 import io.netty.channel.ChannelHandlerContext
 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
-import org.springframework.stereotype.Component
 
 /**
  *
@@ -19,7 +16,7 @@
  */
 class UnderwayWebSocketServerHandler(sceneInfoRep: SceneInfoRep) : BaseHandler() {
 
-    private val realTimeExceptionAnalysisController = RealTimeExceptionAnalysisController(sceneInfoRep)
+    private val sourceTraceController = SourceTraceController(sceneInfoRep)
 
     override var tag: String = "UAV-WS"
 
@@ -41,11 +38,11 @@
                 // Test
                 try {
                     if (msgTxt == "start") {
-                        realTimeExceptionAnalysisController.initTask()
+                        sourceTraceController.initTask()
                     } else {
                         val data = GsonUtils.parserJsonToArrayBeans(msgTxt, DataVo::class.java)
                         data.forEach {
-                            realTimeExceptionAnalysisController.addOneData(
+                            sourceTraceController.addOneData(
                                 it.toBaseRealTimeData(BaseRealTimeData::class.java)
                             )
                         }
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt b/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt
index 6c5f374..7d8fd21 100644
--- a/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt
+++ b/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt
@@ -1,27 +1,19 @@
 package com.flightfeather.uav.socket.processor
 
-import com.flightfeather.uav.biz.FactorFilter
-import com.flightfeather.uav.biz.sourcetrace.RealTimeExceptionAnalysisController
-import com.flightfeather.uav.common.location.LocationRoadNearby
+import com.flightfeather.uav.biz.sourcetrace.SourceTraceController
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import com.flightfeather.uav.model.epw.EPWDataPrep
 import com.flightfeather.uav.domain.repository.AirDataRep
-import com.flightfeather.uav.domain.repository.RealTimeDataRep
 import com.flightfeather.uav.domain.repository.SceneInfoRep
-import com.flightfeather.uav.domain.repository.SegmentInfoRep
 import com.flightfeather.uav.socket.bean.AirDataPackage
 import com.flightfeather.uav.socket.decoder.AirDataDecoder
 import com.flightfeather.uav.socket.decoder.DataPackageDecoder
 import com.flightfeather.uav.socket.eunm.AirCommandUnit
-import com.flightfeather.uav.socket.eunm.FactorType
 import com.flightfeather.uav.socket.eunm.UWDeviceType
-import com.flightfeather.uav.socket.handler.UnderwayWebSocketServerHandler
 import io.netty.channel.ChannelHandlerContext
-import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Component
 import java.text.SimpleDateFormat
 import java.util.*
-import javax.annotation.PostConstruct
 
 /**
  * 澶勭悊socket鎺ユ敹鐨勬秷鎭�
@@ -46,7 +38,7 @@
     private val dataProcessMap = mutableMapOf<String?, EPWDataPrep>()
 
     // 瀹炴椂璧拌埅姹℃煋婧簮澶勭悊鍣�
-    private val realTimeExceptionAnalysisMap = mutableMapOf<String?, RealTimeExceptionAnalysisController>()
+    private val sourceTraceMap = mutableMapOf<String?, SourceTraceController>()
 
     override var tag: String = "璧拌埅鐩戞祴"
 
@@ -60,11 +52,11 @@
             saveToTxt(msg)
             saveToDataBase(packageData)?.takeIf { it.isNotEmpty() }?.get(0)?.let {
                 // 姣忓彴璁惧鏈夊悇鑷崟鐙殑寮傚父鏁版嵁澶勭悊鍣�
-                if (!realTimeExceptionAnalysisMap.containsKey(it.deviceCode)) {
-                    realTimeExceptionAnalysisMap[it.deviceCode] = RealTimeExceptionAnalysisController(sceneInfoRep)
+                if (!sourceTraceMap.containsKey(it.deviceCode)) {
+                    sourceTraceMap[it.deviceCode] = SourceTraceController(sceneInfoRep)
                 }
                 // 灏嗚蛋鑸暟鎹紶鍏ュ紓甯稿鐞嗗櫒
-                realTimeExceptionAnalysisMap[it.deviceCode]?.addOneData(it)
+                sourceTraceMap[it.deviceCode]?.addOneData(it)
             }
 
         } else {
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/sender/MsgType.kt b/src/main/kotlin/com/flightfeather/uav/socket/sender/MsgType.kt
new file mode 100644
index 0000000..be86205
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/socket/sender/MsgType.kt
@@ -0,0 +1,18 @@
+package com.flightfeather.uav.socket.sender
+
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedSummary
+
+enum class MsgType(val value: Int) {
+    /**
+     * 姹℃煋绾跨储
+     * @see [PollutedClue]
+     */
+    PolClue(1),
+
+    /**
+     * 姹℃煋鍒嗘瀽缁撴灉
+     * @see [PollutedSummary.AnalysisResult]
+     */
+    AnaResult(2),
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt b/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt
index 2a765fe..06fa873 100644
--- a/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt
+++ b/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.socket.sender
 
+import com.flightfeather.uav.socket.decoder.UnderwayWebSocketParser
 import io.netty.channel.ChannelHandlerContext
 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame
 
@@ -28,6 +29,11 @@
 
     }
 
+    fun broadcast(type:Int, content:Any) {
+        val msg = UnderwayWebSocketParser.encodeMessage(WebSocketMessage(type,content))
+        broadcast(msg)
+    }
+
     fun broadcast(msg: String) {
         sessionPool.forEach { (t, u) ->
             u?.channel()?.writeAndFlush(TextWebSocketFrame(msg))
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/sender/WebSocketMessage.kt b/src/main/kotlin/com/flightfeather/uav/socket/sender/WebSocketMessage.kt
new file mode 100644
index 0000000..3b810da
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/socket/sender/WebSocketMessage.kt
@@ -0,0 +1,21 @@
+package com.flightfeather.uav.socket.sender
+
+class WebSocketMessage {
+
+    /**
+     * 娑堟伅绫诲瀷
+     */
+    var type: Int = 0
+
+    /**
+     * 娑堟伅鍐呭
+     */
+    var content: Any? = null
+
+    constructor()
+
+    constructor(type: Int, content: Any?) {
+        this.type = type
+        this.content = content
+    }
+}
diff --git a/src/test/kotlin/com/flightfeather/uav/biz/dataprocess/DataProcessTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/dataprocess/DataProcessTest.kt
index 7b51ffb..0a77946 100644
--- a/src/test/kotlin/com/flightfeather/uav/biz/dataprocess/DataProcessTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/biz/dataprocess/DataProcessTest.kt
@@ -1,12 +1,15 @@
 package com.flightfeather.uav.biz.dataprocess
 
 import com.flightfeather.uav.domain.mapper.RealTimeDataMapper
+import com.flightfeather.uav.domain.repository.SceneInfoRep
+import com.flightfeather.uav.lightshare.bean.AreaVo
 import com.flightfeather.uav.lightshare.service.RealTimeDataService
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.test.context.junit4.SpringRunner
+import org.springframework.web.context.ContextLoader
 import java.time.LocalDateTime
 import java.time.format.DateTimeFormatter
 import java.util.*
@@ -56,4 +59,12 @@
         process.outPutDailyVariation()
         process.done()
     }
+
+    @Test
+    fun foo2() {
+        ContextLoader.getCurrentWebApplicationContext()?.getBean(SceneInfoRep::class.java)?.run {
+            val res =  this.findByArea(AreaVo().apply { sceneTypeId = "20" })
+            res.forEach { println(it?.name) }
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSourceTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSourceTest.kt
new file mode 100644
index 0000000..f6ceaa0
--- /dev/null
+++ b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSourceTest.kt
@@ -0,0 +1,33 @@
+package com.flightfeather.uav.biz.sourcetrace.model
+
+import com.flightfeather.uav.biz.FactorFilter
+import com.flightfeather.uav.domain.repository.SceneInfoRep
+import com.flightfeather.uav.socket.eunm.FactorType
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit4.SpringRunner
+
+@RunWith(SpringRunner::class)
+@SpringBootTest
+class PollutedSourceTest {
+
+ @Autowired
+ lateinit var sceneInfoRep: SceneInfoRep
+
+ @Test
+ fun foo1() {
+  val source = PollutedSource()
+  val pollutedArea = PollutedArea().apply {
+   polygon = listOf(
+    121.421521 to 31.195457,
+    121.421721 to 31.195457,
+    121.421521 to 31.195257,
+    121.421721 to 31.195257,
+   )
+  }
+  source.searchScenes(pollutedArea, sceneInfoRep, FactorFilter.SelectedFactor(FactorType.VOC))
+
+ }
+}
\ No newline at end of file

--
Gitblit v1.9.3