feiyu02
2025-07-29 2e024c986c14943a41f7bfe913cfef0cede64198
2025.7.29
1. 动态溯源模块添加记录删除等debug功能
已修改6个文件
120 ■■■■ 文件已修改
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
@@ -28,7 +28,12 @@
     * 每一刻钟对历史线索进行统计,提出会商建议(离污染源较远、污染源数量、出现次数)、走航路线调整建议(离污染源较近、走航轨迹未接近溯源场景)
     */
    constructor(sceneInfoRep: SceneInfoRep, sourceTraceRep: SourceTraceRep, factorFilter: FactorFilter?) {
    constructor(
        sceneInfoRep: SceneInfoRep,
        sourceTraceRep: SourceTraceRep,
        factorFilter: FactorFilter?,
        isSearchAddress: Boolean,
    ) {
        this.sceneInfoRep = sceneInfoRep
        this.sourceTraceRep = sourceTraceRep
        this.config = if (factorFilter != null) {
@@ -43,7 +48,7 @@
                    .withMain(FactorType.O3)
                    .withMain(FactorType.PM25)
                    .withMain(FactorType.PM10)
//                    .withMain(FactorType.VOC)
                    .withMain(FactorType.VOC)
                    .withCombination(
                        listOf(
                            listOf(FactorType.PM25, FactorType.PM10),
@@ -53,11 +58,14 @@
                    .create()
            )
        }
        this.config.isSearchAddress = isSearchAddress
        pollutedSummary = PollutedSummary(config) { summaryCallback(it) }
        newTask()
    }
    constructor(sceneInfoRep: SceneInfoRep, sourceTraceRep: SourceTraceRep) : this(sceneInfoRep, sourceTraceRep, null)
    constructor(sceneInfoRep: SceneInfoRep, sourceTraceRep: SourceTraceRep, isSearchAddress: Boolean = true)
            : this(sceneInfoRep, sourceTraceRep, null, isSearchAddress)
    private val pollutedSummary: PollutedSummary
    private val sceneInfoRep: SceneInfoRep
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/config/RTExcWindLevelConfig.kt
@@ -19,7 +19,8 @@
        val countLimit: Int,
    ){
}
    // 是否联网查找对应路段地址信息
    var isSearchAddress = true
    // 限定距离内(单位:米)
    var distanceLimit = 3000
    // 限定时间内(单位:分钟)
@@ -66,20 +67,25 @@
    )
    /****数据快速上升*****************************************************************************/
    // 监测因子在一个监测周期(4秒)内正常变化的量级范围
    // 在风速处于0 - 1.5 m/s 之间时
    var changeRateUp1 = mutableMapOf(
        // PM2.5在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生2次
        FactorType.PM25 to WindLevelCondition(
            .0 to 1.5,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE1,
            3
//            fixme: 2025.7.24 因为低风速下数据变化次数设置过多,导致遗漏识别
//            3
            2
        ),
        // PM10在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生2次
        FactorType.PM10 to WindLevelCondition(
            .0 to 1.5,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE1,
            3
            2
        ),
        // VOC在一个监测周期(4秒)上升量级大于等于6μg/m³,连续发生1次
        FactorType.VOC to WindLevelCondition(
            .0 to 1.5,
            6.0 to Double.MAX_VALUE,
@@ -87,19 +93,23 @@
            1
        ),
    )
    // 在风速处于1.6 - 7.9 m/s 之间时
    var changeRateUp2 = mutableMapOf(
        // PM2.5在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生3次
        FactorType.PM25 to WindLevelCondition(
            1.6 to 7.9,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE3,
            3
        ),
        // PM10在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生3次
        FactorType.PM10 to WindLevelCondition(
            1.6 to 7.9,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE3,
            3
        ),
        // VOC在一个监测周期(4秒)上升量级大于等于6μg/m³,连续发生1次
        FactorType.VOC to WindLevelCondition(
            1.6 to 7.9,
            6.0 to Double.MAX_VALUE,
@@ -107,19 +117,23 @@
            1
        ),
    )
    // 在风速处于8.0 - 13.8 m/s 之间时
    var changeRateUp3 = mutableMapOf(
        // PM2.5在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生3次
        FactorType.PM25 to WindLevelCondition(
            8.0 to 13.8,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE4,
            3
        ),
        // PM10在一个监测周期(4秒)上升量级大于等于4μg/m³,连续发生3次
        FactorType.PM10 to WindLevelCondition(
            8.0 to 13.8,
            4.0 to Double.MAX_VALUE,
            DistanceType.TYPE4,
            3
        ),
        // VOC在一个监测周期(4秒)上升量级大于等于6μg/m³,连续发生1次
        FactorType.VOC to WindLevelCondition(
            8.0 to 13.8,
            6.0 to Double.MAX_VALUE,
@@ -129,20 +143,22 @@
    )
    /****数据快速下降提醒*****************************************************************************/
    // 监测因子在一个监测周期(4秒)内正常变化的量级范围
    var changeRateWarnDown = mutableMapOf(
        // PM2.5在一个监测周期(4秒)内下降量级大于等于2μg/m³,连续发生3次
        FactorType.PM25 to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            -Double.MAX_VALUE to -2.0,
            DistanceType.TYPE1,
            3
        ),
        // PM10在一个监测周期(4秒)内下降量级大于等于2μg/m³,连续发生3次
        FactorType.PM10 to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            -Double.MAX_VALUE to -2.0,
            DistanceType.TYPE1,
            3
        ),
        // VOC在一个监测周期(4秒)内下降量级大于等于3μg/m³,连续发生3次
        FactorType.VOC to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            -Double.MAX_VALUE to -3.0,
