From 9ed0b1847912221197697791d69e01ccae17f5b9 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 27 八月 2024 17:36:11 +0800
Subject: [PATCH] 1. 新增NO监测因子 2. 新增第三方数据接口数据获取相关模块

---
 src/main/kotlin/com/flightfeather/uav/common/net/ShenXinService.kt                      |  128 +++++++
 src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRep.kt              |  145 +++++--
 src/main/resources/mapper/RealTimeDataGridOptMapper.xml                                 |    3 
 src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRepDelegate.kt      |  134 +++++++
 src/main/resources/mapper/RealTimeDataVehicleMapper.xml                                 |    5 
 src/main/kotlin/com/flightfeather/uav/lightshare/web/ThirdPartyController.kt            |   45 ++
 src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt                       |    4 
 src/main/resources/application-pro.yml                                                  |   13 
 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt |    3 
 pom.xml                                                                                 |   32 +
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ThirdPartyServiceImpl.kt  |   40 ++
 src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt                               |   28 +
 src/main/resources/generator/generatorConfig.xml                                        |    6 
 src/main/kotlin/com/flightfeather/uav/scheduler/ScheduleService.kt                      |   65 +++
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt |    5 
 src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt                 |    3 
 src/main/resources/application-dev.yml                                                  |    3 
 src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt                       |    4 
 src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ThirdPartyLabel.kt                |   10 
 src/main/resources/mapper/RealTimeDataGridMinMapper.xml                                 |    3 
 src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt                         |    1 
 src/main/kotlin/com/flightfeather/uav/lightshare/service/ThirdPartyService.kt           |   30 +
 src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt   |    7 
 src/main/kotlin/com/flightfeather/uav/biz/datafetch/ShenXinDataFetch.kt                 |  130 +++++++
 src/main/resources/application-test.yml                                                 |   15 
 src/main/kotlin/com/flightfeather/uav/common/net/SoapClient.kt                          |  140 +++++++
 src/test/kotlin/com/flightfeather/uav/common/net/ShenXinServiceTest.kt                  |   27 +
 src/main/resources/mapper/RealTimeDataGridMapper.xml                                    |    3 
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt     |   14 
 src/main/resources/mapper/RealTimeDataUavMapper.xml                                     |    3 
 30 files changed, 963 insertions(+), 86 deletions(-)

diff --git a/pom.xml b/pom.xml
index 23dbb36..b8e37db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,6 +217,38 @@
             <artifactId>httpmime</artifactId>
             <version>4.5.14</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/javax.xml.ws/jaxws-api -->
+<!--        <dependency>-->
+<!--            <groupId>javax.xml.ws</groupId>-->
+<!--            <artifactId>jaxws-api</artifactId>-->
+<!--            <version>2.3.1</version>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash; https://mvnrepository.com/artifact/org.apache.axis2/axis2-jaxws &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.axis2</groupId>-->
+<!--            <artifactId>axis2-jaxws</artifactId>-->
+<!--            <version>1.8.2</version>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash; https://mvnrepository.com/artifact/org.apache.axis2/axis2-adb &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.axis2</groupId>-->
+<!--            <artifactId>axis2-adb</artifactId>-->
+<!--            <version>1.8.2</version>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash; https://mvnrepository.com/artifact/org.apache.axis2/axis2-transport-base &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>org.apache.axis2</groupId>-->
+<!--            <artifactId>axis2-transport-base</artifactId>-->
+<!--            <version>1.8.2</version>-->
+<!--        </dependency>-->
+        <!-- https://mvnrepository.com/artifact/org.apache.axis2/axis2-kernel -->
+        <dependency>
+            <groupId>org.apache.axis2</groupId>
+            <artifactId>axis2-kernel</artifactId>
+            <version>1.8.2</version>
+        </dependency>
+
+
     </dependencies>
 
     <build>
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt b/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
index 080d087..6a34992 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/FactorFilter.kt
@@ -38,27 +38,37 @@
         fun default() = builder()
             .withMain(FactorType.VOC)
             .withSubs(listOf(
-                FactorType.H2S,
+//                FactorType.H2S,
                 FactorType.O3,
                 FactorType.PM25,
+                FactorType.PM10,
             ))
-            .withMain(FactorType.H2S)
-            .withSubs(listOf(
-                FactorType.VOC,
-                FactorType.O3,
-                FactorType.PM25,
-            ))
+//            .withMain(FactorType.H2S)
+//            .withSubs(listOf(
+//                FactorType.VOC,
+//                FactorType.O3,
+//                FactorType.PM25,
+//            ))
             .withMain(FactorType.O3)
             .withSubs(listOf(
                 FactorType.VOC,
-                FactorType.H2S,
+//                FactorType.H2S,
                 FactorType.PM25,
+                FactorType.PM10,
             ))
             .withMain(FactorType.PM25)
             .withSubs(listOf(
                 FactorType.VOC,
-                FactorType.H2S,
+//                FactorType.H2S,
                 FactorType.O3,
+                FactorType.PM10,
+            ))
+            .withMain(FactorType.PM10)
+            .withSubs(listOf(
+                FactorType.VOC,
+//                FactorType.H2S,
+                FactorType.O3,
+                FactorType.PM25,
             ))
 //            .withSubs(listOf(
 //                FactorType.NO2,
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 f712600..9a10bdc 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/BaseExceptionContinuousSingle.kt
@@ -21,8 +21,7 @@
                 // 鍒ゆ柇鐩搁偦鏁版嵁鏄惁杩炵画骞朵笖鏄惁婊¤冻寮傚父鍒ゆ柇
                 if (!isContinue) {
                     checkResult(s)
-                    it.sIndex = it.eIndex
-                    it.startData = data
+                    it.refreshAfterCheckResult(data)
                 } else {
                     if (hasException[f] == true) {
                         // 淇敼浜嗚捣濮嬫暟鎹殑浣嶇疆,鍙樻洿涓哄嚭鐜板紓甯哥殑璇ュ��,鑰屼笉鏄師鏉ョ殑鍑虹幇寮傚父鐨勬暟鎹殑鍓嶄竴涓��
@@ -31,8 +30,10 @@
                             it.startData = data
                         }
                         it.existException = true
+                        it.exceptionData.add(data)
                     } else {
                         checkResult(s)
+                        it.refreshAfterCheckResult(data)
                     }
                 }
             }
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
index ed6c540..ae45e39 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/dataanalysis/ExceptionAnalysisController.kt
@@ -11,6 +11,7 @@
 import com.flightfeather.uav.domain.entity.Mission
 import com.flightfeather.uav.domain.repository.RealTimeDataRep
 import com.flightfeather.uav.domain.repository.SegmentInfoRep
+import com.flightfeather.uav.socket.eunm.UWDeviceType
 import org.springframework.stereotype.Component
 import java.time.LocalDateTime
 import java.time.ZoneId
@@ -47,7 +48,11 @@
         val result = mutableListOf<ExceptionResult>()
         taskList.forEach { it.init() }
         // 杞鏁版嵁锛岃绠楀悇涓紓甯�
