feiyu02
2024-07-02 bf3bf9ff25ac106b556b2427cc382c8fcca63bff
1. 新增走航报告自动道路识别模块
已修改7个文件
已添加3个文件
321 ■■■■■ 文件已修改
pom.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/common/net/HttpMethod.kt 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/common/net/SkipCertificateValidation.kt 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/templates/report-underway.ftl 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -211,6 +211,12 @@
            <artifactId>jfreechart</artifactId>
            <version>1.5.3</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.0</version>
        </dependency>
    </dependencies>
    <build>
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionAnalysis.kt
@@ -6,6 +6,7 @@
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionType
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.domain.entity.BaseRealTimeData
import com.flightfeather.uav.domain.entity.avg
import com.flightfeather.uav.socket.eunm.FactorType
import java.time.Duration
@@ -54,6 +55,11 @@
            startData = start.getByFactorType(factor.main)
            endData = end?.getByFactorType(factor.main) ?: startData
            val avgData = exceptionData.avg()
            // æ±‚取污染数据的中心坐标
            longitude = avgData.longitude
            latitude = avgData.latitude
            // æ±‚取主污染因子的均值和范围
            val s = dataSummary(exceptionData, factor.main)
            avg = s.first
            min = s.second
@@ -63,7 +69,7 @@
        }
    }
    fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Float, Float, Float> {
    private fun dataSummary(exceptionData: List<BaseRealTimeData?>, factorType: FactorType): Triple<Float, Float, Float> {
        var min = -1f
        var max = -1f
        var total = 0f
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
@@ -7,6 +7,7 @@
import com.flightfeather.uav.biz.dataanalysis.model.DataAnalysisConfig
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
import com.flightfeather.uav.biz.dataanalysis.model.ExceptionSetting
import com.flightfeather.uav.common.location.LocationRoadNearby
import com.flightfeather.uav.domain.entity.Mission
import com.flightfeather.uav.domain.repository.RealTimeDataRep
import org.springframework.stereotype.Component
@@ -17,6 +18,7 @@
@Component
class ExceptionAnalysisController(
    private val realTimeDataRep: RealTimeDataRep,
    private val locationRoadNearby: LocationRoadNearby,
) {
    var running = false
@@ -26,15 +28,15 @@
    private fun initTask(config: DataAnalysisConfig) {
        taskList.clear()
        taskList.apply {
//            add(ExceptionDataExceed(config))
//            add(ExceptionValueMutation(config))
            add(ExceptionDataExceed(config))
            add(ExceptionValueMutation(config))
            add(ExceptionSlideAverage(config))
        }
    }
    fun run(mission: Mission, factorFilter: FactorFilter): List<ExceptionResult> {
        running = true
        val config = DataAnalysisConfig(mission, ExceptionSetting(), 8, factorFilter)
        val config = DataAnalysisConfig(mission, ExceptionSetting(), factorFilter)
        initTask(config)
        val result = mutableListOf<ExceptionResult>()
@@ -45,8 +47,26 @@
        }
        // å„个异常分析分别结束
        taskList.forEach { it.onDone() }
        // å­˜å‚¨åˆ†æžç»“æžœ
        taskList.forEach {
            // æŸ¥è¯¢å¼‚常周边可能污染源
            it.resultList.forEach { r->
                if (r.longitude != null && r.latitude != null) {
                    val sceneList = locationRoadNearby.searchByRadius(
                        r.longitude!!.toDouble() to r.latitude!!.toDouble(), config.radius)
                    if (sceneList.isNotEmpty()) {
                        val idList = mutableListOf<String>()
                        val nameList = mutableListOf<String>()
                        sceneList.forEach { s->
                            idList.add(s?.guid?:"")
                            nameList.add(s?.name ?: "")
                        }
                        r.relatedSceneId = idList
                        r.relatedSceneName = nameList
                    }
                }
            }
            // å­˜å‚¨åˆ†æžç»“æžœ
            result.addAll(it.resultList)
        }
        running = false
src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/model/DataAnalysisConfig.kt
@@ -11,8 +11,6 @@
    val mission: Mission,
    // æ•°æ®å¼‚常配置
    val exceptionSetting: ExceptionSetting,
    // æ¶‰åŠç›‘测因子数量
    val factorCount: Int,
    // å› å­ç­›é€‰
    val factorFilter: FactorFilter,
){
@@ -28,4 +26,7 @@
    var changeTrendRate = 1
    // æ»‘动平均值变化率异常连续次数
    var changeTrendTimes = 3
    // å¼‚常周边可能污染源查询范围半径(米)
    var radius = 500.0
}
src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,19 @@
package com.flightfeather.uav.common.net
/**
 * é«˜å¾·åœ°å›¾Web服务API
 */
object AMapService {
    private val httpMethod = HttpMethod("restapi.amap.com", 443, true)
    private val KEY = ""
    /**
     * åœ°ç†é€†ç¼–码
     */
    fun reGeo(location:List<Pair<Double, Double>>) {
        httpMethod.get("v3/geocode/regeo", listOf(
        ))
    }
}
src/main/kotlin/com/flightfeather/uav/common/net/HttpMethod.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
package com.flightfeather.uav.common.net
import org.apache.commons.httpclient.HttpClient
import org.apache.commons.httpclient.HttpMethodBase
import org.apache.commons.httpclient.methods.GetMethod
import org.apache.commons.httpclient.methods.PostMethod
import org.apache.commons.httpclient.methods.StringRequestEntity
import org.apache.commons.httpclient.protocol.Protocol
import org.slf4j.LoggerFactory
/**
 * @author riku
 * Date: 2020/10/14
 */
class HttpMethod(
        private val host: String, private val port: Int, private val isHttps: Boolean = false
) {
    private val logger = LoggerFactory.getLogger(HttpMethod::class.java)
    data class MyResponse(
            val success: Boolean,
            val m: HttpMethodBase
    )
    object Head {
        val TEXT_PLAIN = Pair("Content-Type", "text/plain")
    }
    private val httpClient = HttpClient()
    init {
        Protocol.registerProtocol("https", Protocol("https", SkipCertificateValidation.MySecureProtocolSocketFactory(), port))
        if (isHttps) {
            httpClient.hostConfiguration.setHost(host, port, Protocol.getProtocol("https"))
        } else {
            httpClient.hostConfiguration.setHost(host, port)
        }
    }
    fun get(url: String, params: List<Pair<String, String>> = emptyList(), headers: List<Pair<String, String>> = emptyList()): MyResponse {
        var p: String = ""
        params.forEach {
            p += if (p.isBlank()) {
                it.first + "=" + it.second
            } else {
                "&" + it.first + "=" + it.second
            }
        }
        val getMethod = GetMethod("$url?$p")
        defaultConfig(getMethod)
        headers.forEach {
            getMethod.setRequestHeader(it.first, it.second)
        }
        return when (httpClient.executeMethod(getMethod)) {
            200 -> MyResponse(true, getMethod)
            else -> MyResponse(false, getMethod)
        }
    }
    fun post(url: String, data: String = "", headers: List<Pair<String, String>> = emptyList()): MyResponse {
        val postMethod = PostMethod(url)
        defaultConfig(postMethod)
        headers.forEach {
            postMethod.setRequestHeader(it.first, it.second)
        }
        if (data.isNotBlank()) {
            postMethod.requestEntity = StringRequestEntity(data, "application/json", "utf-8")
        }
        return try {
            when (httpClient.executeMethod(postMethod)) {
                200 -> MyResponse(true, postMethod)
                else -> MyResponse(false, postMethod)
            }
        } catch (e: Exception) {
            logger.error(e.message)
            MyResponse(false, postMethod)
        }
    }
    private fun defaultConfig(method: HttpMethodBase) {
        method.setRequestHeader("Accept", "*/*");
        method.setRequestHeader("Connection", "Keep-Alive");
//        method.setRequestHeader("Accept-Language", "zh-cn,zh;q=0.5");
        method.setRequestHeader("Accept-Encoding", "gzip,deflate,br");
//        method.setRequestHeader("Content-Type", "application/json;charset=utf-8")
        method.setRequestHeader("Content-Type", "application/json")
//        method.setRequestHeader("Content-Type", "application/json;charset=GBK")
    }
}
src/main/kotlin/com/flightfeather/uav/common/net/SkipCertificateValidation.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,150 @@
package com.flightfeather.uav.common.net
import org.apache.commons.httpclient.ConnectTimeoutException
import org.apache.commons.httpclient.HttpClientError
import org.apache.commons.httpclient.params.HttpConnectionParams
import org.apache.commons.httpclient.protocol.ControllerThreadSocketFactory
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory
import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory
import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.net.UnknownHostException
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.*
/**
 * é€šè¿‡java è¿›è¡Œè®¿é—®æœ‰æ—¶å€™ä¼šæœ‰è¯ä¹¦è¿›è¡Œæ‹¦æˆª
 */
object SkipCertificateValidation {
    /**
     * å¿½ç•¥HTTPS请求的SSL证书,必须在openConnection之前调用
     * @throws Exception
     */
    @Throws(Exception::class)
    fun ignoreSsl() {
        val hv = HostnameVerifier { urlHostName, session ->
            println("Warning: URL Host: " + urlHostName + " vs. " + session.peerHost)
            true
        }
        trustAllHttpsCertificates()
        HttpsURLConnection.setDefaultHostnameVerifier(hv)
    }
    @Throws(Exception::class)
    private fun trustAllHttpsCertificates() {
        val trustAllCerts = arrayOfNulls<TrustManager>(1)
        val tm: TrustManager = MiTM()
        trustAllCerts[0] = tm
        val sc = SSLContext.getInstance("SSL")
        sc.init(null, trustAllCerts, null)
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)
    }
    internal class MiTM : X509TrustManager {
        override fun getAcceptedIssuers(): Array<X509Certificate>? {
            return null
        }
        @Throws(CertificateException::class)
        override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) {
            return
        }
        @Throws(CertificateException::class)
        override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) {
            return
        }
    }
    class MySecureProtocolSocketFactory : ProtocolSocketFactory {
        //这里添加一个属性,主要目的就是来获取ssl跳过验证
        private var sslContext: SSLContext? = null
        /**
         * åˆ¤æ–­èŽ·å–SSLContext
         * @return
         */
        private val sSLContext: SSLContext?
            get() {
                if (sslContext == null) {
                    sslContext = createEasySSLContext()
                }
                return sslContext
            }
        //后面的方法基本上就是带入相关参数就可以了
        /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
     *      int, java.net.InetAddress, int)
     */
        @Throws(IOException::class, UnknownHostException::class)
        override fun createSocket(host: String, port: Int, clientHost: InetAddress?, clientPort: Int): Socket {
            return sSLContext!!.socketFactory.createSocket(host, port, clientHost, clientPort)
        }
        /*
     * (non-Javadoc)
     *
     * @see org.apache.commons.httpclient.protocol.ProtocolSocketFactory#createSocket(java.lang.String,
     *      int, java.net.InetAddress, int,
     *      org.apache.commons.httpclient.params.HttpConnectionParams)
     */
        @Throws(IOException::class, UnknownHostException::class, ConnectTimeoutException::class)
        override fun createSocket(
            host: String, port: Int, localAddress: InetAddress?, localPort: Int,
            params: HttpConnectionParams?
        ): Socket {
            requireNotNull(params) { "Parameters may not be null" }
            val timeout: Int = params.connectionTimeout
            return if (timeout == 0) {
                createSocket(host, port, localAddress, localPort)
            } else {
                ControllerThreadSocketFactory.createSocket(this, host, port, localAddress, localPort, timeout)
            }
        }
        /*
     * (non-Javadoc)
     *
     * @see SecureProtocolSocketFactory#createSocket(java.lang.String,int)
     */
        @Throws(IOException::class, UnknownHostException::class)
        override fun createSocket(host: String, port: Int): Socket {
            return sSLContext!!.socketFactory.createSocket(host, port)
        }
        /*
     * (non-Javadoc)
     *
     * @see SecureProtocolSocketFactory#createSocket(java.net.Socket,java.lang.String,int,boolean)
     */
