From eb3dd00b0b7fcda477229d518d250f9c842b790b Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 21 十月 2025 17:45:44 +0800
Subject: [PATCH] 2025.10.21 1. 走航季度报告相关数据计算逻辑调整
---
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt | 243 +++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 216 insertions(+), 27 deletions(-)
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
index 0336692..771ff89 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
@@ -1,46 +1,69 @@
package com.flightfeather.uav.lightshare.service.impl
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.common.scaleMap
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.common.utils.ExcelUtil
import com.flightfeather.uav.common.utils.FileExchange
-import com.flightfeather.uav.common.utils.GsonUtils
-import com.flightfeather.uav.dataprocess.AverageUtil
+import com.flightfeather.uav.biz.dataprocess.AverageUtil
import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.domain.mapper.*
+import com.flightfeather.uav.domain.repository.MissionRep
+import com.flightfeather.uav.domain.repository.RealTimeDataRep
+import com.flightfeather.uav.domain.repository.SegmentInfoRep
import com.flightfeather.uav.lightshare.bean.*
import com.flightfeather.uav.lightshare.service.RealTimeDataService
import com.flightfeather.uav.model.epw.EPWDataPrep
-import com.flightfeather.uav.repository.AirDataRepository
-import com.flightfeather.uav.socket.bean.AirData
+import com.flightfeather.uav.domain.repository.AirDataRep
import com.flightfeather.uav.socket.eunm.UWDeviceType
import com.github.pagehelper.PageHelper
import org.apache.poi.xssf.streaming.SXSSFWorkbook
+import org.springframework.beans.BeanUtils
+import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import tk.mybatis.mapper.entity.Example
import java.io.ByteArrayInputStream
+import java.io.File
import java.text.SimpleDateFormat
import java.time.LocalDateTime
+import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.*
import javax.servlet.http.HttpServletResponse
-import javax.swing.text.DateFormatter
+import kotlin.math.sqrt
@Service
class RealTimeDataServiceImpl(
private val realTimeDataMapper: RealTimeDataMapper,
- private val airDataRepository: AirDataRepository,
+ private val airDataRep: AirDataRep,
private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
private val realTimeDataUavMapper: RealTimeDataUavMapper,
private val realTimeDataGridMapper: RealTimeDataGridMapper,
- private val realTimeDataGridMinMapper: RealTimeDataGridMinMapper
+ private val realTimeDataGridOptMapper: RealTimeDataGridOptMapper,
+ private val realTimeDataGridMinMapper: RealTimeDataGridMinMapper,
+ private val missionMapper: MissionMapper,
+ private val missionRep: MissionRep,
+ private val realTimeDataRep: RealTimeDataRep,
+ private val segmentInfoRep: SegmentInfoRep,
) : RealTimeDataService {
+
+ @Value("\${filePath}")
+ lateinit var filePath: String
private var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
private var dateFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
private val fileExchange = FileExchange()
- override fun getSecondData(deviceCode: String?, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
+ override fun getSecondData(
+ deviceType: String?,
+ deviceCode: String?,
+ startTime: String?,
+ endTime: String?,
+ type: Int?,
+ page: Int?,
+ perPage: Int?,
+ ): BaseResponse<List<DataVo>> {
val _perPage = perPage ?: 60
val _page = page ?: 1
val sTime = startTime?.let { dateFormatter.parse(it) }
@@ -50,7 +73,12 @@
var pages = 0
val result = mutableListOf<DataVo>()
- when (UWDeviceType.getType(deviceCode)) {
+ val _deviceType = if (deviceType != null) {
+ UWDeviceType.fromValue(deviceType)
+ } else {
+ UWDeviceType.getType(deviceCode)
+ }
+ when (_deviceType) {
UWDeviceType.VEHICLE -> {
val pageInfo = PageHelper.startPage<RealTimeDataVehicle>(_page, _perPage)
realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
@@ -68,12 +96,24 @@
pages = pageInfo.pages
}
UWDeviceType.GRID -> {
- val pageInfo = PageHelper.startPage<RealTimeDataGrid>(_page, _perPage)
- realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
- getSecondDataExample(this, deviceCode, sTime, eTime)
- }).forEach { result.add(it.toDataVo()) }
- pageNum = pageInfo.pageNum
- pages = pageInfo.pages
+ // 缃戞牸鍖栫洃娴嬬绾у��
+ if (type == null || type == 0) {
+ val pageInfo = PageHelper.startPage<RealTimeDataGrid>(_page, _perPage)
+ realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
+ getSecondDataExample(this, deviceCode, sTime, eTime)
+ }).forEach { result.add(it.toDataVo()) }
+ pageNum = pageInfo.pageNum
+ pages = pageInfo.pages
+ }
+ // 缃戞牸鍖栫洃娴嬪垎閽熷��
+ else if (type == 1) {
+ val pageInfo = PageHelper.startPage<RealTimeDataGridMin>(_page, _perPage)
+ realTimeDataGridMinMapper.selectByExample(Example(RealTimeDataGridMin::class.java).apply {
+ getSecondDataExample(this, deviceCode, sTime, eTime)
+ }).forEach { result.add(it.toDataVo()) }
+ pageNum = pageInfo.pageNum
+ pages = pageInfo.pages
+ }
}
else -> {
// 浠庡師濮嬫暟鎹〃涓幏鍙栨暟鎹�
@@ -111,7 +151,12 @@
}
}
- override fun getNextData(deviceCode: String, updateTime: String, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
+ override fun getNextData(
+ deviceCode: String,
+ updateTime: String,
+ page: Int?,
+ perPage: Int?,
+ ): BaseResponse<List<DataVo>> {
val _perPage = perPage ?: 60
val _page = page ?: 1
val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
@@ -148,12 +193,83 @@
example.orderBy("dataTime")
}
+ override fun getSegmentData(missionCode: String): List<List<DataVo>> {
+ val mission = missionRep.findOne(missionCode) ?: throw BizException("浠诲姟涓嶅瓨鍦�")
+ val data = realTimeDataRep.fetchData(mission)
+
+ val segInfo = SegmentInfo().apply { this.missionCode = missionCode }
+ val segList = segmentInfoRep.findList(segInfo)
+// return TrackSegment.segmentWithRoad(data).map { it.map { b -> b.toDataVo() } }
+ val res = mutableListOf<MutableList<DataVo>>()
+ res.add(mutableListOf())
+ var index = 0
+ data.forEach {
+ if (it.dataTime == null) return@forEach
+ if (it.dataTime!! <= segList[index]?.endTime) {
+ res[index].add(it.toDataVo())
+ if (it.dataTime!! == segList[index]?.endTime) {
+ index++
+ res.add(mutableListOf())
+ }
+ }
+ }
+ // 绉婚櫎鏈�鍚庝竴涓┖闆嗗悎
+ if (res.last().isEmpty()) res.removeLast()
+ return res
+ }
+
override fun importData(file: MultipartFile): BaseResponse<DataImportResult> {
val f = ByteArrayInputStream(file.bytes)
fileExchange.exchangeBoatData("0c0000000001", f).forEach {
realTimeDataMapper.insert(it)
}
- return BaseResponse(true, data = DataImportResult(""))
+ return BaseResponse(true, data = DataImportResult("鎴愬姛"))
+ }
+
+ override fun importJinanData(code: String, file: MultipartFile): DataImportResult {
+ val f = ByteArrayInputStream(file.bytes)
+// val result = fileExchange.exchangeVehicleData(code, f)
+ val result = fileExchange.exchangeJinanData(code, f)
+ if (result.isNotEmpty()) {
+ val first = result.first()
+ val t = DateUtil.instance.dateToString(first.dataTime, DateUtil.DateStyle.YYYY_MM_DD)
+ val last = result.last()
+ val mission = Mission().apply {
+ val tag = code.substring(0, 2) + "-" + code.substring(code.length - 2, code.length)
+ missionCode = "SH-JA-${tag}-${t}"
+ deviceType = UWDeviceType.getType(code)?.value
+ deviceCode = code
+ }
+ missionMapper.selectOne(mission)?.run { throw BizException("璇ヨ澶囪鏃舵浠诲姟宸插瓨鍦紝鏃犳硶閲嶅瀵煎叆") }
+ mission.apply {
+ startTime = first.dataTime
+ endTime = last.dataTime
+ }
+ missionMapper.insert(mission)
+ realTimeDataVehicleMapper.insertList(result)
+ }
+ return DataImportResult("鎴愬姛")
+ }
+
+ override fun downloadTemplate(response: HttpServletResponse): Boolean {
+ val fileName = "JinAn-Template.xlsx"
+ val path = (Thread.currentThread().contextClassLoader?.getResource("/")?.path
+ ?: "src/main/resources") + "/templates/" + fileName
+ val file = File(path)
+ if (file.exists()) {
+ val fName = Base64.getEncoder().encodeToString(fileName.toByteArray())
+ response.apply {
+ setHeader("Content-Disposition", "attachment;filename=$fName")
+ setHeader("fileName", fName)
+ addHeader("Access-Control-Expose-Headers", "fileName")
+ contentType = "application/vnd.ms-excel;charset=UTF-8"
+ setHeader("Pragma", "no-cache")
+ setHeader("Cache-Control", "no-cache")
+ setDateHeader("Expires", 0)
+ }
+ response.outputStream.write(file.readBytes())
+ }
+ return true
}
override fun outToWorkbook(deviceCode: String, startTime: String, endTime: String): SXSSFWorkbook {
@@ -175,13 +291,19 @@
})
if (r.isNotEmpty()) {
val heads = if (page == 1) {
- println("[${DateUtil.instance.dateToString(Date(), DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)}] totalPage: ${pageInfo.pages}")
+ println("[${
+ DateUtil.instance.dateToString(Date(),
+ DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)
+ }] totalPage: ${pageInfo.pages}")
getTableTitle(r[0])
} else {
emptyList()
}
val contents = getTableContents(r)
- print("[${DateUtil.instance.dateToString(Date(), DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)}] currentPage: ${pageInfo.pageNum}......")
+ print("[${
+ DateUtil.instance.dateToString(Date(),
+ DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)
+ }] currentPage: ${pageInfo.pageNum}......")
rowIndex = ExcelUtil.write(heads, contents, workbook, row = rowIndex)
println("output done")
}
@@ -191,7 +313,12 @@
return workbook
}
- override fun outToExcel(deviceCode: String, startTime: String, endTime: String, response: HttpServletResponse): HttpServletResponse {
+ override fun outToExcel(
+ deviceCode: String,
+ startTime: String,
+ endTime: String,
+ response: HttpServletResponse,
+ ): HttpServletResponse {
val workbook = outToWorkbook(deviceCode, startTime, endTime)
val out = response.outputStream
@@ -215,7 +342,13 @@
return contents
}
- private fun getOriginData(deviceCode: String?, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
+ override fun getOriginData(
+ deviceCode: String?,
+ startTime: String?,
+ endTime: String?,
+ page: Int?,
+ perPage: Int?,
+ ): BaseResponse<List<DataVo>> {
val _perPage = perPage ?: 60
val _page = page ?: 1
val sTime = startTime?.let { dateFormatter.parse(it) }
@@ -262,7 +395,7 @@
println("褰撳墠椤垫暟锛�$page")
val dataList = res.data ?: emptyList()
val result = epwDataPrep.mDataPrep2(dataList)
- count += airDataRepository.savePrepData2(result)
+ count += airDataRep.savePrepData2(result).size
page++
}
@@ -275,17 +408,17 @@
var count = 0
val minFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm")
- val averageUtil = AverageUtil<RealTimeDataGrid, RealTimeDataGridMin>({d ->
+ val averageUtil = AverageUtil<RealTimeDataGridOpt, RealTimeDataGridMin>({ d ->
minFormatter.format(d.dataTime)
- },{list ->
- list.avg()
+ }, { list ->
+ list.avg() as RealTimeDataGridMin
})
while (total == -1 || page <= total) {
println("------鍧囧�艰绠梥tart------")
- val p = PageHelper.startPage<RealTimeDataGrid>(page, 50000)
- val res = realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
+ val p = PageHelper.startPage<RealTimeDataGridOpt>(page, 50000)
+ val res = realTimeDataGridOptMapper.selectByExample(Example(RealTimeDataGridOpt::class.java).apply {
createCriteria().andBetween("dataTime", "2021-06-01 00:00:00", "2021-11-05 00:00:00")
})
@@ -305,4 +438,60 @@
return BaseResponse(count > 0, data = "鎻掑叆鏁版嵁: ${count}鏉�")
}
+
+ override fun dataCalibration(): BaseResponse<String> {
+ var page = 1
+ var total = -1
+ var count = 0
+ val sT = "2021-06-19 00:00:00"
+ val eT = "2021-10-21 00:00:00"
+
+ println("------鏁版嵁浼樺寲start------")
+ while (total == -1 || page <= total) {
+ // 棰勫鐞嗗悗鐨勭綉鏍煎寲鏁版嵁
+ val p = PageHelper.startPage<RealTimeDataGrid>(page, 50000)
+ val dataList1 = realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
+ createCriteria().andBetween("dataTime", sT, eT)
+ })
+ // 鍘熷鏁版嵁锛圚2S锛�
+ val res = getOriginData("0d0000000001", sT, eT, page, 50000)
+ val dataList2 = res.data ?: emptyList()
+
+ total = p.pages
+
+ if (page == 1) {
+ println("鎬婚〉鏁帮細$total")
+ }
+ println("褰撳墠椤垫暟锛�$page")
+
+ for (i in dataList1.indices) {
+ if (i >= dataList2.size) break
+ val d1 = dataList1[i]
+ val d2 = dataList2[i]
+ // 鍒ゆ柇灏忔椂锛岃幏鍙栧搴旀椂娈电殑浼樺寲绯绘暟
+ val h = LocalDateTime.ofInstant(d1.dataTime?.toInstant(), ZoneId.systemDefault()).hour
+ val scaleList = scaleMap[h] ?: continue
+ d1.apply {
+ // 鍚勯澶勭悊鍚庣殑鍥犲瓙锛堥櫎H2S锛変箻绯绘暟
+ no2 = no2?.times(scaleList[0])
+ co = co?.times(scaleList[1])
+ so2 = so2?.times(scaleList[3])
+ o3 = o3?.times(scaleList[4])
+ voc = voc?.times(scaleList[7])
+
+ // 鍗曠嫭鎶婂師濮嬬殑H2S涔樹互绯绘暟
+ h2s = d2.values?.get(2)?.factorData?.toFloat()?.times(scaleList[2])
+ h2s = h2s?.let { sqrt(it) * 2 }
+ }
+
+ // 鏇存柊绉掔骇鍊�
+ val opt = RealTimeDataGridOpt()
+ BeanUtils.copyProperties(d1, opt)
+ count += realTimeDataGridOptMapper.insert(opt)
+ }
+ page++
+ }
+
+ return BaseResponse(count > 0, data = "鎻掑叆鏁版嵁: ${count}鏉�")
+ }
}
\ No newline at end of file
--
Gitblit v1.9.3