@@ -153,23 +169,26 @@
    /****数据有上升趋势提醒*****************************************************************************/
    var changeRateWarnUp = mutableMapOf(
        // PM2.5在一个监测周期(4秒)上升量级在2 - 4μg/m³之间,连续发生3次
        FactorType.PM25 to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            2.0 to 4.0,
            DistanceType.TYPE1,
            3
        ),
        // PM10在一个监测周期(4秒)上升量级在2 - 4μg/m³之间,连续发生3次
        FactorType.PM10 to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            2.0 to 4.0,
            DistanceType.TYPE1,
            3
        ),
        // VOC在一个监测周期(4秒)上升量级在3 - 6μg/m³之间,连续发生2次
        FactorType.VOC to WindLevelCondition(
            .0 to Double.MAX_VALUE,
            3.0 to 6.0,
            DistanceType.TYPE1,
            1
            2
        ),
    )
}
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedArea.kt
@@ -72,15 +72,20 @@
            MapUtil.wgs84ToGcj02(it)
        }
        closePolygon = closeSourceTrace(historyData, pair)
        closePolygon = closeSourceTrace(historyData, pair).map {
            // 将坐标转换为gcj02(火星坐标系),因为污染源场景信息都为此坐标系
            MapUtil.wgs84ToGcj02(it)
        }
        if (config.isSearchAddress) {
        try {
            val address = AMapService.reGeo(pair)
                val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(pair))
            this.address = address.district + address.township + address.street
            Thread.sleep(100)
//                Thread.sleep(100)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        }
    }
src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/PollutedSummary.kt
@@ -182,7 +182,7 @@
                // 建议的走航路线
                result.direction = AMapService.directionDriving(origin, destination)
                Thread.sleep(200)
//                Thread.sleep(200)
            }
            // 线索分析完成后,移动至历史线索列表
            historyClueList.addAll(clueList)
src/main/kotlin/com/flightfeather/uav/domain/repository/SourceTraceRep.kt
@@ -6,6 +6,7 @@
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.Mission
import com.flightfeather.uav.domain.entity.SourceTraceMsg
import com.flightfeather.uav.domain.mapper.SourceTraceMsgMapper
import com.flightfeather.uav.socket.sender.MsgType
@@ -103,4 +104,12 @@
            }
        }
    }
    fun delete(mission: Mission): Int {
        return sourceTraceMsgMapper.deleteByExample(Example(SourceTraceMsg::class.java).apply {
            createCriteria().andEqualTo("deviceCode", mission.deviceCode)
                .andGreaterThanOrEqualTo("startTime", mission.startTime)
                .andLessThanOrEqualTo("endTime", mission.endTime)
        })
    }
}
src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
@@ -29,17 +29,18 @@
    lateinit var missionMapper: MissionMapper
    @Autowired
    lateinit var missionRep: MissionRep
    @Autowired
    lateinit var realTimeDataService: RealTimeDataService
    @Test
    fun autoSourceTrace() {
        val sourceTraceController = SourceTraceController(sceneInfoRep, sourceTraceRep)
        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
            createCriteria().andEqualTo("deviceType", "0a")
                .andLessThanOrEqualTo("startTime", "2024-11-07 15:00:00")
            orderBy("startTime").desc()
        })
        missions.forEach { m ->
        val sourceTraceController = SourceTraceController(sceneInfoRep, sourceTraceRep, false)
        val mCode = listOf("SH-CN-20241227", "SH-CN-20241127", "SH-CN-20240906", "SH-CN-20240830(05)",
            "SH-CN-20240830(04)", "SH-CN-20240823", "SH-CN-20240723(02)", "SH-CN-20250723(01)")
        mCode.forEach { c->
            missionRep.findOne(c)?.let {m ->
            val rtData = realTimeDataService.getSecondData(
                m?.deviceType,
                m?.deviceCode,
@@ -56,11 +57,34 @@
            }
            sourceTraceController.initTask()
        }
        }
//        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
//            createCriteria().andEqualTo("deviceType", "0a")
//                .andLessThanOrEqualTo("startTime", "2024-11-07 15:00:00")
//            orderBy("startTime").desc()
//        })
//        missions.forEach { m ->
//            val rtData = realTimeDataService.getSecondData(
//                m?.deviceType,
//                m?.deviceCode,
//                DateUtil.instance.dateToString(m?.startTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
//                DateUtil.instance.dateToString(m?.endTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
//                null,
//                1,
//                10000
//            )
//            rtData.data?.forEach { d ->
//                val rtdVehicle = d.toBaseRealTimeData(RealTimeDataVehicle::class.java)
////            Thread.sleep(500)
//                sourceTraceController.addOneData(rtdVehicle)
//            }
//            sourceTraceController.initTask()
//        }
//        val rtData = realTimeDataService.getSecondData(
//            "0a",
//            "0a0000000001",
//            "2025-01-06 13:32:00",
//            "2025-01-06 15:52:36",
//            "2024-08-23 12:30:23",
//            "2024-08-23 15:12:56",
//            null,
//            1,
//            10000
@@ -73,4 +97,15 @@
    }
    @Test
    fun deleteSourceTrace() {
        val mCode = listOf("SH-CN-20241227", "SH-CN-20241127", "SH-CN-20240906", "SH-CN-20240830(05)",
            "SH-CN-20240830(04)", "SH-CN-20240823", "SH-CN-20240723(02)", "SH-CN-20250723(01)")
        mCode.forEach {c ->
            missionRep.findOne(c)?.let {
                sourceTraceRep.delete(it)
            }
        }
    }
}