//        @Throws(IOException::class, UnknownHostException::class)
//        override fun createSocket(socket: Socket?, host: String?, port: Int, autoClose: Boolean): Socket {
//            return sSLContext!!.socketFactory.createSocket(socket, host, port, autoClose)
//        }
        companion object {
            /**
             * è¿™ä¸ªåˆ›å»ºä¸€ä¸ªèŽ·å–SSLContext的方法,导入MyX509TrustManager进行初始化
             * @return
             */
            private fun createEasySSLContext(): SSLContext {
                return try {
                    val context = SSLContext.getInstance("SSL")
                    context.init(
                        null, arrayOf(MiTM()),
                        null
                    )
                    context
                } catch (e: Exception) {
                    throw HttpClientError(e.toString())
                }
            }
        }
    }
}
src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
@@ -1,7 +1,7 @@
package com.flightfeather.uav.domain.entity
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.biz.dataprocess.AvgPair
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.socket.bean.AirData
import com.flightfeather.uav.socket.eunm.FactorType
@@ -11,7 +11,10 @@
import java.util.*
import javax.persistence.Column
import javax.persistence.Id
import kotlin.math.*
import kotlin.math.atan
import kotlin.math.cos
import kotlin.math.round
import kotlin.math.sin
/**
 * å®žæ—¶ç›‘测数据基类
@@ -148,7 +151,7 @@
}
fun List<BaseRealTimeData>.avg(): RealTimeDataGridMin {
fun List<BaseRealTimeData>.avg(): BaseRealTimeData {
    //风向采用单位矢量法求取均值
    var u = .0//东西方位分量总和
    var v = .0//南北方位分量总和
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
@@ -374,7 +374,7 @@
        val averageUtil = AverageUtil<RealTimeDataGridOpt, RealTimeDataGridMin>({ d ->
            minFormatter.format(d.dataTime)
        }, { list ->
            list.avg()
            list.avg() as RealTimeDataGridMin
        })
        while (total == -1 || page <= total) {
src/main/resources/templates/report-underway.ftl
@@ -1252,7 +1252,7 @@
                                <w:szCs w:val="28" />
                                <w:lang w:val="en-US" w:eastAsia="zh-CN" />
                            </w:rPr>
                            <w:t>${item_index + 1}. ä»Ž${item.startTime}至${item.endTime},${item.factorName}出现${item.exception}<#if item.relatedSceneName??>,结合监测数据变化和受点反向溯源,<#list item.relatedSceneName as scene>${scene}、</#list>等可能存在污染风险。<#else>。</#if></w:t>
                            <w:t>${item_index + 1}. ä»Ž${item.startTime}至${item.endTime},${item.factorName}出现${item.exception}<#if item.relatedSceneName??>,结合监测数据变化和受点反向溯源,<#list item.relatedSceneName as scene><#if (scene_index > 0)>、</#if>${scene}</#list>等可能存在污染风险。<#else>。</#if></w:t>
                        </w:r>
                    </w:p>
                    <w:p>