src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
@@ -1,29 +1,38 @@
package com.flightfeather.uav.lightshare.service.impl
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.domain.entity.RealTimeData
import com.flightfeather.uav.domain.entity.toRowContent
import com.flightfeather.uav.domain.entity.toRowTitle
import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.domain.mapper.RealTimeDataGridMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataUavMapper
import com.flightfeather.uav.domain.mapper.RealTimeDataVehicleMapper
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.socket.eunm.UWDeviceType
import com.github.pagehelper.PageHelper
import org.apache.poi.hssf.usermodel.HSSFWorkbook
import org.apache.poi.xssf.streaming.SXSSFWorkbook
import org.springframework.stereotype.Service
import org.springframework.web.multipart.MultipartFile
import tk.mybatis.mapper.entity.Example
import java.io.ByteArrayInputStream
import java.io.FileInputStream
import java.io.InputStream
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
import javax.servlet.http.HttpServletResponse
@Service
class RealTimeDataServiceImpl(val realTimeDataMapper: RealTimeDataMapper) : RealTimeDataService {
class RealTimeDataServiceImpl(
    private val realTimeDataMapper: RealTimeDataMapper,
    private val airDataRepository: AirDataRepository,
    private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
    private val realTimeDataUavMapper: RealTimeDataUavMapper,
    private val realTimeDataGridMapper: RealTimeDataGridMapper
) : RealTimeDataService {
    private var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private val fileExchange = FileExchange()
@@ -35,30 +44,54 @@
        val eTime = endTime?.let { dateFormatter.parse(it) }
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
        val result = mutableListOf<DataVo>()
        realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().apply {
                deviceCode?.let { andEqualTo("deviceCode", it) }
                sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
                eTime?.let { andLessThanOrEqualTo("dataTime", it) }
        when (UWDeviceType.getType(deviceCode)) {
            UWDeviceType.VEHICLE -> {
                realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            orderBy("dataTime").apply {
                // 当请求接口不传递起始时间,默认获取最新的数据
                if (startTime == null && endTime == null) {
                    desc()
            UWDeviceType.UAV -> {
                realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            UWDeviceType.GRID -> {
                realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            else -> {
                // 从原始数据表中获取数据
                realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach {
                    if (it.longitude == null || it.latitude == null) {
                        return@forEach
                    }
                    result.add(it.toDataVo())
                }
            }
        }).forEach {
            result.add(DataVo(
                    dateFormatter.format(it.dataTime),
                    it.deviceCode,
                    GsonUtils.parserJsonToArrayBeans(it.factors, AirData::class.java),
                    it.longitude.toDouble(), it.latitude.toDouble()
            ))
        }
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    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 {
            // 当请求接口不传递起始时间,默认获取最新的数据
            if (sTime == null && eTime == null) {
                desc()
            }
        }
    }
    override fun getNextData(deviceCode: String, updateTime: String, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
@@ -66,19 +99,36 @@
        val _page = page ?: 1
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
        val result = mutableListOf<DataVo>()
        realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().andEqualTo("deviceCode", deviceCode)
                .andGreaterThan("dataTime", updateTime)
            orderBy("dataTime")
        }).forEach {
            result.add(DataVo(
                dateFormatter.format(it.dataTime),
                it.deviceCode,
                GsonUtils.parserJsonToArrayBeans(it.factors, AirData::class.java),
                it.longitude.toDouble(), it.latitude.toDouble()
            ))
        when (UWDeviceType.getType(deviceCode)) {
            UWDeviceType.VEHICLE -> {
                realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            UWDeviceType.UAV -> {
                realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            UWDeviceType.GRID -> {
                realTimeDataGridMapper.selectByExample(Example(RealTimeDataGrid::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
            else -> {
                realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                    getNextDataExample(this, deviceCode, updateTime)
                }).forEach { result.add(it.toDataVo()) }
            }
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    private fun getNextDataExample(example: Example, deviceCode: String, updateTime: String) {
        example.createCriteria().andEqualTo("deviceCode", deviceCode)
            .andGreaterThan("dataTime", updateTime)
        example.orderBy("dataTime")
    }
    override fun importData(file: MultipartFile): BaseResponse<DataImportResult> {
@@ -89,22 +139,37 @@
        return BaseResponse(true, data = DataImportResult(""))
    }
    override fun outToWorkbook(deviceCode: String, startTime: String, endTime: String): HSSFWorkbook {
    override fun outToWorkbook(deviceCode: String, startTime: String, endTime: String): SXSSFWorkbook {
        val sTime = dateFormatter.parse(startTime)
        val eTime = dateFormatter.parse(endTime)
        val r = realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
            createCriteria().andEqualTo("deviceCode", deviceCode)
                .apply {
                    sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
                    eTime?.let { andLessThanOrEqualTo("dataTime", it) }
        var page = 1
        var totalPage = 1
        val pageSize = 10000
        val workbook = SXSSFWorkbook()
        var rowIndex = 0
        while (page <= totalPage) {
            val pageInfo = PageHelper.startPage<RealTimeData>(page, pageSize)
            val r = realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                createCriteria().andEqualTo("deviceCode", deviceCode)
                    .apply {
                        sTime?.let { andGreaterThanOrEqualTo("dataTime", it) }
                        eTime?.let { andLessThanOrEqualTo("dataTime", it) }
                    }
            })
            if (r.isNotEmpty()) {
                val heads = if (page == 1) {
                    println("[${DateUtil.instance.dateToString(Date(), DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)}] totalPage: ${pageInfo.pages}")
                    getTableTitle(r[0])
                } else {
                    emptyList()
                }
        })
        val workbook = HSSFWorkbook()
        if (r.isNotEmpty()) {
            val heads = getTableTitle(r[0])
            val contents = getTableContents(r)
            ExcelUtil.write(heads, contents, workbook)
                val contents = getTableContents(r)
                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")
            }
            totalPage = pageInfo.pages
            page++
        }
        return workbook
    }
@@ -132,4 +197,18 @@
        }
        return contents
    }
    override fun dataPreprocessing(): BaseResponse<String> {
        val epwDataPrep = EPWDataPrep()
        val res = getSecondData("0b0000000002", "2021-10-23 19:00:00", "2021-10-23 20:00:00", 1, 5000)
        val dataList = res.data ?: emptyList()
        var count = 0
        dataList.forEach {
            val result = epwDataPrep.mDataPrep2(listOf(it))
            count += airDataRepository.savePrepData2(result)
            println("[${it.deviceCode}]: [${it.time}]")
            Thread.sleep(4000)
        }
        return BaseResponse(count > 0, data = "插入数据: ${count}条")
    }
}