-        realTimeDataRep.fetchData(mission.deviceCode, mission.startTime, mission.endTime).forEach { d ->
+        realTimeDataRep.fetchData(UWDeviceType.fromValue(mission.deviceType),
+            mission.deviceCode,
+            mission.startTime,
+            mission.endTime
+        ).forEach { d ->
             taskList.forEach { it.onNextData(d) }
         }
         // 鍚勪釜寮傚父鍒嗘瀽鍒嗗埆缁撴潫
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/datafetch/ShenXinDataFetch.kt b/src/main/kotlin/com/flightfeather/uav/biz/datafetch/ShenXinDataFetch.kt
new file mode 100644
index 0000000..3cf32bd
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/biz/datafetch/ShenXinDataFetch.kt
@@ -0,0 +1,130 @@
+package com.flightfeather.uav.biz.datafetch
+
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.common.net.ShenXinService
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.repository.MissionRep
+import com.flightfeather.uav.domain.repository.RealTimeDataRep
+import com.flightfeather.uav.socket.eunm.UWDeviceType
+import org.springframework.stereotype.Component
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.concurrent.ConcurrentHashMap
+
+/**
+ * 鐢虫鐜繚璧拌埅鐩戞祴鏁版嵁鑾峰彇
+ * 姣忓彴璁惧鍙湁涓�涓嚎绋嬶紝纭繚涓嶄細閲嶅鑾峰彇
+ * @date 2024/8/23
+ * @author feiyu02
+ */
+@Component
+class ShenXinDataFetch(private val missionRep: MissionRep, private val realTimeDataRep: RealTimeDataRep) {
+
+    // 璁惧鏄惁姝e湪鑾峰彇鏈�鏂版暟鎹�
+    private val deviceStatusMap = ConcurrentHashMap<String, Boolean>()
+    // 璧拌埅浠诲姟鏄惁姝e湪鑾峰彇鏁版嵁
+    private val missionStatusMap = ConcurrentHashMap<String, Boolean>()
+    /**
+     * 鑾峰彇鏈�鏂扮殑鏁版嵁
+     * @param deviceType 璁惧绫诲瀷
+     * @param code 璁惧缂栧彿
+     */
+    private fun fetchLatestData(deviceType: UWDeviceType, code: String) {
+        if (deviceStatusMap.containsKey(code)) {
+            // 璁惧姝e湪鑾峰彇瀹炴椂鏁版嵁锛屽垯鐩存帴杩斿洖锛屾斁寮冩湰娆¤姹�
+            if (deviceStatusMap[code] == true) {
+                return
+            }
+            // 鍚﹀垯寮�濮嬭幏鍙栨暟鎹紝淇敼鐘舵�佷负true
+            else {
+                deviceStatusMap[code] = true
+            }
+        }
+        // 褰撹澶囬娆¤幏鍙栨暟鎹椂锛岀洿鎺ュ紑濮嬪苟淇敼鐘舵�佷负true
+        else {
+            deviceStatusMap[code] = true
+        }
+
+        try {
+            val latestData = realTimeDataRep.fetchData(deviceType, code, null, null, null, 1, 1)
+            val st = if (latestData.isEmpty()) {
+                LocalDate.now().atStartOfDay()
+            } else {
+                LocalDateTime.ofInstant(latestData[0].dataTime?.toInstant(), ZoneId.systemDefault()).plusSeconds(1)
+            }
+            val data = ShenXinService.fetchData(code, st, LocalDateTime.now())
+            realTimeDataRep.saveData(deviceType, data)
+        } finally {
+            // 璁惧瀹屾垚鏁版嵁鑾峰彇鍚庯紝淇敼鐘舵�佷负false
+            deviceStatusMap[code] = false
+        }
+    }
+
+    /**
+     * 鑾峰彇缁欏畾鏃堕棿鑼冨洿鍐呯殑鏁版嵁
+     */
+    fun fetchLatestData(deviceType: UWDeviceType, code: String, sTime: LocalDateTime?, eTime: LocalDateTime?) {
+        if (sTime != null && eTime != null) {
+            val data = ShenXinService.fetchData(code, sTime, eTime)
+            realTimeDataRep.deleteData(deviceType, code, sTime, eTime)
+            realTimeDataRep.saveData(deviceType, data)
+        } else if (sTime == null && eTime == null) {
+            fetchLatestData(deviceType, code)
+        } else {
+            throw BizException("寮�濮嬪拰缁撴潫鏃堕棿闇�瑕侀兘鐪佺暐鎴栬�呴兘濉啓")
+        }
+    }
+
+    /**
+     * 鑾峰彇浠诲姟鐨勬墍鏈夋暟鎹�
+     * @param mission 浠诲姟淇℃伅
+     * @param forceUpdate 寮哄埗灏嗚幏鍙栫殑鏁版嵁鏇挎崲鍘熸湁鐨勬暟鎹�
+     */
+    fun fetchMissionData(mission: Mission, forceUpdate: Boolean = false) {
+        if (missionStatusMap.containsKey(mission.missionCode)) {
+            // 璧拌埅浠诲姟姝e湪鑾峰彇鏁版嵁锛屽垯鐩存帴杩斿洖锛屾斁寮冩湰娆¤姹�
+            if (missionStatusMap[mission.missionCode] == true) {
+                return
+            }
+            // 鍚﹀垯寮�濮嬭幏鍙栨暟鎹紝淇敼鐘舵�佷负true
+            else {
+                missionStatusMap[mission.missionCode] = true
+            }
+        }
+        // 褰撹蛋鑸换鍔¢娆¤幏鍙栨暟鎹椂锛岀洿鎺ュ紑濮嬪苟淇敼鐘舵�佷负true
+        else {
+            missionStatusMap[mission.missionCode] = true
+        }
+
+        try {
+            val st = LocalDateTime.ofInstant(mission.startTime?.toInstant(), ZoneId.systemDefault())
+            val et = LocalDateTime.ofInstant(mission.endTime?.toInstant(), ZoneId.systemDefault())
+            val data = ShenXinService.fetchData(mission.deviceCode, st, et)
+            val type = UWDeviceType.fromValue(mission.deviceType)
+            val oldData = realTimeDataRep.fetchData(mission)
+            // 鍒ゆ柇鏂版暟鎹暟鎹噺鏄惁绛変簬鏃ф暟鎹紝鑻ヤ笉鐩哥瓑锛屽垯绠�鍗曡涓烘暟鎹湁鍙樺姩锛涙垨鑰呰缃簡寮哄埗鏇存柊
+            if (data.size != oldData.size || forceUpdate) {
+                if (oldData.isNotEmpty()) {
+                    realTimeDataRep.deleteData(mission)
+                }
+                realTimeDataRep.saveData(type, data)
+            }
+        } finally {
+            // 璧拌埅浠诲姟瀹屾垚鏁版嵁鑾峰彇鍚庯紝淇敼鐘舵�佷负false
+            missionStatusMap[mission.missionCode] = false
+        }
+    }
+
+    /**
+     * 鑾峰彇浠诲姟鐨勬墍鏈夋暟鎹�
+     * @param missionCode 浠诲姟缂栧彿
+     * @param forceUpdate 寮哄埗灏嗚幏鍙栫殑鏁版嵁鏇挎崲鍘熸湁鐨勬暟鎹�
+     */
+    fun fetchMissionData(missionCode: String, forceUpdate: Boolean = false) {
+        val mission = missionRep.findOne(missionCode) ?: throw BizException("浠诲姟涓嶅瓨鍦紝鏃犳硶鑾峰彇绗笁鏂规暟鎹�")
+        fetchMissionData(mission, forceUpdate)
+    }
+
+
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
index 62bbcf6..a2c474d 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionReport.kt
@@ -149,12 +149,12 @@
         // 4. 鐢熸垚鎶ュ憡
         val fileName = "report/" + "${mission.districtName}璧拌埅鐩戞祴鎶ュ憡-${
             DateUtil.instance.dateToString(mission.startTime, DateUtil.DateStyle.YYYY_MM_DD)
-        }.doc"
+        }(${mission.missionCode}).doc"
         val reportTemplate = ReportTemplate(templateName, filePath, fileName)
         val param = getParam(mission, exceptions, summaries)
         val params = reportTemplate.getParam(param)
         GeneratePdfUtil.generateWord(params)
