2025.7.29
1. 动态溯源模块添加记录删除等debug功能
| | |
| | | * 每一刻钟对历史线索进行统计,提出会商建议(离污染源较远、污染源数量、出现次数)、走航路线调整建议(离污染源较近、走航轨迹未接近溯源场景) |
| | | */ |
| | | |
| | | 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) { |
| | |
| | | .withMain(FactorType.O3) |
| | | .withMain(FactorType.PM25) |
| | | .withMain(FactorType.PM10) |
| | | // .withMain(FactorType.VOC) |
| | | .withMain(FactorType.VOC) |
| | | .withCombination( |
| | | listOf( |
| | | listOf(FactorType.PM25, FactorType.PM10), |
| | |
| | | .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 |
| | |
| | | val countLimit: Int, |
| | | ){ |
| | | } |
| | | |
| | | // 是否联网查找对应路段地址信息 |
| | | var isSearchAddress = true |
| | | // 限定距离内(单位:米) |
| | | var distanceLimit = 3000 |
| | | // 限定时间内(单位:分钟) |
| | |
| | | ) |
| | | |
| | | /****数据快速上升*****************************************************************************/ |
| | | // 监测因子在一个监测周期(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, |
| | |
| | | 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, |
| | |
| | | 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, |
| | |
| | | ) |
| | | |
| | | /****数据快速下降提醒*****************************************************************************/ |
| | | // 监测因子在一个监测周期(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, |
| | |
| | | |
| | | /****数据有上升趋势提醒*****************************************************************************/ |
| | | 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 |
| | | ), |
| | | ) |
| | | } |
| | |
| | | MapUtil.wgs84ToGcj02(it) |
| | | } |
| | | |
| | | closePolygon = closeSourceTrace(historyData, pair) |
| | | closePolygon = closeSourceTrace(historyData, pair).map { |
| | | // 将坐标转换为gcj02(火星坐标系),因为污染源场景信息都为此坐标系 |
| | | MapUtil.wgs84ToGcj02(it) |
| | | } |
| | | |
| | | try { |
| | | val address = AMapService.reGeo(pair) |
| | | this.address = address.district + address.township + address.street |
| | | Thread.sleep(100) |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | if (config.isSearchAddress) { |
| | | try { |
| | | val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(pair)) |
| | | this.address = address.district + address.township + address.street |
| | | // Thread.sleep(100) |
| | | } catch (e: Exception) { |
| | | e.printStackTrace() |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | // 建议的走航路线 |
| | | result.direction = AMapService.directionDriving(origin, destination) |
| | | Thread.sleep(200) |
| | | // Thread.sleep(200) |
| | | } |
| | | // 线索分析完成后,移动至历史线索列表 |
| | | historyClueList.addAll(clueList) |
| | |
| | | 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 |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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) |
| | | }) |
| | | } |
| | | } |
| | |
| | | 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 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) |
| | | 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, |
| | | 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.addOneData(rtdVehicle) |
| | | } |
| | | sourceTraceController.initTask() |
| | | } |
| | | 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 |
| | |
| | | |
| | | } |
| | | |
| | | @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) |
| | | } |
| | | } |
| | | } |
| | | |
| | | } |