From f1ea263462d1f3f10a886fb083536a38b03a1ceb Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期三, 14 五月 2025 17:33:04 +0800 Subject: [PATCH] 1. 新增动态污染溯源的数据异常判断逻辑 2. 新增动态污染溯源websocket连接功能 --- src/main/kotlin/com/flightfeather/uav/socket/handler/BaseHandler.kt | 9 src/main/kotlin/com/flightfeather/uav/UAVApplication.kt | 2 src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt | 11 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRealTimeException.kt | 73 +++++ src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt | 36 ++ src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt | 133 ++++++++ src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt | 5 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeExceptionAnalysisController.kt | 162 +++++++++-- src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt | 30 - src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt | 33 +- src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt | 9 src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt | 120 +++++--- /dev/null | 43 --- src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeAnalysisConfig.kt | 13 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt | 5 src/main/kotlin/com/flightfeather/uav/domain/entity/SceneInfo.java | 6 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RealTimeExceptionResult.kt | 18 + src/main/kotlin/com/flightfeather/uav/domain/repository/impl/AirDataRepImpl.kt | 41 -- src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ExceptionStatusType.kt | 11 src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt | 53 ++- 20 files changed, 561 insertions(+), 252 deletions(-) diff --git a/src/main/kotlin/com/flightfeather/uav/UAVApplication.kt b/src/main/kotlin/com/flightfeather/uav/UAVApplication.kt index c660050..d94f3f2 100644 --- a/src/main/kotlin/com/flightfeather/uav/UAVApplication.kt +++ b/src/main/kotlin/com/flightfeather/uav/UAVApplication.kt @@ -23,7 +23,7 @@ @Bean fun runner() = ApplicationRunner{ - underwaySocketServer.startWebSocketServer(9031, underwayProcessor) + underwaySocketServer.startWebSocketServer(9031) underwaySocketServer.startUnderwayServer(9030, underwayProcessor) underwaySocketServer.startElectricServer(9009, electricProcessor) } diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt index 52f9cac..0c2e28a 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuous.kt @@ -105,21 +105,23 @@ } // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇 if (!isContinue || needCut(it)) { - checkResult(s) // 鏁版嵁涓嶈繛缁椂锛岃褰曞紓甯告儏鍐� - if (it.eIndex - it.sIndex >= durationCount) { - it.refreshAfterCheckResult(data) - } + recordException(s, it, data) +// checkResult(s) +// if (it.eIndex - it.sIndex >= durationCount) { +// it.refreshAfterCheckResult(data) +// } } else { if (hasException[f] == true) { it.existException = true it.exceptionData.add(data) } else { // 寮傚父涓嶅啀閲嶅鍑虹幇鏃讹紝璁板綍寮傚父鎯呭喌 - checkResult(s) - if (it.eIndex - it.sIndex >= durationCount) { - it.refreshAfterCheckResult(data) - } + recordException(s, it, data) +// checkResult(s) +// if (it.eIndex - it.sIndex >= durationCount) { +// it.refreshAfterCheckResult(data) +// } } } } @@ -131,6 +133,13 @@ checkResult() } + fun recordException(factor: FactorFilter.SelectedFactor, tag: Tag, data: BaseRealTimeData) { + checkResult(factor) + if (tag.eIndex - tag.sIndex >= durationCount) { + tag.refreshAfterCheckResult(data) + } + } + /** * 妫�鏌ヨ繛缁紓甯哥粨鏉熸椂锛屾槸鍚︾鍚堝紓甯稿瓨鍌ㄦ潯浠� */ @@ -139,20 +148,12 @@ if (factor != null && tag != null) { if (tag.existException && judgeExceptionCount(tag)) { onNewException(tag, factor) -// tag.startData?.let { -// resultList.add(newResult(it, lastData, factor, tag.exceptionData)) -// } -// tag.existException = false } } else { config.factorFilter.selectedList.forEach { f -> val tag1 = tagMap[f.main] ?: return@forEach if (tag1.existException && judgeExceptionCount(tag1)) { onNewException(tag1, f) -// tag1.startData?.let { -// resultList.add(newResult(it, lastData, f, tag1.exceptionData)) -// } -// tag1.existException = false } } } diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeAnalysisConfig.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeAnalysisConfig.kt index 6f8a4af..bd28bbb 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeAnalysisConfig.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeAnalysisConfig.kt @@ -25,6 +25,15 @@ // 绐佸彉鐜� var mutationRate = .2 - // 婧簮鏈夋晥鏈�澶ч閫燂紝5鍒嗛挓涓嶈秴杩�2鍏噷鐨勯閫燂紙鏆傚畾锛� - var sourceTraceWindSpeedLimit = 6.7 + // 婧簮鏈夋晥鏈�澶ф椂闂达紙鍗曚綅锛氬垎閽�) + var sourceTraceTimeLimit = 5 + + // 婧簮鏈夋晥鏈�澶ц窛绂伙紙鍗曚綅锛氱背锛� + var sourceTraceDistanceLimit = 2000 + + // 婧簮鏈夋晥鏈�澶ч閫燂紙鍗曚綅锛氱背/绉掞級锛�5鍒嗛挓涓嶈秴杩�2鍏噷鐨勯閫燂紙鏆傚畾锛� + var sourceTraceWindSpeedLimit = 6.667 + + // 婧簮鎵╂暎鍋忕Щ瑙掑害锛堝崟浣嶏細搴︼級 + var sourceTraceDegOffset = 30.0 } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeExceptionAnalysisController.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeExceptionAnalysisController.kt index 4bd356a..9fb9090 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeExceptionAnalysisController.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/RealTimeExceptionAnalysisController.kt @@ -4,68 +4,170 @@ import com.flightfeather.uav.biz.dataanalysis.BaseExceptionAnalysis import com.flightfeather.uav.biz.sourcetrace.exceptiontype.RealTimeExceptionValueMutation import com.flightfeather.uav.biz.sourcetrace.model.RealTimeExceptionResult -import com.flightfeather.uav.common.api2word.utils.JsonUtils -import com.flightfeather.uav.common.location.LocationRoadNearby import com.flightfeather.uav.common.utils.GsonUtils +import com.flightfeather.uav.common.utils.MapUtil import com.flightfeather.uav.domain.entity.BaseRealTimeData +import com.flightfeather.uav.domain.entity.SceneInfo import com.flightfeather.uav.domain.entity.avg -import com.flightfeather.uav.domain.repository.RealTimeDataRep -import com.flightfeather.uav.domain.repository.SegmentInfoRep +import com.flightfeather.uav.domain.repository.SceneInfoRep +import com.flightfeather.uav.socket.eunm.FactorType import com.flightfeather.uav.socket.handler.UnderwayWebSocketServerHandler -import com.google.gson.Gson +import com.flightfeather.uav.socket.sender.UnderwayWebSocketSender +import java.util.Timer +import java.util.TimerTask +import kotlin.math.PI /** * 瀹炴椂璧拌埅姹℃煋婧簮 * @date 2025/5/8 * @author feiyu02 */ -class RealTimeExceptionAnalysisController ( - private val realTimeDataRep: RealTimeDataRep, - private val locationRoadNearby: LocationRoadNearby, - private val segmentInfoRep: SegmentInfoRep, - private val underwayWebSocketServerHandler: UnderwayWebSocketServerHandler, - factorFilter: FactorFilter -){ - private var config:RealTimeAnalysisConfig = RealTimeAnalysisConfig(factorFilter) + +class RealTimeExceptionAnalysisController { + + constructor(sceneInfoRep: SceneInfoRep, factorFilter: FactorFilter?) { + this.sceneInfoRep = sceneInfoRep + this.config = if (factorFilter != null) + RealTimeAnalysisConfig(factorFilter) + else + RealTimeAnalysisConfig( + 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(config) + } + + constructor(sceneInfoRep: SceneInfoRep) : this(sceneInfoRep, null) + + + private val sceneInfoRep: SceneInfoRep + + private val config: RealTimeAnalysisConfig private val taskList = mutableListOf<BaseExceptionAnalysis<RealTimeAnalysisConfig, RealTimeExceptionResult>>() private fun initTask(config: RealTimeAnalysisConfig) { taskList.clear() taskList.apply { - add(RealTimeExceptionValueMutation(config){ exceptionCallback(it)}) + add( + RealTimeExceptionValueMutation(config) { exceptionCallback(it) }.also { it.init() } + ) } + } - init { - initTask(config) - } - - // 璁$畻鍘嗗彶浠诲姟 + /** + * 璁$畻鏂扮殑涓�鏉″疄鏃惰蛋鑸暟鎹� + */ fun addOneData(data: BaseRealTimeData) { - taskList - + // 璁$畻寮傚父 + taskList.forEach { it.onNextData(data) } + // 闄愬畾鏃堕棿鍐呮病鏈夋柊鏁版嵁浼犲叆锛屽垯缁撴潫褰撳墠鐨勮绠� } + /** + * 瓒呮椂澶勭悊锛屾湁涓ょ瓒呮椂鎯呭喌 + * 1. 杈冪煭鏃堕棿鍐咃紝涓诲姩缁撴潫杩炵画褰撳墠寮傚父鍒ゆ柇 + * 2. 杈冮暱鏃堕棿鍐咃紝杩涜鍒濆鍖栨搷浣� + */ + 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: RealTimeExceptionResult) { - if (sourceTrace(ex, config)) { - underwayWebSocketServerHandler.broadcast(GsonUtils.gson.toJson(ex)) - } + // 婧簮姹℃煋婧愪俊鎭� + sourceTrace(ex, config) + // 骞挎挱姹℃煋婧簮寮傚父缁撴灉 + UnderwayWebSocketSender.broadcast(GsonUtils.gson.toJson(ex)) } - private fun sourceTrace(ex: RealTimeExceptionResult, config: RealTimeAnalysisConfig):Boolean { + /** + * 姹℃煋鍙嶅悜婧簮 + */ + private fun sourceTrace(ex: RealTimeExceptionResult, config: RealTimeAnalysisConfig) { + // 璁$畻寮傚父鏁版嵁鍧囧�� val avgData = ex.dataList.avg() if (avgData.windSpeed!! > config.sourceTraceWindSpeedLimit) { - return false + return } // 鍙栦腑闂寸偣浣滀负鍙嶅悜婧簮鐨勮捣鐐� val midData = ex.dataList[ex.dataList.size / 2] -// avgData.longitude -// avgData.latitude -// avgData.windDirection - return false + // 璁$畻鍙嶅悜婧簮鍖哄煙 + val polygon = calSector( + avgData.windSpeed!!.toDouble(), + avgData.windDirection!!.toDouble(), + midData.longitude!!.toDouble() to midData.latitude!!.toDouble(), + config.sourceTraceTimeLimit, + config.sourceTraceDegOffset + ) + + // 鎸夌収鍖哄煙妫�绱㈠唴閮ㄦ薄鏌撴簮淇℃伅 + + // 1. 棣栧厛鎸夌収鍥涜嚦鑼冨洿浠庢暟鎹簱鍒濇绛涢�夋薄鏌撴簮 + val fb = MapUtil.calFourBoundaries(polygon) + val sceneList = sceneInfoRep.findByCoordinateRange(fb) + // 2. 鍐嶇簿纭垽鏂槸鍚﹀湪鍙嶅悜婧簮鍖哄煙澶氳竟褰㈠唴閮� + val result = mutableListOf<SceneInfo>() + sceneList.forEach { + // Fixme 2025.5.14: 姹℃煋婧愮殑鍧愭爣鏄珮寰峰湴鍥惧潗鏍囩郴锛堢伀鏄熷潗鏍囩郴锛夛紝鑰岃蛋鑸暟鎹槸WGS84鍧愭爣绯� + val point = MapUtil.gcj02ToWgs84(it!!.longitude.toDouble() to it.latitude.toDouble()) + if (MapUtil.isPointInPolygon(point, polygon)) { + result.add(it) + } + } + + // 鏇存柊涓棿鐐逛俊鎭� + ex.midData = avgData.apply { + longitude = midData.longitude + latitude = midData.latitude + } + // 鏇存柊婧簮鑼冨洿鍐呯殑姹℃煋鍦烘櫙淇℃伅 + ex.relatedSceneList = result + } + + /** + * 鏍规嵁涓績鐐瑰潗鏍囥�侀鍚戝拰椋庨�燂紝浠ュ強缁欏畾鐨勫す瑙掞紝璁$畻浠ヤ腑蹇冪偣鎸夌収椋庡悜椋庨�熷拰鏃堕暱锛屽悜澶栨墿鏁e舰鎴愮殑鎵囧舰鐨勭偣鍧愭爣 + * @param windSpeed 椋庨�燂紝鍗曚綅锛氱背/绉� + * @param windDir 椋庡悜锛屽崟浣嶏細搴� + * @param center 涓績鐐瑰潗鏍囩粡绾害 + * @param durationMin 鏃堕暱锛屽崟浣嶏細鍒嗛挓 + * @param defaultDegOffset 鎵╂暎鍋忕Щ瑙掑害 + * @return 澶氳竟褰㈤《鐐瑰潗鏍囬泦鍚� + */ + private fun calSector( + windSpeed: Double, windDir: Double, center: Pair<Double, Double>, durationMin: Int, + defaultDegOffset: Double = 30.0, + ): List<Pair<Double, Double>> { + + val sDeg = windDir - defaultDegOffset + val eDeg = windDir + defaultDegOffset + val distance = windSpeed * durationMin * 60 + + // 宸︿晶锛堥�嗘椂閽堜晶锛夐《鐐� + val p1 = MapUtil.getPointByLen(center, distance, sDeg * PI / 180) + // 椋庡悜鍙嶅悜椤剁偣 + val p2 = MapUtil.getPointByLen(center, distance, windDir * PI / 180) + // 鍙充晶锛堥『鏃堕拡渚э級椤剁偣 + val p3 = MapUtil.getPointByLen(center, distance, eDeg * PI / 180) + + return listOf(center, p1, p2, p3) } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRealTimeException.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRealTimeException.kt new file mode 100644 index 0000000..c464995 --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/BaseRealTimeException.kt @@ -0,0 +1,73 @@ +package com.flightfeather.uav.biz.sourcetrace.exceptiontype + +import com.flightfeather.uav.biz.FactorFilter +import com.flightfeather.uav.biz.dataanalysis.BaseExceptionContinuous +import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig +import com.flightfeather.uav.biz.sourcetrace.model.RealTimeExceptionResult +import com.flightfeather.uav.domain.entity.BaseRealTimeData + +// 寮傚父鏁版嵁鐢熸垚鍥炶皟绫� +typealias NewExceptionCallback = (ex: RealTimeExceptionResult) -> Unit +/** + * 璧拌埅鍔ㄦ�佹函婧愬紓甯稿垽鏂� + * 鐩告瘮浜庡叾鐖剁被锛屼慨鏀逛簡寮傚父鍒嗙粍鐨勯�昏緫锛屼笉鍐嶈�冭檻寮傚父闇�瑕佽繛缁嚭鐜帮紝鑰屾槸鍙�氳繃鏁版嵁閲囨牱鏃堕棿鏄惁杩炵画浠ュ強鏄惁闇�瑕佷富鍔ㄦ埅鍙栧垎缁勬潵鍐冲畾 + * 鍙﹀鏂板浜嗗紓甯稿疄鏃舵挱鎶ョ殑閫昏緫 + * @date 2025/5/13 + * @author feiyu02 + */ +abstract class BaseRealTimeException(config: RealTimeAnalysisConfig) : + BaseExceptionContinuous<RealTimeAnalysisConfig, RealTimeExceptionResult>(config) { + + constructor(config: RealTimeAnalysisConfig, callback: NewExceptionCallback) : this(config){ + this.callback = callback + } + + var callback: NewExceptionCallback? = null + + override fun onNextData(data: BaseRealTimeData) { + val isContinue = isContinuous(lastData, data) + val hasException = judgeException(lastData, data) + config.factorFilter.selectedList.forEach { s -> + val f = s.main + tagMap[f]?.let { + it.eIndex++ + // 璧峰鏁版嵁 + it.endData = data + if (it.startData == null) { + it.refreshAfterCheckResult(data) + } + // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画鎴栬�呮槸鍚︽弧瓒宠嚜瀹氫箟鎴彇鏉′欢 + if (!isContinue || needCut(it)) { + // 璁板綍寮傚父锛岀粨鏉熷紓甯哥殑瀹炴椂鐘舵�佹挱鎶� + recordException(s, it, data) + } else { + if (hasException[f] == true) { + it.existException = true + it.exceptionData.add(data) + } + // 绉婚櫎浜嗙埗绫诲師鏈夐�昏緫锛屾敼涓哄綋婊¤冻寮傚父鏉′欢鏃讹紝闇�瑕佸疄鏃舵帹閫佹挱鎶ュ紓甯哥殑鐘舵�佸彉鍖栵紝浣嗕笉鎴彇寮傚父 + checkResult(s) + } + } + } + lastData = data + } + + override fun newResult( + start: BaseRealTimeData, + end: BaseRealTimeData?, + factor: FactorFilter.SelectedFactor, + exceptionData: List<BaseRealTimeData>, + ): RealTimeExceptionResult { + val eType = getExceptionType() + return RealTimeExceptionResult(start, end, factor, exceptionData, eType) + } + + override fun onNewException(tag: Tag, factor: FactorFilter.SelectedFactor) { + super.onNewException(tag, factor) + callback?.let { func -> + val exc = resultList.last() + func.invoke(exc) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionContinuous.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionContinuous.kt deleted file mode 100644 index ce7c9b4..0000000 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionContinuous.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.flightfeather.uav.biz.sourcetrace.exceptiontype - -import com.flightfeather.uav.biz.FactorFilter -import com.flightfeather.uav.biz.dataanalysis.BaseExceptionContinuous -import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult -import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig -import com.flightfeather.uav.biz.sourcetrace.model.RealTimeExceptionResult -import com.flightfeather.uav.domain.entity.BaseRealTimeData - -// 寮傚父鏁版嵁鐢熸垚鍥炶皟绫� -typealias NewExceptionCallback = (ex: RealTimeExceptionResult) -> Unit -/** - * - * @date 2025/5/13 - * @author feiyu02 - */ -abstract class RealTimeExceptionContinuous(config: RealTimeAnalysisConfig) : - BaseExceptionContinuous<RealTimeAnalysisConfig, RealTimeExceptionResult>(config) { - - constructor(config: RealTimeAnalysisConfig, callback: NewExceptionCallback) : this(config){ - this.callback = callback - } - - var callback: NewExceptionCallback? = null - - override fun newResult( - start: BaseRealTimeData, - end: BaseRealTimeData?, - factor: FactorFilter.SelectedFactor, - exceptionData: List<BaseRealTimeData>, - ): RealTimeExceptionResult { - val eType = getExceptionType() - return RealTimeExceptionResult(start, end, factor, exceptionData, eType) - } - - override fun onNewException(tag: Tag, factor: FactorFilter.SelectedFactor) { - super.onNewException(tag, factor) - callback?.let { func -> - val exc = resultList.last() - func.invoke(exc) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt index b87f479..f5eb79f 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/exceptiontype/RealTimeExceptionValueMutation.kt @@ -1,6 +1,5 @@ package com.flightfeather.uav.biz.sourcetrace.exceptiontype -import com.flightfeather.uav.biz.FactorFilter import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType import com.flightfeather.uav.biz.sourcetrace.RealTimeAnalysisConfig import com.flightfeather.uav.common.utils.MapUtil @@ -15,7 +14,7 @@ * @date 2025/5/13 * @author feiyu02 */ -class RealTimeExceptionValueMutation : RealTimeExceptionContinuous { +class RealTimeExceptionValueMutation : BaseRealTimeException { constructor(config: RealTimeAnalysisConfig) : super(config) @@ -53,7 +52,7 @@ } override fun judgeExceptionCount(tag: Tag): Boolean { - // 棣栦釜鏁版嵁娌℃湁鍓嶄竴涓暟鎹弬鐓э紝涓嶇畻寮傚父鍊硷紝鏈�鍚庝竴涓暟鎹槸鍒ゆ柇缁撴潫鐨勬甯稿�硷紝鍥犳寮傚父鏁版嵁涓暟鐨勮绠椾笅鏍囦负sIndex鍜宔Index + // 棣栦釜鏁版嵁娌℃湁鍓嶄竴涓暟鎹弬鐓э紝涓嶇畻寮傚父鍊硷紝鏈�鍚庝竴涓暟鎹槸鍒ゆ柇缁撴潫鐨勬甯稿�硷紝鍥犳寮傚父鏁版嵁涓暟鐨勮绠椾笅鏍囦负sIndex鍜宔Index - 1 val sIndex = tag.sIndex val eIndex = tag.eIndex - 1 diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RealTimeExceptionResult.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RealTimeExceptionResult.kt index 86ef036..8f5d0eb 100644 --- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RealTimeExceptionResult.kt +++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/model/RealTimeExceptionResult.kt @@ -7,6 +7,8 @@ import com.flightfeather.uav.domain.entity.BaseRealTimeData import com.flightfeather.uav.domain.entity.SceneInfo import com.flightfeather.uav.domain.entity.avg +import com.flightfeather.uav.lightshare.bean.DataVo +import com.flightfeather.uav.lightshare.eunm.ExceptionStatusType import com.flightfeather.uav.socket.eunm.FactorType import java.math.BigDecimal @@ -16,6 +18,11 @@ * @author feiyu02 */ class RealTimeExceptionResult() : BaseExceptionResult() { + + // 寮傚父缂栧彿 + var guid: String? = null + // 寮傚父鐨勭姸鎬� + var status:Int = ExceptionStatusType.InProgress.value var deviceCode: String? = null @@ -39,10 +46,16 @@ // 寮傚父鏁版嵁锛屽ご灏惧彲鑳藉寘鍚竴瀹氶噺鐨勫亸绉� var dataList: MutableList<BaseRealTimeData> = mutableListOf() + var dataVoList: MutableList<DataVo> = mutableListOf() // 涓績鐐圭粡绾害 var longitude: BigDecimal? = null var latitude: BigDecimal? = null + + // 涓棿鏁版嵁鐐瑰潗鏍� + var midData: BaseRealTimeData? = null +// var midLongitude: BigDecimal? = null +// var midLatitude: BigDecimal? = null // 婧簮浼佷笟 var relatedSceneList: List<SceneInfo?>? = null @@ -77,7 +90,10 @@ min = s.second max = s.third - exceptionData.forEach { dataList.add(it) } + exceptionData.forEach { + dataList.add(it) + dataVoList.add(it.toDataVo()) + } } private fun dataSummary( diff --git a/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt b/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt index cdcfcb9..5ae24c7 100644 --- a/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt +++ b/src/main/kotlin/com/flightfeather/uav/common/utils/MapUtil.kt @@ -1,14 +1,15 @@ package com.flightfeather.uav.common.utils -import kotlin.math.PI -import kotlin.math.asin -import kotlin.math.cos -import kotlin.math.sin +import kotlin.math.* object MapUtil { private const val Ea = 6378137 //璧ら亾鍗婂緞 private const val Eb = 6356725 //鏋佸崐寰� + + // 鍧愭爣杞崲鍙傛暟 + const val a = 6378245.0; //闀垮崐杞� + const val ee = 0.00669342162296594323; //鎵佺巼/*** GCJ02 杞崲涓� WGS84* @param lng* @param lat* @returns {*[]}*/ /** * 鏍规嵁鍧愭爣鐐广�佽窛绂诲拰瑙掑害锛岃幏鍙栧彟涓�涓潗鏍� @@ -93,6 +94,24 @@ } /** + * 璁$畻澶氳竟褰㈢殑鍥涜嚦鑼冨洿 + * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 + * @return 鍥涜嚦鑼冨洿锛岄『搴忎负鏈�灏忕粡搴︼紝鏈�澶х粡搴�, 鏈�灏忕含搴︼紝鏈�澶х含搴� + */ + fun calFourBoundaries(polygon: List<Pair<Double, Double>>): List<Double> { + // 璁$畻澶氳竟褰㈤《鐐圭粡搴﹁寖鍥村拰绾害鑼冨洿 + val xsSort = polygon.map { it.first }.sorted() + val ysSort = polygon.map { it.second }.sorted() + + val xMin = xsSort[0] + val yMin = ysSort[0] + val xMax = xsSort[xsSort.lastIndex] + val yMax = ysSort[ysSort.lastIndex] + + return listOf(xMin, xMax, yMin, yMax) + } + + /** * 鍒ゆ柇鍧愭爣鐐规槸鍚﹀湪澶氳竟褰㈢殑鍥涜嚦鑼冨洿鍐� * @param point 鍧愭爣鐐� * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 @@ -102,13 +121,19 @@ val x = point.first val y = point.second // 璁$畻澶氳竟褰㈤《鐐圭粡搴﹁寖鍥村拰绾害鑼冨洿 - val xsSort = polygon.map { it.first }.sorted() - val ysSort = polygon.map { it.second }.sorted() + val fb = calFourBoundaries(polygon) +// val xsSort = polygon.map { it.first }.sorted() +// val ysSort = polygon.map { it.second }.sorted() +// +// val xMin = xsSort[0] +// val yMin = ysSort[0] +// val xMax = xsSort[xsSort.lastIndex] +// val yMax = ysSort[ysSort.lastIndex] - val xMin = xsSort[0] - val yMin = ysSort[0] - val xMax = xsSort[xsSort.lastIndex] - val yMax = ysSort[ysSort.lastIndex] + val xMin = fb[0] + val xMax = fb[1] + val yMin = fb[2] + val yMax = fb[3] return x >= xMin && x <= xMax && y >= yMin && y <= yMax } @@ -146,7 +171,7 @@ * @param point 鍧愭爣鐐� * @param polygon 澶氳竟褰㈠潗鏍囩偣鏁扮粍 */ - fun inPolygon(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>):Boolean { + fun inPolygon(point: Pair<Double, Double>, polygon: List<Pair<Double, Double>>): Boolean { val x = point.first val y = point.second var j = polygon.size - 1 @@ -177,4 +202,90 @@ // 璁$畻鏄惁鍦ㄥ杈瑰舰鍐呴儴 return inPolygon(point, polygon) } + + /** + * 鍒ゆ柇缁忕含搴︽槸鍚﹀湪鍥藉唴 + * @return true: 缁忕含搴︿笉鍦ㄥ浗鍐咃紝false锛氱粡绾害鍦ㄥ浗鍐� + */ + fun outOfChina(point: Pair<Double, Double>): Boolean { + val lng = point.first + val lat = point.second + return !(lng > 73.66 && lng < 135.05 && lat > 3.86 && lat < 53.55) + } + + private fun transformLat(point: Pair<Double, Double>): Double { + val lng = point.first + val lat = point.second + var ret = -100.0 + + 2.0 * lng + + 3.0 * lat + + 0.2 * lat * lat + + 0.1 * lng * lat + + 0.2 * sqrt(abs(lng)) + ret += ((20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0) / 3.0 + ret += ((20.0 * sin(lat * PI) + 40.0 * sin((lat / 3.0) * PI)) * 2.0) / 3.0 + ret += ((160.0 * sin((lat / 12.0) * PI) + 320 * sin((lat * PI) / 30.0)) * 2.0) / 3.0 + return ret; + } + + private fun transformLng(point: Pair<Double, Double>): Double { + val lng = point.first + val lat = point.second + var ret = 300.0 + + lng + + 2.0 * lat + + 0.1 * lng * lng + + 0.1 * lng * lat + + 0.1 * sqrt(abs(lng)); + ret += ((20.0 * sin(6.0 * lng * PI) + 20.0 * sin(2.0 * lng * PI)) * 2.0) / 3.0; + ret += ((20.0 * sin(lng * PI) + 40.0 * sin((lng / 3.0) * PI)) * 2.0) / 3.0; + ret += ((150.0 * sin((lng / 12.0) * PI) + 300.0 * sin((lng / 30.0) * PI)) * 2.0) / 3.0 + return ret; + } + + /** + * 鐏槦鍧愭爣绯昏浆WGS84鍧愭爣绯� + */ + fun gcj02ToWgs84(point: Pair<Double, Double>): Pair<Double, Double> { + if (outOfChina(point)) { + return point; + } else { + val lng = point.first + val lat = point.second + var dlat = transformLat(lng - 105.0 to lat - 35.0); + var dlng = transformLng(lng - 105.0 to lat - 35.0); + val radlat = (lat / 180.0) * PI; + var magic = sin(radlat); + magic = 1 - ee * magic * magic; + val sqrtmagic = sqrt(magic); + dlat = (dlat * 180.0) / (((a * (1 - ee)) / (magic * sqrtmagic)) * PI); + dlng = (dlng * 180.0) / ((a / sqrtmagic) * cos(radlat) * PI); + val mglat = Math.round((lat * 2 - lat - dlat) * 1000000) / 1000000; + val mglng = Math.round((lng * 2 - lng - dlng) * 1000000) / 1000000; + return mglng.toDouble() to mglat.toDouble() + } + } + + /** + * WGS84鍧愭爣绯昏浆鐏槦鍧愭爣绯� + */ + fun wgs84ToGcj02(point: Pair<Double, Double>): Pair<Double, Double> { + if (outOfChina(point)) { + return point + } else { + val lng = point.first + val lat = point.second + var dLat = transformLat(lng - 105.0 to lat - 35.0); + var dLon = transformLng(lng - 105.0 to lat - 35.0); + val radLat = (lat / 180.0) * PI; + var magic = sin(radLat); + magic = 1 - ee * magic * magic; + val sqrtMagic = sqrt(magic); + dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * PI); + dLon = (dLon * 180.0) / ((a / sqrtMagic) * cos(radLat) * PI); + val mgLat = lat + dLat; + val mgLon = lng + dLon; + return mgLon to mgLat + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/SceneInfo.java b/src/main/kotlin/com/flightfeather/uav/domain/entity/SceneInfo.java index 716dede..4b3ee4c 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/entity/SceneInfo.java +++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/SceneInfo.java @@ -28,9 +28,15 @@ @Column(name = "Location") private String location; + /** + * 缁忓害锛岄珮寰峰湴鍥惧潗鏍囩郴 + */ @Column(name = "Longitude") private BigDecimal longitude; + /** + * 绾害锛岄珮寰峰湴鍥惧潗鏍囩郴 + */ @Column(name = "Latitude") private BigDecimal latitude; diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/impl/AirDataRepImpl.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/impl/AirDataRepImpl.kt index 5008d5b..2931e5b 100644 --- a/src/main/kotlin/com/flightfeather/uav/domain/repository/impl/AirDataRepImpl.kt +++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/impl/AirDataRepImpl.kt @@ -132,8 +132,7 @@ dataList.forEach {vo -> when (UWDeviceType.getType(vo.deviceCode)) { UWDeviceType.VEHICLE -> { - val d = RealTimeDataVehicle() - dataTransform(vo, d) + val d = vo.toBaseRealTimeData(RealTimeDataVehicle::class.java) /***************************************************************************************************/ // FIXME: 2021/10/27 杞﹁浇鐩戞祴閮ㄥ垎鍥犲瓙閲忕骇璋冩暣 calibration(d, UWDeviceType.VEHICLE) @@ -142,8 +141,7 @@ res.add(d) } UWDeviceType.UAV -> { - val d = RealTimeDataUav() - dataTransform(vo, d) + val d = vo.toBaseRealTimeData(RealTimeDataUav::class.java) /***************************************************************************************************/ // FIXME: 2021/10/25 鏃犱汉鏈洪儴鍒嗗洜瀛愰噰鐢ㄨ溅杞芥暟鎹~鍏咃紝鍙栨渶鏂扮殑15鍒嗛挓鐨勬暟鎹� if (tmpVehicleDataList.isEmpty()) { @@ -167,8 +165,7 @@ res.add(d) } UWDeviceType.GRID -> { - val d = RealTimeDataGrid() - dataTransform(vo, d) + val d = vo.toBaseRealTimeData(RealTimeDataGrid::class.java) /**************************************************************************/ // FIXME: 2021/11/8 閽堝鍘嗗彶缃戞牸鍖栧師濮嬫暟鎹紝杩涜涓存椂鏍″噯澶勭悊 // val dTime = LocalDateTime.ofInstant(d.dataTime?.toInstant(), ZoneId.systemDefault()) @@ -267,38 +264,6 @@ } } } - } - } - - fun dataTransform(vo: DataVo, bean: BaseRealTimeData) { - bean.apply { - deviceCode = vo.deviceCode - latitude = vo.lat?.toBigDecimal() - longitude = vo.lng?.toBigDecimal() - dataTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(vo.time) - createTime = Date() - vo.values?.forEach { - when (it.factorId?.toInt()) { - FactorType.NO2.value -> no2 = it.factorData?.toFloat() - FactorType.CO.value -> co = it.factorData?.toFloat() - FactorType.H2S.value -> h2s = it.factorData?.toFloat() - FactorType.SO2.value -> so2 = it.factorData?.toFloat() - FactorType.O3.value -> o3 = it.factorData?.toFloat() - - FactorType.PM25.value -> pm25 = it.factorData?.toFloat() - FactorType.PM10.value -> pm10 = it.factorData?.toFloat() - FactorType.TEMPERATURE.value -> temperature = it.factorData?.toFloat() - FactorType.HUMIDITY.value -> humidity = it.factorData?.toFloat() - FactorType.VOC.value -> voc = it.factorData?.toFloat() - - FactorType.NOI.value -> noi = it.factorData?.toFloat() - FactorType.VELOCITY.value -> velocity = it.factorData?.toFloat() - FactorType.WIND_SPEED.value -> windSpeed = it.factorData?.toFloat() - FactorType.WIND_DIRECTION.value -> windDirection = it.factorData?.toFloat() - FactorType.HEIGHT.value -> height = it.factorData?.toFloat() - } - } - } } diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt index ab8b068..b548bc7 100644 --- a/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/bean/DataVo.kt @@ -1,9 +1,12 @@ package com.flightfeather.uav.lightshare.bean import com.fasterxml.jackson.annotation.JsonInclude +import com.flightfeather.uav.domain.entity.BaseRealTimeData import com.flightfeather.uav.model.BaseMData import com.flightfeather.uav.socket.bean.AirData import com.flightfeather.uav.socket.eunm.FactorType +import java.text.SimpleDateFormat +import java.util.Date /** * @author riku @@ -11,55 +14,86 @@ */ @JsonInclude(JsonInclude.Include.NON_NULL) data class DataVo( - //鏃堕棿, yyyy-MM-dd HH:mm:ss - var time: String? = null, - //绔欑偣缂栧彿 - var deviceCode: String? = null, - //鏁版嵁鍊� - var values: List<AirData>? = null, - //缁忓害 - var lng: Double? = null, - //绾害 - var lat: Double? = null + //鏃堕棿, yyyy-MM-dd HH:mm:ss + var time: String? = null, + //绔欑偣缂栧彿 + var deviceCode: String? = null, + //鏁版嵁鍊� + var values: List<AirData>? = null, + //缁忓害 + var lng: Double? = null, + //绾害 + var lat: Double? = null, ) : BaseMData() { - override fun getFactorData(type: FactorType): Double? { - if (values == null) throw IllegalStateException(this.javaClass.name + ": 鐩戞祴鏁版嵁鏁扮粍涓簄ull") - for (d in values!!) { - if (d.factorName == type.name) { - return d.factorData - } - } - return null + override fun getFactorData(type: FactorType): Double? { + if (values == null) throw IllegalStateException(this.javaClass.name + ": 鐩戞祴鏁版嵁鏁扮粍涓簄ull") + for (d in values!!) { + if (d.factorName == type.name) { + return d.factorData + } } + return null + } - fun toRowContent(): Array<Any> { - val row = mutableListOf<Any>() - row.add(deviceCode ?: "") - row.add(time ?: "") - row.add(lng ?: -1.0) - row.add(lat ?: -1.0) - values?.forEach { - if (FactorType.outputFactor(it.factorName)) { - row.add(it.factorData ?: -1.0) + fun toRowContent(): Array<Any> { + val row = mutableListOf<Any>() + row.add(deviceCode ?: "") + row.add(time ?: "") + row.add(lng ?: -1.0) + row.add(lat ?: -1.0) + values?.forEach { + if (FactorType.outputFactor(it.factorName)) { + row.add(it.factorData ?: -1.0) // row.add(it.physicalQuantity ?: -1.0) - } - } - return row.toTypedArray() + } } + return row.toTypedArray() + } - fun toRowTitle(): Array<String> { - val list = mutableListOf<String>() - list.add("缂栧彿") - list.add("閲囨牱鏃堕棿") - list.add("缁忓害") - list.add("绾害") - values?.forEach { - if (FactorType.outputFactor(it.factorName)) { - val name = it.factorName ?: "" - list.add(name) + fun toRowTitle(): Array<String> { + val list = mutableListOf<String>() + list.add("缂栧彿") + list.add("閲囨牱鏃堕棿") + list.add("缁忓害") + list.add("绾害") + values?.forEach { + if (FactorType.outputFactor(it.factorName)) { + val name = it.factorName ?: "" + list.add(name) // list.add("$name(鐗╃悊閲�)") - } - } - return list.toTypedArray() + } } + return list.toTypedArray() + } + + fun <T : BaseRealTimeData> toBaseRealTimeData(clz:Class<T>): T { + return clz.newInstance().apply { + deviceCode = this@DataVo.deviceCode + latitude = this@DataVo.lat?.toBigDecimal() + longitude = this@DataVo.lng?.toBigDecimal() + dataTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(this@DataVo.time) + createTime = Date() + this@DataVo.values?.forEach { + when (it.factorId?.toInt()) { + FactorType.NO2.value -> no2 = it.factorData?.toFloat() + FactorType.CO.value -> co = it.factorData?.toFloat() + FactorType.H2S.value -> h2s = it.factorData?.toFloat() + FactorType.SO2.value -> so2 = it.factorData?.toFloat() + FactorType.O3.value -> o3 = it.factorData?.toFloat() + + FactorType.PM25.value -> pm25 = it.factorData?.toFloat() + FactorType.PM10.value -> pm10 = it.factorData?.toFloat() + FactorType.TEMPERATURE.value -> temperature = it.factorData?.toFloat() + FactorType.HUMIDITY.value -> humidity = it.factorData?.toFloat() + FactorType.VOC.value -> voc = it.factorData?.toFloat() + + FactorType.NOI.value -> noi = it.factorData?.toFloat() + FactorType.VELOCITY.value -> velocity = it.factorData?.toFloat() + FactorType.WIND_SPEED.value -> windSpeed = it.factorData?.toFloat() + FactorType.WIND_DIRECTION.value -> windDirection = it.factorData?.toFloat() + FactorType.HEIGHT.value -> height = it.factorData?.toFloat() + } + } + } + } } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ExceptionStatusType.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ExceptionStatusType.kt new file mode 100644 index 0000000..d83afaa --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ExceptionStatusType.kt @@ -0,0 +1,11 @@ +package com.flightfeather.uav.lightshare.eunm + +/** + * 寮傚父鐘舵�� + * @date 2025/5/14 + * @author feiyu02 + */ +enum class ExceptionStatusType(val value: Int, val des: String) { + InProgress(1, "鎸佺画涓�"), + Ended(2, "宸茬粨鏉�"), +} \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt b/src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt index 1abff63..09adc8b 100644 --- a/src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt +++ b/src/main/kotlin/com/flightfeather/uav/socket/UnderwaySocketServer.kt @@ -1,5 +1,6 @@ package com.flightfeather.uav.socket +import com.flightfeather.uav.domain.repository.SceneInfoRep import com.flightfeather.uav.socket.handler.ServerHandler import com.flightfeather.uav.socket.handler.UnderwayWebSocketServerHandler import com.flightfeather.uav.socket.processor.BaseProcessor @@ -25,7 +26,7 @@ * *******************************************************************************/ @Component class UnderwaySocketServer( - private val underwayWebSocketServerHandler:UnderwayWebSocketServerHandler + private val sceneInfoRep: SceneInfoRep ) { private val bossGroup = NioEventLoopGroup() @@ -39,8 +40,8 @@ electricServer(processor)?.bind(port)?.sync() } - fun startWebSocketServer(port: Int, processor: BaseProcessor) { - webSocketServer(processor)?.bind(port)?.sync() + fun startWebSocketServer(port: Int) { + webSocketServer()?.bind(port)?.sync() } fun stopServer() { @@ -92,13 +93,13 @@ /** * 澶氬弬鏁拌蛋鑸湇鍔$ */ - private fun webSocketServer(processor: BaseProcessor):ServerBootstrap? = newServer(object : ChannelInitializer<NioSocketChannel>() { + private fun webSocketServer():ServerBootstrap? = newServer(object : ChannelInitializer<NioSocketChannel>() { override fun initChannel(p0: NioSocketChannel?) { p0?.pipeline() ?.addLast(HttpServerCodec()) ?.addLast(HttpObjectAggregator(65535)) ?.addLast(WebSocketServerProtocolHandler("/ws")) - ?.addLast(underwayWebSocketServerHandler) + ?.addLast(UnderwayWebSocketServerHandler(sceneInfoRep)) } }) } \ No newline at end of file diff --git a/src/main/kotlin/com/flightfeather/uav/socket/handler/BaseHandler.kt b/src/main/kotlin/com/flightfeather/uav/socket/handler/BaseHandler.kt index 90808a1..42634b7 100644 --- a/src/main/kotlin/com/flightfeather/uav/socket/handler/BaseHandler.kt +++ b/src/main/kotlin/com/flightfeather/uav/socket/handler/BaseHandler.kt @@ -15,12 +15,10 @@ abstract var tag: String override fun channelRegistered(ctx: ChannelHandlerContext?) { - super.channelRegistered(ctx) println("------銆�${tag}銆慖P杩炴帴锛歔ip:${ctx?.channel()?.remoteAddress()}] ${ SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( Date() )}") -// ctx?.fireChannelActive() } override fun channelActive(ctx: ChannelHandlerContext?) { @@ -28,19 +26,13 @@ SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( Date() )}") - super.channelActive(ctx) } override fun channelRead(ctx: ChannelHandlerContext?, msg: Any?) { - super.channelRead(ctx, msg) println("------銆�${tag}銆戞敹鍒扮殑鍘熷鏁版嵁锛歔ip:${ctx?.channel()?.remoteAddress()}] ${ SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( Date() )}") - } - - override fun channelReadComplete(ctx: ChannelHandlerContext?) { - super.channelReadComplete(ctx) } override fun channelInactive(ctx: ChannelHandlerContext?) { @@ -48,7 +40,6 @@ SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format( Date() )}") - super.channelInactive(ctx) } @Deprecated("Deprecated in Java") 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 0e912d3..3c5b0fa 100644 --- a/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt +++ b/src/main/kotlin/com/flightfeather/uav/socket/handler/UnderwayWebSocketServerHandler.kt @@ -1,5 +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.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 @@ -9,28 +17,39 @@ * @date 2025/5/13 * @author feiyu02 */ -@Component -class UnderwayWebSocketServerHandler : BaseHandler() { +class UnderwayWebSocketServerHandler(sceneInfoRep: SceneInfoRep) : BaseHandler() { - private val sessionPool = mutableMapOf<String?, ChannelHandlerContext?>() + private val realTimeExceptionAnalysisController = RealTimeExceptionAnalysisController(sceneInfoRep) override var tag: String = "UAV-WS" override fun channelRegistered(ctx: ChannelHandlerContext?) { super.channelRegistered(ctx) // 灏嗚繛鎺ュ瓨鍌� - if (!sessionPool.containsKey(ctx?.name())) { - sessionPool[ctx?.name()] = ctx - } + UnderwayWebSocketSender.saveSession(ctx) } override fun channelRead(ctx: ChannelHandlerContext?, msg: Any?) { super.channelRead(ctx, msg) - when (msg) { - is TextWebSocketFrame->{ - println(msg.text()) - ctx?.channel()?.writeAndFlush(msg) + is TextWebSocketFrame -> { + val msgTxt = msg.text() + + println(msgTxt) +// ctx?.channel()?.writeAndFlush(msg) + + // Test + try { + val data = GsonUtils.parserJsonToArrayBeans(msgTxt, DataVo::class.java) + data.forEach { + realTimeExceptionAnalysisController.addOneData( + it.toBaseRealTimeData(BaseRealTimeData::class.java) + ) + } + } catch (e: Exception) { +// ctx?.channel()?.writeAndFlush(TextWebSocketFrame("褰撳墠涓烘祴璇曠姸鎬侊紝浼犺緭鐨勬暟鎹笉鏄蛋鑸暟鎹牸寮�")) + println("褰撳墠涓烘祴璇曠姸鎬侊紝浼犺緭鐨勬暟鎹笉鏄蛋鑸暟鎹牸寮�") + } } } } @@ -38,18 +57,6 @@ override fun channelInactive(ctx: ChannelHandlerContext?) { super.channelInactive(ctx) // 灏嗚繛鎺ョЩ闄� - if (sessionPool.containsKey(ctx?.name())) { - sessionPool.remove(ctx?.name()) - } - } - - fun send() { - - } - - fun broadcast(msg: String) { - sessionPool.forEach { t, u -> - u?.channel()?.writeAndFlush(TextWebSocketFrame(msg)) - } + UnderwayWebSocketSender.removeSession(ctx) } } \ No newline at end of file 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 a649598..6c5f374 100644 --- a/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt +++ b/src/main/kotlin/com/flightfeather/uav/socket/processor/UnderwayProcessor.kt @@ -7,6 +7,7 @@ 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 @@ -31,10 +32,7 @@ @Component class UnderwayProcessor( private val airDataRep: AirDataRep, - private val realTimeDataRep: RealTimeDataRep, - private val locationRoadNearby: LocationRoadNearby, - private val segmentInfoRep: SegmentInfoRep, - private val underwayWebSocketServerHandler: UnderwayWebSocketServerHandler, + private val sceneInfoRep: SceneInfoRep, ) : BaseProcessor() { companion object { @@ -48,23 +46,7 @@ private val dataProcessMap = mutableMapOf<String?, EPWDataPrep>() // 瀹炴椂璧拌埅姹℃煋婧簮澶勭悊鍣� - private val realTimeExceptionAnalysisController = - RealTimeExceptionAnalysisController( - realTimeDataRep, - locationRoadNearby, - segmentInfoRep, - underwayWebSocketServerHandler, - 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() - ) + private val realTimeExceptionAnalysisMap = mutableMapOf<String?, RealTimeExceptionAnalysisController>() override var tag: String = "璧拌埅鐩戞祴" @@ -77,8 +59,12 @@ deviceSession.saveDevice(packageData.deviceCode, ctx) saveToTxt(msg) saveToDataBase(packageData)?.takeIf { it.isNotEmpty() }?.get(0)?.let { + // 姣忓彴璁惧鏈夊悇鑷崟鐙殑寮傚父鏁版嵁澶勭悊鍣� + if (!realTimeExceptionAnalysisMap.containsKey(it.deviceCode)) { + realTimeExceptionAnalysisMap[it.deviceCode] = RealTimeExceptionAnalysisController(sceneInfoRep) + } // 灏嗚蛋鑸暟鎹紶鍏ュ紓甯稿鐞嗗櫒 - realTimeExceptionAnalysisController.addOneData(it) + realTimeExceptionAnalysisMap[it.deviceCode]?.addOneData(it) } } else { diff --git a/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt b/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt new file mode 100644 index 0000000..2a765fe --- /dev/null +++ b/src/main/kotlin/com/flightfeather/uav/socket/sender/UnderwayWebSocketSender.kt @@ -0,0 +1,36 @@ +package com.flightfeather.uav.socket.sender + +import io.netty.channel.ChannelHandlerContext +import io.netty.handler.codec.http.websocketx.TextWebSocketFrame + +/** + * + * @date 2025/5/14 + * @author feiyu02 + */ +object UnderwayWebSocketSender { + + private val sessionPool = mutableMapOf<String?, ChannelHandlerContext?>() + + fun saveSession(ctx: ChannelHandlerContext?) { + if (!sessionPool.containsKey(ctx?.name())) { + sessionPool[ctx?.name()] = ctx + } + } + + fun removeSession(ctx: ChannelHandlerContext?) { + if (sessionPool.containsKey(ctx?.name())) { + sessionPool.remove(ctx?.name()) + } + } + + fun send() { + + } + + fun broadcast(msg: String) { + sessionPool.forEach { (t, u) -> + u?.channel()?.writeAndFlush(TextWebSocketFrame(msg)) + } + } +} \ No newline at end of file diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt index 1d70ec0..2865f6c 100644 --- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt +++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt @@ -23,8 +23,6 @@ @Autowired lateinit var realTimeDataVehicleMapper: RealTimeDataVehicleMapper - @Autowired - lateinit var airDataRepository: AirDataRepImpl @Test fun outToExcel() { @@ -153,8 +151,7 @@ } println("褰撳墠椤垫暟锛�$page") res.data?.forEach {vo -> - val d = RealTimeDataVehicle() - airDataRepository.dataTransform(vo, d) + val d = vo.toBaseRealTimeData(RealTimeDataVehicle::class.java) realTimeDataVehicleMapper.insert(d) count++ } diff --git a/src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt b/src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt index cfa3b78..8c62914 100644 --- a/src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt +++ b/src/test/kotlin/com/flightfeather/uav/socket/UnderwayProcessorTest.kt @@ -2,14 +2,21 @@ import com.flightfeather.uav.socket.processor.UnderwayProcessor 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 /** * @author riku * Date: 2019/9/16 */ +@RunWith(SpringRunner::class) +@SpringBootTest class UnderwayProcessorTest { - private val messageManager = UnderwayProcessor() + @Autowired + lateinit var messageManager: UnderwayProcessor @Test fun bccCheck() { -- Gitblit v1.9.3