-        return fileName
+        return filePath + fileName
     }
 
     private fun getParam(mission: Mission, exceptions: List<ExceptionResult>, summaries: List<Summary>): Param {
diff --git a/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt b/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt
index 4ea338d..615bc8f 100644
--- a/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt
+++ b/src/main/kotlin/com/flightfeather/uav/common/net/AMapService.kt
@@ -11,6 +11,7 @@
 
 /**
  * 楂樺痉鍦板浘Web鏈嶅姟API
+ * Date: 2024/07/14
  */
 object AMapService {
 
diff --git a/src/main/kotlin/com/flightfeather/uav/common/net/ShenXinService.kt b/src/main/kotlin/com/flightfeather/uav/common/net/ShenXinService.kt
new file mode 100644
index 0000000..6474986
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/common/net/ShenXinService.kt
@@ -0,0 +1,128 @@
+package com.flightfeather.uav.common.net
+
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.common.utils.DateUtil
+import com.flightfeather.uav.domain.entity.BaseRealTimeData
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.entity.RealTimeDataVehicle
+import org.w3c.dom.Element
+import java.math.BigDecimal
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+import java.util.*
+import javax.xml.soap.Node
+
+/**
+ * 鐢虫鐜繚璧拌埅鐩戞祴鏁版嵁鎺ュ彛API
+ * Date: 2024/08/22
+ */
+object ShenXinService {
+
+    private const val USER = "user1"
+    private const val PW = "User1@jingan"
+
+    //    "
+    private val soapClient = SoapClient(
+        "http://tempuri.org/",
+        "http://180.169.129.106:9001/WebService.asmx?wsdl",
+        "WebService", "WebServiceSoap", "GetData",
+        "GetDataResponse"
+    )
+
+    data class DataParams(
+        val mn: String?,
+        val dtFrom: String?,
+        val dtTo: String?,
+        val compUser: String = USER,
+        val compPassword: String = PW,
+    ) {
+        fun toMap(): MutableMap<String?, String?> {
+            return mutableMapOf(
+                "compUser" to compUser,
+                "compPassword" to compPassword,
+                "mn" to mn,
+                "dtFrom" to dtFrom,
+                "dtTo" to dtTo,
+            )
+        }
+    }
+
+    fun fetchData(mission: Mission, updateTime: LocalDateTime): List<BaseRealTimeData> {
+        val et = LocalDateTime.ofInstant(mission.endTime.toInstant(), ZoneId.systemDefault())
+        if (updateTime.isAfter(et)) return emptyList()
+        return fetchData(mission.deviceCode, updateTime, et)
+    }
+
+    fun fetchData(deviceCode: String?, startTime: LocalDateTime, endTime:LocalDateTime): List<BaseRealTimeData> {
+        val st = startTime.format(DateTimeFormatter.ofPattern(DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS.value))
+        val et = endTime.format(DateTimeFormatter.ofPattern(DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS.value))
+        val param = DataParams(deviceCode, st, et)
+        val realTimeDataVehicleList = mutableListOf<BaseRealTimeData>()
+        soapClient.sendMessage(param.toMap())?.let { res ->
+            try {
+                // 鑺傜偣GetDataResult
+                val result = res.item(0).firstChild
+                // 鑺傜偣ReturnCode锛�0琛ㄧず鎴愬姛
+                if (result.firstChild.textContent == "0") {
+//                    println(result.childNodes.item(2).nodeName)
+                    // 鑺傜偣ListInfo鍐呯殑鏁版嵁鍒楄〃
+                    val dataNodes = result.childNodes.item(2).childNodes
+                    // 閬嶅巻姣忎釜DataInfo鑺傜偣锛岃浆鎹负 [RealTimeDataVehicle] 瀵硅薄
+                    for (i in 0 until dataNodes.length) {
+                        val dataInfo = dataNodes.item(i)
+                        if (dataInfo.nodeType == Element.ELEMENT_NODE) {
+                            val element = dataInfo as Element
+                            realTimeDataVehicleList.add(elementToRealTimeData(deviceCode, element))
+                        }
+                    }
+                }
+            } catch (e: Exception) {
+                throw BizException("鐢虫鐜繚璧拌埅鐩戞祴鏁版嵁鎺ュ彛瑙f瀽澶辫触", e)
+            }
+        }
+        return realTimeDataVehicleList
+    }
+
+    /**
+     * DataInfo杞崲涓篟ealTimeDataVehicle
+     */
+    private fun elementToRealTimeData(deviceCode: String?, element: Element): BaseRealTimeData {
+        return BaseRealTimeData().apply {
+            this.deviceCode = deviceCode
+            no = toFloatBlank(element.getElementsByTagName("NO").item(0).textContent)
+            no2 = toFloatBlank(element.getElementsByTagName("NO2").item(0).textContent)
+            co = toFloatBlank(element.getElementsByTagName("CO").item(0).textContent) * 1000
+            pm25 = toFloatBlank(element.getElementsByTagName("PM25").item(0).textContent)
+            pm10 = toFloatBlank(element.getElementsByTagName("PM10").item(0).textContent)
+            longitude = toBigDecimal(element.getElementsByTagName("Lon").item(0).textContent)
+            latitude = toBigDecimal(element.getElementsByTagName("Lat").item(0).textContent)
+            temperature = toFloatBlank(element.getElementsByTagName("Temperature").item(0).textContent)
+            velocity = toFloatBlank(element.getElementsByTagName("Speed").item(0).textContent)
+            windSpeed = toFloatBlank(element.getElementsByTagName("WindSpeed").item(0).textContent)
+            windDirection = toFloatBlank(element.getElementsByTagName("WindDirection").item(0).textContent)
+            dataTime = DateUtil.instance.StringToDate(
+                element.getElementsByTagName("PostTime").item(0).textContent,
+                DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS_EN)
+            createTime = Date()
+        }
+    }
+
+    private fun toFloatBlank(str: String): Float {
+        val _str = str.trim()
+        return if (_str.isBlank()) {
+            0f
+        } else {
+            _str.toFloat()
+        }
+    }
+
+    private fun toBigDecimal(str: String): BigDecimal {
+        val _str = str.trim()
+        return if (_str.isBlank()) {
+            BigDecimal.ZERO
+        } else {
+            _str.toBigDecimal()
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/common/net/SoapClient.kt b/src/main/kotlin/com/flightfeather/uav/common/net/SoapClient.kt
new file mode 100644
index 0000000..9913895
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/common/net/SoapClient.kt
@@ -0,0 +1,140 @@
+package com.flightfeather.uav.common.net
+
+import com.flightfeather.uav.common.exception.BizException
+import com.sun.xml.internal.ws.client.BindingProviderProperties
+import com.sun.xml.internal.ws.developer.JAXWSProperties
+import javax.xml.soap.*
+import javax.xml.ws.Dispatch
+import javax.xml.ws.Service
+import org.w3c.dom.Document
+import org.w3c.dom.NodeList
+import java.net.URL
+import javax.xml.namespace.QName
+import javax.xml.ws.BindingProvider
+import javax.xml.ws.BindingProvider.SOAPACTION_URI_PROPERTY
+import javax.xml.ws.BindingProvider.SOAPACTION_USE_PROPERTY
+import javax.xml.ws.soap.SOAPBinding
+
+
+/**
+ * soap瀹㈡埛绔�
+ * @date 2024/8/22
+ * @author feiyu02
+ */
+class SoapClient {
+    var nameSpace = "" //wsdl鐨勫懡鍚嶇┖闂�
+    var wsdlUrl = "" //wsdl鏂囨。鍦板潃
+    var serviceName = "" //鏈嶅姟鐨勫悕瀛�
+    var portName = ""
+    var responseName = "" //@WebResult锛氭敞瑙d笂鐨刵ame鍊�
+    var elementName = "" //榛樿鏄璁块棶鐨勬柟娉曞悕 濡傛灉@WebMethod灞炴�ame鏈夊�� 鍒欐槸璇ュ�硷紝瀹為檯杩樻槸浠sdl鏂囨。涓轰富
+    var timeout = 20000
+
+    /**
+     * @param nameSpace
+     * @param wsdlUrl
+     * @param serviceName
+     * @param portName
+     * @param element
+     * @param responseName
+     */
+    constructor(
+        nameSpace: String, wsdlUrl: String,
+        serviceName: String, portName: String, element: String,
+        responseName: String,
+    ) {
+        this.nameSpace = nameSpace
+        this.wsdlUrl = wsdlUrl
+        this.serviceName = serviceName
+        this.portName = portName
+        elementName = element
+        this.responseName = responseName
+    }
+
+    /**
+     * @param nameSpace
+     * @param wsdlUrl
+     * @param serviceName
+     * @param portName
+     * @param element
+     * @param responseName
+     * @param timeOut      姣
+     */
+    constructor(
+        nameSpace: String, wsdlUrl: String,
+        serviceName: String, portName: String, element: String,
+        responseName: String, timeOut: Int,
+    ) {
+        this.nameSpace = nameSpace
+        this.wsdlUrl = wsdlUrl
+        this.serviceName = serviceName
+        this.portName = portName
+        elementName = element
+        this.responseName = responseName
+        timeout = timeOut
+    }
+
+    @Throws(Exception::class)
+    fun sendMessage(inMsg: Map<String?, String?>): NodeList? {
+        // 鍒涘缓URL瀵硅薄
+        var url: URL? = null
+        url = try {
+            URL(wsdlUrl)
+        } catch (e: Exception) {
+            throw BizException("soap:鍒涘缓URL瀵硅薄寮傚父", e)
+        }
+        // 鍒涘缓鏈嶅姟(Service)
+        val sname = QName(nameSpace, serviceName)
+        val service: Service = Service.create(url, sname)
+
+        // 鍒涘缓Dispatch瀵硅薄
+        var dispatch: Dispatch<SOAPMessage?>? = null
+        dispatch = try {
+            service.createDispatch(QName(nameSpace, portName), SOAPMessage::class.java, Service.Mode.MESSAGE)
+        } catch (e: Exception) {
+            throw BizException("soap:鍒涘缓Dispatch瀵硅薄寮傚父", e)
+        }
+
+        // 鍒涘缓SOAPMessage
+        return try {
+            //杩欏彞璇濆緢閲嶈锛屽惁鍒欐姤閿欐湇鍔″櫒鏈兘璇嗗埆 HTTP 澶� SOAPAction 鐨勫��
+            dispatch?.requestContext?.put(SOAPACTION_URI_PROPERTY, nameSpace + elementName)
+            dispatch?.requestContext?.put(SOAPACTION_USE_PROPERTY, true)
+            dispatch?.requestContext?.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, wsdlUrl.replace("?wsdl", ""))
+            val msg: SOAPMessage = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL).createMessage()
+            msg.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8")
+            val envelope: SOAPEnvelope = msg.getSOAPPart().getEnvelope()
+
+
+            // 鍒涘缓SOAPHeader(涓嶆槸蹇呴渶)
+            // SOAPHeader header = envelope.getHeader();
+            // if (header == null)
+            // header = envelope.addHeader();
+            // QName hname = new QName(nameSpace, "username", "nn");
+            // header.addHeaderElement(hname).setValue("huoyangege");
+
+
+            // 鍒涘缓SOAPBody
+            val body: SOAPBody = envelope.getBody()
+            val ename = QName(nameSpace, elementName, "")
+            val ele: SOAPBodyElement = body.addBodyElement(ename)
+            // 澧炲姞Body鍏冪礌鍜屽��
+            inMsg.forEach { (key, value) ->
+                ele.addChildElement(QName(nameSpace, key)).value = value
+            }
+
+            // 瓒呮椂璁剧疆
+            dispatch?.requestContext?.put(BindingProviderProperties.CONNECT_TIMEOUT, timeout)
+            dispatch?.requestContext?.put(JAXWSProperties.REQUEST_TIMEOUT, timeout)
+            // 閫氳繃Dispatch浼犻�掓秷鎭�,浼氳繑鍥炲搷搴旀秷鎭�
+            val response = dispatch?.invoke(msg)
+
+            // 鍝嶅簲娑堟伅澶勭悊,灏嗗搷搴旂殑娑堟伅杞崲涓篸oc瀵硅薄
+            val doc = response?.soapPart?.envelope?.body?.extractContentAsDocument()
+//            doc?.getElementsByTagName(responseName)?.item(0)?.textContent ?: ""
+            doc?.getElementsByTagName(responseName)
+        } catch (e: Exception) {
+            throw BizException("soap:鎺ュ彛璁块棶寮傚父", e)
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
index 3628094..d7bd69b 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
@@ -69,6 +69,9 @@
     @Column(name = "NOI")
     var noi: Float? = null
 
+    @Column(name = "NO")
+    var no: Float? = null
+
     var velocity: Float? = null
 
     @Column(name = "wind_speed")
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRep.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRep.kt
index b41950d..718bdd4 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRep.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRep.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.uav.domain.repository
 
+import com.flightfeather.uav.common.exception.BizException
 import com.flightfeather.uav.domain.entity.*
 import com.flightfeather.uav.domain.mapper.RealTimeDataGridMapper
 import com.flightfeather.uav.domain.mapper.RealTimeDataGridMinMapper
@@ -9,6 +10,8 @@
 import com.github.pagehelper.PageHelper
 import org.springframework.stereotype.Repository
 import tk.mybatis.mapper.entity.Example
+import java.time.LocalDateTime
+import java.time.ZoneId
 import java.util.*
 
 /**
@@ -22,56 +25,106 @@
     private val realTimeDataGridMinMapper: RealTimeDataGridMinMapper,
 ) {
 
-    private fun getSecondDataExample(example: Example, deviceCode: String?, sTime: Date?, eTime: Date?) {
-        example.createCriteria().apply {
-            deviceCode?.let { andEqualTo("deviceCode", it) }
-            sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
-            eTime?.let { andLessThanOrEqualTo("dataTime", it) }
-        }
-        example.orderBy("dataTime").apply {
-            // 褰撹姹傛帴鍙d笉浼犻�掕捣濮嬫椂闂达紝榛樿鑾峰彇鏈�鏂扮殑鏁版嵁
-            if (sTime == null && eTime == null) {
-                desc()
-            }
-        }
-    }
+    private val delegate = RealTimeDataRepDelegate(realTimeDataVehicleMapper, realTimeDataUavMapper,
+        realTimeDataGridMapper, realTimeDataGridMinMapper)
 
     fun fetchData(
-        deviceCode: String,
-        sTime: Date?,
-        eTime: Date?,
-        type: Int? = 0,
+        deviceType: UWDeviceType?, deviceCode: String, sTime: Date? = null, eTime: Date? = null, type: Int? = 0,
+        page: Int? = null, perPage: Int? = null,
     ): List<BaseRealTimeData> {
-        var result = listOf<BaseRealTimeData>()
-        when (UWDeviceType.getType(deviceCode)) {
-            UWDeviceType.VEHICLE -> {
-                result = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
-                    getSecondDataExample(this, deviceCode, sTime, eTime)
-                })
-            }
-            UWDeviceType.UAV -> {
-                result = realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
-                    getSecondDataExample(this, deviceCode, sTime, eTime)
-                })
-            }
-            UWDeviceType.GRID -> {
-                // 缃戞牸鍖栫洃娴嬬绾у��
-                result = if (type == null || type == 0) {
-                    realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
-                        getSecondDataExample(this, deviceCode, sTime, eTime)
-                    })
-                }
-                // 缃戞牸鍖栫洃娴嬪垎閽熷��
-                else {
-                    realTimeDataGridMinMapper.selectByExample(Example(RealTimeDataGridMin::class.java).apply {
-                        getSecondDataExample(this, deviceCode, sTime, eTime)
-                    })
-                }
-            }
-            else -> Unit
+        if (page != null && perPage != null) {
+            var pageInfo = PageHelper.startPage<BaseRealTimeData>(page, perPage)
         }
-        return result
+        return delegate.selectByDeviceType(deviceType, type) { example ->
+            example.createCriteria().apply {
+                andEqualTo("deviceCode", deviceCode)
+                sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
+                eTime?.let { andLessThanOrEqualTo("dataTime", it) }
+            }
+            example.orderBy("dataTime").apply {
+                // 褰撹姹傛帴鍙d笉浼犻�掕捣濮嬫椂闂达紝榛樿鑾峰彇鏈�鏂扮殑鏁版嵁
+                if (sTime == null && eTime == null) {
+                    desc()
+                }
+            }
+        }
+
+
+//        var result = listOf<BaseRealTimeData>()
+//        when (deviceType) {
+//            UWDeviceType.VEHICLE -> {
+//                result = realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
+//                    getSecondDataExample(this, deviceCode, sTime, eTime)
+//                })
+//            }
+//            UWDeviceType.UAV -> {
+//                result = realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
+//                    getSecondDataExample(this, deviceCode, sTime, eTime)
+//                })
+//            }
+//            UWDeviceType.GRID -> {
+//                // 缃戞牸鍖栫洃娴嬬绾у��
+//                result = if (type == null || type == 0) {
+//                    realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
+//                        getSecondDataExample(this, deviceCode, sTime, eTime)
+//                    })
+//                }
+//                // 缃戞牸鍖栫洃娴嬪垎閽熷��
+//                else {
+//                    realTimeDataGridMinMapper.selectByExample(Example(RealTimeDataGridMin::class.java).apply {
+//                        getSecondDataExample(this, deviceCode, sTime, eTime)
+//                    })
+//                }
+//            }
+//            else -> Unit
+//        }
+//        return result
     }
 
-    fun fetchData(mission: Mission) = fetchData(mission.deviceCode, mission.startTime, mission.endTime)
+    fun fetchData(mission: Mission) =
+        fetchData(UWDeviceType.fromValue(mission.deviceType), mission.deviceCode, mission.startTime, mission.endTime)
+
+
+    fun saveData(deviceType: UWDeviceType?, data: List<BaseRealTimeData>, type: Int? = 0): Int {
+        return delegate.insertByDeviceType(deviceType, type, data)
+//        return when (deviceType) {
+//            UWDeviceType.UAV -> realTimeDataUavMapper.insertList(data as List<RealTimeDataUav>)
+//            UWDeviceType.VEHICLE -> realTimeDataVehicleMapper.insertList(data as List<RealTimeDataVehicle>)
+//            UWDeviceType.GRID -> realTimeDataGridMapper.insertList(data as List<RealTimeDataGrid>)
+//            UWDeviceType.BOAT -> 0
+//            else -> 0
+//        }
+    }
+
+    fun deleteData(mission: Mission, type: Int? = 0): Int {
+        if (mission.deviceCode == null || mission.startTime == null || mission.endTime == null) {
+            throw BizException("瑕佸垹闄ょ殑璧拌埅浠诲姟缂哄け璁惧缂栧彿鎴栭噰鏍锋椂闂磋寖鍥达紝鏃犳硶鍒犻櫎瀵瑰簲鐩戞祴鏁版嵁")
+        }
+        return deleteData(UWDeviceType.fromValue(mission.deviceType),
+            mission.deviceCode,
+            mission.startTime,
+            mission.endTime, type)
+    }
+
+    fun deleteData(deviceType: UWDeviceType?, deviceCode: String, sTime: Date?, eTime: Date?, type: Int? = 0): Int {
+        return delegate.deleteByDeviceType(deviceType, type) {
+            it.createCriteria().apply {
+                andEqualTo("deviceCode", deviceCode)
+                andGreaterThanOrEqualTo("dataTime", sTime)
+                andLessThanOrEqualTo("dataTime", eTime)
+            }
+        }
+    }
+
+    fun deleteData(
+        deviceType: UWDeviceType?, deviceCode: String, sTime: LocalDateTime?, eTime: LocalDateTime?, type: Int? = 0,
+    ): Int = deleteData(deviceType, deviceCode,
+        Date.from(sTime?.atZone(ZoneId.systemDefault())?.toInstant()),
+        Date.from(eTime?.atZone(ZoneId.systemDefault())?.toInstant()),
+        type
+    )
+
+    fun deleteData(deviceType: UWDeviceType?, data: List<BaseRealTimeData>, type: Int? = 0) {
+        delegate.deleteByDeviceType(deviceType, type, data)
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRepDelegate.kt b/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRepDelegate.kt
new file mode 100644
index 0000000..8ce8813
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/domain/repository/RealTimeDataRepDelegate.kt
@@ -0,0 +1,134 @@
+package com.flightfeather.uav.domain.repository
+
+import com.flightfeather.uav.domain.entity.*
+import com.flightfeather.uav.domain.mapper.RealTimeDataGridMapper
+import com.flightfeather.uav.domain.mapper.RealTimeDataGridMinMapper
+import com.flightfeather.uav.domain.mapper.RealTimeDataUavMapper
+import com.flightfeather.uav.domain.mapper.RealTimeDataVehicleMapper
+import com.flightfeather.uav.socket.eunm.UWDeviceType
+import tk.mybatis.mapper.entity.Example
+import java.util.*
+
+/**
+ * 瀹炴椂璧拌埅鏁版嵁鏁版嵁搴撶浉鍏虫搷浣滀唬鐞嗙被
+ * @date 2024/8/27
+ * @author feiyu02
+ */
+class RealTimeDataRepDelegate(
+    private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
+    private val realTimeDataUavMapper: RealTimeDataUavMapper,
+    private val realTimeDataGridMapper: RealTimeDataGridMapper,
+    private val realTimeDataGridMinMapper: RealTimeDataGridMinMapper,
+) {
+    /**
+     * 鏍规嵁璁惧绫诲瀷鎵ц涓嶅悓鏁版嵁搴撴搷浣滄楠�
+     * 鍚勭被璁惧鐨勭洃娴嬫暟鎹櫧鍒嗕笉鍚屾暟鎹〃瀛樺偍锛屼絾鏁版嵁琛ㄧ粨鏋勭浉鍚�
+     * @param deviceType 璁惧绫诲瀷
+     * @param type 鏁版嵁缁熻鍛ㄦ湡锛�0锛氱绾у�硷紱1锛氬垎閽熷��
+     * @param callbacks 閽堝涓嶅悓绫诲瀷鐨勮澶囧搴旂殑涓嶅悓鍥炶皟鍑芥暟
+     */
+    private fun <T> byDeviceType(deviceType: UWDeviceType?, type: Int? = 0, vararg callbacks: () -> T): T? {
+        return when (deviceType) {
+            UWDeviceType.VEHICLE -> {
+                if (callbacks.isNotEmpty()) callbacks[0].invoke() else null
+            }
+            UWDeviceType.UAV -> {
+                if (callbacks.size > 1) callbacks[1].invoke() else null
+            }
+            UWDeviceType.GRID -> {
+                // 缃戞牸鍖栫洃娴嬬绾у��
+                if (type == null || type == 0) {
+                    if (callbacks.size > 2) callbacks[2].invoke() else null
+                }
+                // 缃戞牸鍖栫洃娴嬪垎閽熷��
+                else {
+                    if (callbacks.size > 3) callbacks[3].invoke() else null
+                }
+            }
+            else -> null
+        }
+    }
+
+    /**
+     * 缁熶竴鐨剆elect鏂规硶
+     * @param deviceType 璁惧绫诲瀷
+     * @param type 鏁版嵁缁熻鍛ㄦ湡锛�0锛氱绾у�硷紱1锛氬垎閽熷��
+     * @param condition 鏌ヨ鏉′欢
+     */
+    fun selectByDeviceType(
+        deviceType: UWDeviceType?, type: Int? = 0,
+        condition: (example: Example) -> Unit,
+    ): List<BaseRealTimeData> {
+        return byDeviceType(deviceType, type, {
+            realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply { condition(this) })
+        }, {
+            realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply { condition(this) })
+        }, {
+            realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply { condition(this) })
+        }, {
+            realTimeDataGridMinMapper.selectByExample(Example(RealTimeDataGridMin::class.java).apply { condition(this) })
+        }) ?: emptyList()
+    }
+
+    /**
+     * 缁熶竴鐨刬nsert鏂规硶
+     * @param deviceType 璁惧绫诲瀷
+     * @param type 鏁版嵁缁熻鍛ㄦ湡锛�0锛氱绾у�硷紱1锛氬垎閽熷��
+     * @param data 鏁版嵁
+     */
+    fun insertByDeviceType(deviceType: UWDeviceType?, type: Int? = 0, data: List<BaseRealTimeData>): Int {
+        return byDeviceType(deviceType, type, {
+            realTimeDataVehicleMapper.insertList(data as List<RealTimeDataVehicle>)
+        }, {
+            realTimeDataUavMapper.insertList(data as List<RealTimeDataUav>)
+        }, {
+            realTimeDataGridMapper.insertList(data as List<RealTimeDataGrid>)
+        }, {
+            realTimeDataGridMinMapper.insertList(data as List<RealTimeDataGridMin>)
+        }) ?: 0
+    }
+
+    /**
+     * 缁熶竴鐨刣elete鏂规硶
+     * @param deviceType 璁惧绫诲瀷
+     * @param type 鏁版嵁缁熻鍛ㄦ湡锛�0锛氱绾у�硷紱1锛氬垎閽熷��
+     * @param data 鏁版嵁
+     */
+    fun deleteByDeviceType(deviceType: UWDeviceType?, type: Int? = 0, data: List<BaseRealTimeData>): Int {
+        return byDeviceType(deviceType, type, {
+            var count = 0
+            data.forEach { count += realTimeDataVehicleMapper.delete(it as RealTimeDataVehicle) }
+            count
+        }, {
+            var count = 0
+            data.forEach { count += realTimeDataUavMapper.delete(it as RealTimeDataUav) }
+            count
+        }, {
+            var count = 0
+            data.forEach { count += realTimeDataGridMapper.delete(it as RealTimeDataGrid) }
+            count
+        }, {
+            var count = 0
+            data.forEach { count += realTimeDataGridMinMapper.delete(it as RealTimeDataGridMin) }
+            count
+        }) ?: 0
+    }
+
+    /**
+     * 缁熶竴鐨刣elete鏂规硶
+     * @param deviceType 璁惧绫诲瀷
+     * @param type 鏁版嵁缁熻鍛ㄦ湡锛�0锛氱绾у�硷紱1锛氬垎閽熷��
+     * @param condition 鏌ヨ鏉′欢
+     */
+    fun deleteByDeviceType(deviceType: UWDeviceType?, type: Int? = 0, condition: (example: Example) -> Unit,): Int {
+        return byDeviceType(deviceType, type, {
+            realTimeDataVehicleMapper.deleteByExample(Example(RealTimeDataVehicle::class.java).apply { condition(this) })
+        }, {
+            realTimeDataUavMapper.deleteByExample(Example(RealTimeDataUav::class.java).apply { condition(this) })
+        }, {
+            realTimeDataGridMapper.deleteByExample(Example(RealTimeDataGrid::class.java).apply { condition(this) })
+        }, {
+            realTimeDataGridMinMapper.deleteByExample(Example(RealTimeDataGridMin::class.java).apply { condition(this) })
+        }) ?: 0
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ThirdPartyLabel.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ThirdPartyLabel.kt
new file mode 100644
index 0000000..9618326
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/eunm/ThirdPartyLabel.kt
@@ -0,0 +1,10 @@
+package com.flightfeather.uav.lightshare.eunm
+
+/**
+ * 绗笁鏂规暟鎹帴鍙f爣璇�
+ * @date 2024/8/26
+ * @author feiyu02
+ */
+enum class ThirdPartyLabel(val value: String) {
+    ShenXin("shenxin")
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/ThirdPartyService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/ThirdPartyService.kt
new file mode 100644
index 0000000..58a8b7d
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/ThirdPartyService.kt
@@ -0,0 +1,30 @@
+package com.flightfeather.uav.lightshare.service
+
+import com.flightfeather.uav.socket.eunm.UWDeviceType
+import java.time.LocalDateTime
+
+/**
+ *
+ * @date 2024/8/26
+ * @author feiyu02
+ */
+interface ThirdPartyService {
+
+    /**
+     * 鑾峰彇璧拌埅浠诲姟瀵瑰簲鐨勮寖鍥村唴鐨勬暟鎹�
+     * @param label 鎺ュ彛鏍囩锛岃〃鏄庢槸鍝釜绗笁鏂规暟鎹帴鍙�
+     * @param missionCode 浠诲姟缂栧彿
+     */
+    fun fetchMissionData(label: String, missionCode: String): Boolean
+
+    /**
+     * 鑾峰彇璁惧鏈�鏂版暟鎹�
+     * @param label 鎺ュ彛鏍囩锛岃〃鏄庢槸鍝釜绗笁鏂规暟鎹帴鍙�
+     * @param type 璁惧绫诲瀷
+     * @param deviceCode 璁惧缂栧彿
+     * @param startTime 鏁版嵁璧峰鏃堕棿
+     */
+    fun fetchLatestData(
+        label: String, type: UWDeviceType, deviceCode: String, startTime: LocalDateTime?, endTime: LocalDateTime?,
+    ): Boolean
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
index a7a0458..a1b05e1 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImpl.kt
@@ -13,6 +13,8 @@
 import com.github.pagehelper.PageHelper
 import org.springframework.stereotype.Service
 import tk.mybatis.mapper.entity.Example
+import java.io.File
+import java.util.*
 import javax.servlet.http.HttpServletResponse
 
 @Service
@@ -35,6 +37,7 @@
         return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages),data = result)
     }
 
+    @Synchronized
     override fun createMission(mission: Mission): BaseResponse<Boolean> {
         missionMapper.selectByPrimaryKey(mission.missionCode)?.run {
             return BaseResponse(false, "浠诲姟缂栧彿宸插瓨鍦�")
@@ -61,6 +64,15 @@
     }
 
     override fun getReport(missionCode: String, response: HttpServletResponse) {
-        missionReport.execute(missionCode, FactorFilter.default())
+        val path = missionReport.execute(missionCode, FactorFilter.default())
+        val pathArr = path.split("/")
+        val file = File(path)
+        if (file.exists()) {
+            response.contentType = "application/vnd.ms-excel;charset=UTF-8"
+            val name = Base64.getEncoder().encodeToString(pathArr.last().toByteArray())
+            response.setHeader("fileName", name)
+            response.outputStream.write(file.readBytes())
+        }
+        return
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ThirdPartyServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ThirdPartyServiceImpl.kt
new file mode 100644
index 0000000..a2cf978
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ThirdPartyServiceImpl.kt
@@ -0,0 +1,40 @@
+package com.flightfeather.uav.lightshare.service.impl
+
+import com.flightfeather.uav.biz.datafetch.ShenXinDataFetch
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.lightshare.eunm.ThirdPartyLabel
+import com.flightfeather.uav.lightshare.service.ThirdPartyService
+import com.flightfeather.uav.socket.eunm.UWDeviceType
+import org.springframework.stereotype.Service
+import java.time.LocalDateTime
+
+/**
+ *
+ * @date 2024/8/26
+ * @author feiyu02
+ */
+@Service
+class ThirdPartyServiceImpl(private val shenXinDataFetch: ShenXinDataFetch) : ThirdPartyService {
+
+    override fun fetchMissionData(label: String, missionCode: String): Boolean {
+        when (label) {
+            ThirdPartyLabel.ShenXin.value -> {
+                shenXinDataFetch.fetchMissionData(missionCode)
+                return true
+            }
+            else -> throw BizException("绗笁鏂规帴鍙f爣璇嗕笉瀛樺湪")
+        }
+    }
+
+    override fun fetchLatestData(
+        label: String, type: UWDeviceType, deviceCode: String, startTime: LocalDateTime?, endTime: LocalDateTime?,
+    ): Boolean {
+        when (label) {
+            ThirdPartyLabel.ShenXin.value -> {
+                shenXinDataFetch.fetchLatestData(type, deviceCode, startTime, endTime)
+                return true
+            }
+            else -> throw BizException("绗笁鏂规帴鍙f爣璇嗕笉瀛樺湪")
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/web/ThirdPartyController.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/web/ThirdPartyController.kt
new file mode 100644
index 0000000..80b7408
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/web/ThirdPartyController.kt
@@ -0,0 +1,45 @@
+package com.flightfeather.uav.lightshare.web
+
+import com.fasterxml.jackson.annotation.JsonFormat
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.lightshare.service.ThirdPartyService
+import com.flightfeather.uav.socket.eunm.UWDeviceType
+import io.swagger.annotations.Api
+import io.swagger.annotations.ApiOperation
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RequestParam
+import org.springframework.web.bind.annotation.RestController
+import java.time.LocalDateTime
+
+/**
+ * 绗笁鏂瑰鎺ョ浉鍏虫帴鍙o紝鍖呭惈
+ * 1. 鐢虫鐜繚璧拌埅鏁版嵁鐩稿叧鎺ュ彛
+ * @date 2024/8/26
+ * @author feiyu02
+ */
+@Api(tags = ["绗笁鏂瑰鎺ョ浉鍏矨PI鎺ュ彛"])
+@RestController
+@RequestMapping("air/thirdParty")
+class ThirdPartyController(private val thirdPartyService: ThirdPartyService) {
+
+    @ApiOperation(value = "鏍规嵁浠诲姟淇℃伅鑾峰彇瀵瑰簲鑼冨洿鍐呯殑绗笁鏂硅蛋鑸暟鎹�")
+    @GetMapping("/data/fetch/mission")
+    fun fetchMissionData(
+        @RequestParam label: String,
+        @RequestParam missionCode: String,
+    ) = resPack { thirdPartyService.fetchMissionData(label, missionCode) }
+
+    @ApiOperation(value = "鑾峰彇瀹炴椂鏈�鏂扮殑绗笁鏂硅蛋鑸暟鎹�")
+    @GetMapping("/data/fetch/latest")
+    fun fetchLatestData(
+        @RequestParam label: String,
+        @RequestParam deviceType: String,
+        @RequestParam deviceCode: String,
+        @RequestParam(required = false) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") startTime: LocalDateTime?,
+        @RequestParam(required = false) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") endTime: LocalDateTime?,
+    ) = resPack {
+        val type = UWDeviceType.fromValue(deviceType) ?: throw BizException("璁惧绫诲瀷涓嶅瓨鍦�")
+        thirdPartyService.fetchLatestData(label, type, deviceCode, startTime, endTime)
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/scheduler/ScheduleService.kt b/src/main/kotlin/com/flightfeather/uav/scheduler/ScheduleService.kt
new file mode 100644
index 0000000..c9f344d
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/scheduler/ScheduleService.kt
@@ -0,0 +1,65 @@
+package com.flightfeather.uav.scheduler
+
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.springframework.beans.factory.annotation.Value
+import org.springframework.scheduling.annotation.Async
+import org.springframework.scheduling.annotation.Scheduled
+import org.springframework.stereotype.Component
+import java.time.LocalDate
+import java.time.LocalDateTime
+
+/**
+ * 瀹氭椂浠诲姟璋冨害
+ * 涓�涓猚ron琛ㄨ揪寮忔湁鑷冲皯6涓紙涔熷彲鑳�7涓級鏈夌┖鏍煎垎闅旂殑鏃堕棿鍏冪礌銆傛寜椤哄簭渚濇涓猴細
+ * 绉掞紙0~59锛�
+ * 鍒嗛挓锛�0~59锛�
+ * 灏忔椂锛�0~23锛�
+ * 澶╋紙1~31锛�
+ * 鏈堬紙1~12锛�
+ * 鏄熸湡锛�1~7 1=SUN 鎴� SUN锛孧ON锛孴UE锛學ED锛孴HU锛孎RI锛孲AT锛�
+ */
+@Component
+class ScheduleService(
+    @Value("\${mode}")
+    var mode: String,
+) {
+    val logger: Logger = LoggerFactory.getLogger(ScheduleService::class.java)
+
+//    @Async
+//    @Scheduled(cron = "0 0 0 * * *")
+    fun eachDay() {
+        if (mode != "pro") return
+        logger.info("=====>>>>>姣忔棩浠诲姟鎵ц {}", System.currentTimeMillis())
+
+        logger.info("=====>>>>>姣忔棩浠诲姟缁撴潫 {}", System.currentTimeMillis())
+    }
+
+//    @Async
+//    @Scheduled(cron = "0 0 0 * * MON")
+    fun eachWeek() {
+        if (mode != "pro") return
+        logger.info("=====>>>>>姣忓懆浠诲姟鎵ц {}", System.currentTimeMillis())
+        // 鎵ц涓婂懆鐨勮嚜璇勪换鍔�
+
+        logger.info("=====>>>>>姣忓懆浠诲姟缁撴潫 {}", System.currentTimeMillis())
+    }
+
+//    @Async
+//    @Scheduled(cron = "0 0 0 1 * *")
+    fun eachStartOfMonth() {
+        if (mode != "pro") return
+        logger.info("=====>>>>>姣忔湀1鍙蜂换鍔℃墽琛� {}", System.currentTimeMillis())
+
+        logger.info("=====>>>>>姣忔湀1鍙蜂换鍔$粨鏉� {}", System.currentTimeMillis())
+    }
+
+//    @Async
+//    @Scheduled(cron = "0 0 0 2 * *")
+    fun eachMonth() {
+        if (mode != "pro") return
+        logger.info("=====>>>>>姣忔湀2鍙蜂换鍔℃墽琛� {}", System.currentTimeMillis())
+
+        logger.info("=====>>>>>姣忔湀2鍙蜂换鍔$粨鏉� {}", System.currentTimeMillis())
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt b/src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt
index c354375..67cf06f 100644
--- a/src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt
+++ b/src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt
@@ -13,7 +13,9 @@
         /**
          * 鏍规嵁璁惧缂栧彿鑾峰彇璁惧绫诲瀷
          */
-        fun getType(deviceCode: String?): UWDeviceType? = when (deviceCode?.substring(0, 2)) {
+        fun getType(deviceCode: String?): UWDeviceType? = fromValue(deviceCode?.substring(0, 2))
+
+        fun fromValue(value: String?): UWDeviceType? = when (value) {
             UAV.value -> UAV
             VEHICLE.value -> VEHICLE
             BOAT.value -> BOAT
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 8505ffc..0d907a9 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -12,4 +12,5 @@
         enabled: true
 
 imgPath: target/
-filePath: target/
\ No newline at end of file
+filePath: target/
+mode: dev
\ No newline at end of file
diff --git a/src/main/resources/application-pro.yml b/src/main/resources/application-pro.yml
index 5236afe..a01fab2 100644
--- a/src/main/resources/application-pro.yml
+++ b/src/main/resources/application-pro.yml
@@ -1,14 +1,14 @@
 spring:
   datasource:
     #    绾夸笂鏈嶅姟鍣� 47
-    url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
-    username: dronemonitor
-    password: dronemonitor_hackxrnomxm
-
-    #    绾夸笂鏈嶅姟鍣� 114
 #    url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
 #    username: dronemonitor
 #    password: dronemonitor_hackxrnomxm
+
+    #    绾夸笂鏈嶅姟鍣� 114
+    url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
+    username: dronemonitor
+    password: dronemonitor_hackxrnomxm
 
 springfox:
   documentation:
@@ -17,4 +17,5 @@
         enabled: false
 
 imgPath: D:/02product/10underway/images/
-filePath: D:/02product/10underway/files/
\ No newline at end of file
+filePath: D:/02product/10underway/files/
+mode: pro
\ No newline at end of file
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml
index 243bc45..75ca738 100644
--- a/src/main/resources/application-test.yml
+++ b/src/main/resources/application-test.yml
@@ -7,13 +7,13 @@
     #    password: cn.FLIGHTFEATHER
 
     #   杩滅▼鏈嶅姟鍣�
-    url: jdbc:mysql://47.100.191.150:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
-    username: remoteU1
-    password: eSoF8DnzfGTlhAjE
-
-#    url: jdbc:mysql://114.215.109.124:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
+#    url: jdbc:mysql://47.100.191.150:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
 #    username: remoteU1
-#    password: feiyu2024
+#    password: eSoF8DnzfGTlhAjE
+
+    url: jdbc:mysql://114.215.109.124:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
+    username: remoteU1
+    password: feiyu2024
 
 springfox:
   documentation:
@@ -22,4 +22,5 @@
         enabled: true
 
 imgPath: C:/02product/10underway/images/
-filePath: C:/02product/10underway/files/
\ No newline at end of file
+filePath: C:/02product/10underway/files/
+mode: test
\ No newline at end of file
diff --git a/src/main/resources/generator/generatorConfig.xml b/src/main/resources/generator/generatorConfig.xml
index e292e5a..4bb181c 100644
--- a/src/main/resources/generator/generatorConfig.xml
+++ b/src/main/resources/generator/generatorConfig.xml
@@ -54,13 +54,13 @@
 <!--        <table tableName="co_assessment" domainObjectName="Assessment" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="real_time_data_grid" domainObjectName="RealTimeDataGrid" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="real_time_data_uav" domainObjectName="RealTimeDataUav" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-<!--        <table tableName="real_time_data_vehicle" domainObjectName="RealTimeDataVehicle" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+        <table tableName="real_time_data_vehicle" domainObjectName="RealTimeDataVehicle" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
 <!--        <table tableName="device_info" domainObjectName="DeviceInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="factor_calibration" domainObjectName="FactorCalibration" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="real_time_data_grid_min" domainObjectName="RealTimeDataGridMin" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="real_time_data_grid_opt" domainObjectName="RealTimeDataGridOpt" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="scene_info" domainObjectName="SceneInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-        <table tableName="segment_info" domainObjectName="SegmentInfo" enableCountByExample="false"
-               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
+<!--        <table tableName="segment_info" domainObjectName="SegmentInfo" enableCountByExample="false"-->
+<!--               enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
     </context>
 </generatorConfiguration>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RealTimeDataGridMapper.xml b/src/main/resources/mapper/RealTimeDataGridMapper.xml
index 955924d..2b24ce4 100644
--- a/src/main/resources/mapper/RealTimeDataGridMapper.xml
+++ b/src/main/resources/mapper/RealTimeDataGridMapper.xml
@@ -23,6 +23,7 @@
     <result column="humidity" jdbcType="REAL" property="humidity" />
     <result column="VOC" jdbcType="REAL" property="voc" />
     <result column="NOI" jdbcType="REAL" property="noi" />
+    <result column="NO" jdbcType="REAL" property="no" />
     <result column="velocity" jdbcType="REAL" property="velocity" />
     <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
     <result column="wind_direction" jdbcType="REAL" property="windDirection" />
@@ -33,7 +34,7 @@
       WARNING - @mbg.generated
     -->
     id, device_code, latitude, longitude, altitude, data_time, create_time, NO2, CO, 
-    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, velocity, wind_speed, 
+    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, NO, velocity, wind_speed,
     wind_directon, height
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RealTimeDataGridMinMapper.xml b/src/main/resources/mapper/RealTimeDataGridMinMapper.xml
index 77bb6e2..242676a 100644
--- a/src/main/resources/mapper/RealTimeDataGridMinMapper.xml
+++ b/src/main/resources/mapper/RealTimeDataGridMinMapper.xml
@@ -23,6 +23,7 @@
     <result column="humidity" jdbcType="REAL" property="humidity" />
     <result column="VOC" jdbcType="REAL" property="voc" />
     <result column="NOI" jdbcType="REAL" property="noi" />
+    <result column="NO" jdbcType="REAL" property="no" />
     <result column="velocity" jdbcType="REAL" property="velocity" />
     <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
     <result column="wind_direction" jdbcType="REAL" property="windDirection" />
@@ -33,7 +34,7 @@
       WARNING - @mbg.generated
     -->
     id, device_code, latitude, longitude, altitude, data_time, create_time, NO2, CO, 
-    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, velocity, wind_speed, 
+    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, NO, velocity, wind_speed,
     wind_direction, height
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RealTimeDataGridOptMapper.xml b/src/main/resources/mapper/RealTimeDataGridOptMapper.xml
index 88eec71..c449443 100644
--- a/src/main/resources/mapper/RealTimeDataGridOptMapper.xml
+++ b/src/main/resources/mapper/RealTimeDataGridOptMapper.xml
@@ -23,6 +23,7 @@
     <result column="humidity" jdbcType="REAL" property="humidity" />
     <result column="VOC" jdbcType="REAL" property="voc" />
     <result column="NOI" jdbcType="REAL" property="noi" />
+    <result column="NO" jdbcType="REAL" property="no" />
     <result column="velocity" jdbcType="REAL" property="velocity" />
     <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
     <result column="wind_direction" jdbcType="REAL" property="windDirection" />
@@ -33,7 +34,7 @@
       WARNING - @mbg.generated
     -->
     id, device_code, latitude, longitude, altitude, data_time, create_time, NO2, CO, 
-    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, velocity, wind_speed, 
+    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, NO, velocity, wind_speed,
     wind_direction, height
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RealTimeDataUavMapper.xml b/src/main/resources/mapper/RealTimeDataUavMapper.xml
index 28a023f..99f53a9 100644
--- a/src/main/resources/mapper/RealTimeDataUavMapper.xml
+++ b/src/main/resources/mapper/RealTimeDataUavMapper.xml
@@ -23,6 +23,7 @@
     <result column="humidity" jdbcType="REAL" property="humidity" />
     <result column="VOC" jdbcType="REAL" property="voc" />
     <result column="NOI" jdbcType="REAL" property="noi" />
+    <result column="NO" jdbcType="REAL" property="no" />
     <result column="velocity" jdbcType="REAL" property="velocity" />
     <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
     <result column="wind_direction" jdbcType="REAL" property="windDirection" />
@@ -33,7 +34,7 @@
       WARNING - @mbg.generated
     -->
     id, device_code, latitude, longitude, altitude, data_time, create_time, NO2, CO, 
-    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, velocity, wind_speed, 
+    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, NO, velocity, wind_speed,
     wind_directon, height
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/RealTimeDataVehicleMapper.xml b/src/main/resources/mapper/RealTimeDataVehicleMapper.xml
index 18dfc17..3f3c8e0 100644
--- a/src/main/resources/mapper/RealTimeDataVehicleMapper.xml
+++ b/src/main/resources/mapper/RealTimeDataVehicleMapper.xml
@@ -23,6 +23,7 @@
     <result column="humidity" jdbcType="REAL" property="humidity" />
     <result column="VOC" jdbcType="REAL" property="voc" />
     <result column="NOI" jdbcType="REAL" property="noi" />
+    <result column="NO" jdbcType="REAL" property="no" />
     <result column="velocity" jdbcType="REAL" property="velocity" />
     <result column="wind_speed" jdbcType="REAL" property="windSpeed" />
     <result column="wind_direction" jdbcType="REAL" property="windDirection" />
@@ -33,7 +34,7 @@
       WARNING - @mbg.generated
     -->
     id, device_code, latitude, longitude, altitude, data_time, create_time, NO2, CO, 
-    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, velocity, wind_speed, 
-    wind_directon, height
+    H2S, SO2, O3, PM25, PM10, temperature, humidity, VOC, NOI, NO, velocity, wind_speed, 
+    wind_direction, height
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/common/net/ShenXinServiceTest.kt b/src/test/kotlin/com/flightfeather/uav/common/net/ShenXinServiceTest.kt
new file mode 100644
index 0000000..b57805a
--- /dev/null
+++ b/src/test/kotlin/com/flightfeather/uav/common/net/ShenXinServiceTest.kt
@@ -0,0 +1,27 @@
+package com.flightfeather.uav.common.net
+
+import com.flightfeather.uav.domain.entity.Mission
+import org.junit.Assert.*
+import org.junit.Test
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.*
+
+class ShenXinServiceTest {
+
+    @Test
+    fun fetchData() {
+        val mission = Mission().apply {
+            missionCode = "SHJA-20240813"
+            deviceType = "0a"
+            deviceCode = "TX105"
+            startTime = Date.from(LocalDateTime.of(2024, 8, 13, 11, 30, 0, 0).atZone(ZoneId.systemDefault())
+                .toInstant())
+            endTime = Date.from(LocalDateTime.of(2024, 8, 13, 17, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant())
+            districtName = "闈欏畨鍖�"
+        }
+        val date = LocalDateTime.of(2024, 8, 13, 15, 43, 0, 0)
+        val res = ShenXinService.fetchData(mission, date)
+        println(res)
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
index bf2247e..f7f4603 100644
--- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
@@ -24,6 +24,7 @@
 
     @Test
     fun getReport() {
-        missionReport.execute("SH-CN-20240514", FactorFilter.default())
+        missionReport.execute("SH-CN-20240723-01", FactorFilter.default())
+        missionReport.execute("SH-CN-20240723-02", FactorFilter.default())
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3