feiyu02
2024-07-18 5b0d58c3f7f35f61c0a0437bac3ff708db57fe61
src/main/kotlin/com/flightfeather/uav/repository/impl/AirDataRepositoryImpl.kt
@@ -1,32 +1,333 @@
package com.flightfeather.uav.repository.impl
import com.flightfeather.uav.domain.entity.RealTimeData
import com.flightfeather.uav.domain.mapper.RealTimeDataMapper
import com.flightfeather.uav.common.utils.GsonUtils
import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.domain.mapper.*
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.repository.AirDataRepository
import com.flightfeather.uav.socket.bean.AirPackageData
import com.flightfeather.uav.socket.bean.AirData
import com.flightfeather.uav.socket.bean.AirDataPackage
import com.flightfeather.uav.socket.eunm.FactorType
import com.flightfeather.uav.socket.eunm.UWDeviceType
import com.github.pagehelper.PageHelper
import com.google.gson.Gson
import org.springframework.stereotype.Repository
import tk.mybatis.mapper.entity.Example
import java.math.BigDecimal
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.ZoneId
import java.util.*
import kotlin.math.abs
import kotlin.math.sqrt
/**
 * @author riku
 * Date: 2020/6/11
 */
@Repository
class AirDataRepositoryImpl(private val realTimeDataMapper: RealTimeDataMapper): AirDataRepository {
class AirDataRepositoryImpl(
    private val realTimeDataMapper: RealTimeDataMapper,
    private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
    private val realTimeDataUavMapper: RealTimeDataUavMapper,
    private val realTimeDataGridMapper: RealTimeDataGridMapper,
    private val factorCalibrationMapper: FactorCalibrationMapper
): AirDataRepository {
    override fun saveAirData(packageData: AirPackageData): Int {
    // FIXME: 2021/10/25 临时车载数据,由于无人机部分监测因子数据无效,因此暂时采用车载数据作为填充
    private val tmpVehicleDataList = mutableListOf<BaseRealTimeData>()
    // 走航监测校准系数
    private val calibrationMap = mutableMapOf<String, MutableMap<Int, Float>>()
    // 走航监测校准系数更新时间
    private var cUpdateTime = LocalDateTime.now()
    // 走航监测校准系数更新时间间隔(分钟)
    private val cInterval = 5L
    override fun saveAirData(dataPackage: AirDataPackage): Int {
        val data = RealTimeData().apply {
            deviceCode = packageData.deviceCode
            latitude
            longitude
            deviceCode = dataPackage.deviceCode
            latitude = BigDecimal.ZERO
            longitude = BigDecimal.ZERO
            altitude
            height
            factors = Gson().toJson(packageData.dataUnit)
            dataTime = packageData.dataTime
            factors = Gson().toJson(dataPackage.dataUnit)
            dataTime = dataPackage.dataTime
        }
        dataPackage.dataUnit.forEach {
            if (it is AirData) {
                when (it.factorId?.toInt()) {
                    FactorType.LAT.value -> {
                        data.latitude = it.factorData?.toBigDecimal()
                    }
                    FactorType.LNG.value -> {
                        data.longitude = it.factorData?.toBigDecimal()
                    }
                    FactorType.TIME.value -> {
                        it.statusList?.takeIf {l-> l.isNotEmpty() }?.get(0)?.let {d ->
                            data.dataTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(d)
                        }
                    }
                }
            }
        }
        realTimeDataMapper.insert(data)
        return 0
    }
    override fun savePrepData(dataPackage: AirDataPackage): Int {
        var count = 0
        when (UWDeviceType.getType(dataPackage.deviceCode)) {
            UWDeviceType.VEHICLE -> {
                val d = RealTimeDataVehicle()
                dataTransform(dataPackage, d)
                realTimeDataVehicleMapper.insert(d)
                count++
            }
            UWDeviceType.UAV -> {
                val d = RealTimeDataUav()
                dataTransform(dataPackage, d)
                realTimeDataUavMapper.insert(d)
                count++
            }
            UWDeviceType.GRID -> {
                val d = RealTimeDataGrid()
                dataTransform(dataPackage, d)
                realTimeDataGridMapper.insert(d)
                count++
            }
            else -> Unit
        }
        return count
    }
    override fun savePrepData(dataList: List<RealTimeData>): Int {
        var count = 0
        dataList.forEach {vo ->
            when (UWDeviceType.getType(vo.deviceCode)) {
                UWDeviceType.VEHICLE -> {
                    val d = RealTimeDataVehicle()
                    dataTransform(vo, d)
                    realTimeDataVehicleMapper.insert(d)
                    count++
                }
                UWDeviceType.UAV -> {
                    val d = RealTimeDataUav()
                    dataTransform(vo, d)
                    realTimeDataUavMapper.insert(d)
                    count++
                }
                UWDeviceType.GRID -> {
                    val d = RealTimeDataGrid()
                    dataTransform(vo, d)
                    realTimeDataGridMapper.insert(d)
                    count++
                }
                else -> Unit
            }
        }
        return count
    }
    override fun savePrepData2(dataList: List<DataVo>): Int {
        var count = 0
        dataList.forEach {vo ->
            when (UWDeviceType.getType(vo.deviceCode)) {
                UWDeviceType.VEHICLE -> {
                    val d = RealTimeDataVehicle()
                    dataTransform(vo, d)
                    /***************************************************************************************************/
                    // FIXME: 2021/10/27 车载监测部分因子量级调整
                    calibration(d, UWDeviceType.VEHICLE)
                    /***************************************************************************************************/
                    realTimeDataVehicleMapper.insert(d)
                    count++
                }
                UWDeviceType.UAV -> {
                    val d = RealTimeDataUav()
                    dataTransform(vo, d)
                    /***************************************************************************************************/
                    // FIXME: 2021/10/25 无人机部分因子采用车载数据填充,取最新的15分钟的数据
                    if (tmpVehicleDataList.isEmpty()) {
                        val p = PageHelper.startPage<RealTimeDataVehicle>(1, 225)
                        realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                            orderBy("dataTime").desc()
                        }).let { tmpVehicleDataList.addAll(it) }
                    }
                    if (tmpVehicleDataList.isNotEmpty()) {
                        tmpVehicleDataList[0].let {
                            d.no2 = it.no2
                            d.co = it.co
                            d.h2s = it.h2s
                            d.so2 = it.so2
                            d.o3 = it.o3
                        }
                        tmpVehicleDataList.removeFirst()
                    }
                    /***************************************************************************************************/
                    realTimeDataUavMapper.insert(d)
                    count++
                }
                UWDeviceType.GRID -> {
                    val d = RealTimeDataGrid()
                    dataTransform(vo, d)
                    /**************************************************************************/
                    // FIXME: 2021/11/8 针对历史网格化原始数据,进行临时校准处理
//                    val dTime = LocalDateTime.ofInstant(d.dataTime?.toInstant(), ZoneId.systemDefault())
//                    // CO: 2021.8.28 17:27起 *0.25
//                    val coTime = LocalDateTime.of(2021, 8, 28, 17, 27, 0)
//                    if (dTime.isAfter(coTime)) {
//                        d.co = d.co?.times(0.25f)
//                    }
//
//                    // NO2
//                    d.no2 = d.no2?.times(0.6f)
//
//                    // O3
//                    d.o3 = abs(d.o3?.minus(d.no2?.div(2) ?: 0f) ?: 0f) * 1.5f
//
//                    // SO2: *0.2, 2021.8.29 6:00起 *0.08
//                    val so2Time = LocalDateTime.of(2021, 8, 29, 6, 0, 0)
//                    d.so2 = if (dTime.isAfter(so2Time)) {
//                        d.so2?.times(0.08f)
//                    } else {
//                        d.so2?.times(0.2f)
//                    }
//
//                    // H2S
//                    d.h2s = d.h2s?.let { sqrt(it) * 2 }
                    /**************************************************************************/
                    realTimeDataGridMapper.insert(d)
                    count++
                }
                UWDeviceType.BOAT -> {
                }
                else -> Unit
            }
        }
        return count
    }
    private fun dataTransform(vo: RealTimeData, bean: BaseRealTimeData) {
        bean.apply {
            deviceCode = vo.deviceCode
            latitude = vo.latitude
            longitude = vo.longitude
            dataTime = vo.dataTime
            createTime = vo.createTime
            GsonUtils.parserJsonToArrayBeans(vo.factors, AirData::class.java).forEach {
                when (it.factorId?.toInt()) {
                    FactorType.NO2.value -> no2 = it.factorData?.toFloat()
                    FactorType.CO.value -> co = it.factorData?.toFloat()
                    FactorType.H2S.value -> h2s = it.factorData?.toFloat()
                    FactorType.SO2.value -> so2 = it.factorData?.toFloat()
                    FactorType.O3.value -> o3 = it.factorData?.toFloat()
                    FactorType.PM25.value -> pm25 = it.factorData?.toFloat()
                    FactorType.PM10.value -> pm10 = it.factorData?.toFloat()
                    FactorType.TEMPERATURE.value -> temperature = it.factorData?.toFloat()
                    FactorType.HUMIDITY.value -> humidity = it.factorData?.toFloat()
                    FactorType.VOC.value -> voc = it.factorData?.toFloat()
                    FactorType.NOI.value -> noi = it.factorData?.toFloat()
                    FactorType.VELOCITY.value -> velocity = it.factorData?.toFloat()
                    FactorType.WIND_SPEED.value -> windSpeed = it.factorData?.toFloat()
                    FactorType.WIND_DIRECTION.value -> windDirection = it.factorData?.toFloat()
                    FactorType.HEIGHT.value -> height = it.factorData?.toFloat()
                }
            }
        }
    }
    private fun dataTransform(dataPackage: AirDataPackage, bean: BaseRealTimeData) {
        bean.apply {
            deviceCode = dataPackage.deviceCode
            dataPackage.dataUnit.forEach {
                if (it is AirData) {
                    when (it.factorId?.toInt()) {
                        FactorType.NO2.value -> no2 = it.factorData?.toFloat()
                        FactorType.CO.value -> co = it.factorData?.toFloat()
                        FactorType.H2S.value -> h2s = it.factorData?.toFloat()
                        FactorType.SO2.value -> so2 = it.factorData?.toFloat()
                        FactorType.O3.value -> o3 = it.factorData?.toFloat()
                        FactorType.PM25.value -> pm25 = it.factorData?.toFloat()
                        FactorType.PM10.value -> pm10 = it.factorData?.toFloat()
                        FactorType.TEMPERATURE.value -> temperature = it.factorData?.toFloat()
                        FactorType.HUMIDITY.value -> humidity = it.factorData?.toFloat()
                        FactorType.VOC.value -> voc = it.factorData?.toFloat()
                        FactorType.NOI.value -> noi = it.factorData?.toFloat()
                        FactorType.VELOCITY.value -> velocity = it.factorData?.toFloat()
                        FactorType.WIND_SPEED.value -> windSpeed = it.factorData?.toFloat()
                        FactorType.WIND_DIRECTION.value -> windDirection = it.factorData?.toFloat()
                        FactorType.HEIGHT.value -> height = it.factorData?.toFloat()
                        FactorType.LAT.value -> latitude = it.factorData?.toBigDecimal()
                        FactorType.LNG.value -> longitude = it.factorData?.toBigDecimal()
                        FactorType.TIME.value -> it.statusList?.takeIf { l -> l.isNotEmpty() }?.get(0)?.let { d ->
                            dataTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(d)
                        }
                    }
                }
            }
        }
    }
    fun dataTransform(vo: DataVo, bean: BaseRealTimeData) {
        bean.apply {
            deviceCode = vo.deviceCode
            latitude = vo.lat?.toBigDecimal()
            longitude = vo.lng?.toBigDecimal()
            dataTime = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(vo.time)
            createTime = Date()
            vo.values?.forEach {
                when (it.factorId?.toInt()) {
                    FactorType.NO2.value -> no2 = it.factorData?.toFloat()
                    FactorType.CO.value -> co = it.factorData?.toFloat()
                    FactorType.H2S.value -> h2s = it.factorData?.toFloat()
                    FactorType.SO2.value -> so2 = it.factorData?.toFloat()
                    FactorType.O3.value -> o3 = it.factorData?.toFloat()
                    FactorType.PM25.value -> pm25 = it.factorData?.toFloat()
                    FactorType.PM10.value -> pm10 = it.factorData?.toFloat()
                    FactorType.TEMPERATURE.value -> temperature = it.factorData?.toFloat()
                    FactorType.HUMIDITY.value -> humidity = it.factorData?.toFloat()
                    FactorType.VOC.value -> voc = it.factorData?.toFloat()
                    FactorType.NOI.value -> noi = it.factorData?.toFloat()
                    FactorType.VELOCITY.value -> velocity = it.factorData?.toFloat()
                    FactorType.WIND_SPEED.value -> windSpeed = it.factorData?.toFloat()
                    FactorType.WIND_DIRECTION.value -> windDirection = it.factorData?.toFloat()
                    FactorType.HEIGHT.value -> height = it.factorData?.toFloat()
                }
            }
        }
    }
    private fun calibration(data: BaseRealTimeData, type: UWDeviceType) {
        //1. 校准系数按照一定时间间隔进行刷新
        val now = LocalDateTime.now()
        if (calibrationMap.isEmpty() || now.minusMinutes(cInterval).isAfter(cUpdateTime)) {
            cUpdateTime = now
            calibrationMap[type.value] = mutableMapOf()
            factorCalibrationMapper.selectByExample(Example(FactorCalibration::class.java).apply {
                createCriteria().andEqualTo("deviceType", type.value)
            }).forEach {
                calibrationMap[type.value]?.put(it.factorId, it.factorScale)
            }
        }
        //2. 根据校准系数计算
        calibrationMap[type.value]?.let{
            data.voc = data.voc?.times(it[FactorType.VOC.value] ?: 1f)
            data.co = data.co?.times(it[FactorType.CO.value] ?: 1f)
            data.pm25 = data.pm25?.times(it[FactorType.PM25.value] ?: 1f)
            data.pm10 = data.pm10?.times(it[FactorType.PM10.value] ?: 1f)
            data.no2 = data.no2?.times(it[FactorType.NO2.value] ?: 1f)
            data.h2s = data.h2s?.times(it[FactorType.H2S.value] ?: 1f)
            data.so2 = data.so2?.times(it[FactorType.SO2.value] ?: 1f)
            data.o3 = data.o3?.times(it[FactorType.O3.value] ?: 1f)
        }
    }
}