From 61871594dfa0a5ac2c4d895d9ec4034feba57094 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期五, 12 九月 2025 17:20:53 +0800 Subject: [PATCH] 2025.9.5 1. 新增走航任务统计功能 --- src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt | 217 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 195 insertions(+), 22 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 301ccbe..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?, type: Int?, 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 { @@ -123,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) @@ -160,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 { @@ -187,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") } @@ -203,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 @@ -227,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) } @@ -274,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++ } @@ -287,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") }) @@ -319,6 +440,58 @@ } override fun dataCalibration(): BaseResponse<String> { - return BaseResponse(true) + 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