1. 添加车载走航动态校准功能
2. 添加网格化数据校准功能
3. 添加网格化数据分钟均值转换功能(待完成)
已修改10个文件
已添加4个文件
552 ■■■■■ 文件已修改
src/main/kotlin/com/flightfeather/uav/domain/entity/FactorCalibration.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/domain/mapper/FactorCalibrationMapper.kt 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/bean/ElectricVo.kt 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/ElectricityService.kt 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/RealTimeDataService.kt 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ElectricityServiceImpl.kt 171 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/lightshare/web/ElectricityController.kt 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/repository/impl/AirDataRepositoryImpl.kt 80 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/generator/generatorConfig.xml 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/FactorCalibrationMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/kotlin/com/flightfeather/uav/domain/entity/FactorCalibration.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,119 @@
package com.flightfeather.uav.domain.entity;
import javax.persistence.*;
@Table(name = "factor_calibration")
public class FactorCalibration {
    @Id
    private Integer id;
    /**
     * è®¾å¤‡ç±»åž‹ï¼ˆ0a:车载; 0b:无人机; 0c:无人船; 0d:网格化)
     */
    @Column(name = "device_type")
    private String deviceType;
    /**
     * ç›‘测因子id
     */
    @Column(name = "factor_id")
    private Integer factorId;
    /**
     * ç›‘测因子名称
     */
    @Column(name = "factor_name")
    private String factorName;
    /**
     * ç›‘测因子校准系数
     */
    @Column(name = "factor_scale")
    private Float factorScale;
    /**
     * @return id
     */
    public Integer getId() {
        return id;
    }
    /**
     * @param id
     */
    public void setId(Integer id) {
        this.id = id;
    }
    /**
     * èŽ·å–è®¾å¤‡ç±»åž‹ï¼ˆ0a:车载; 0b:无人机; 0c:无人船; 0d:网格化)
     *
     * @return device_type - è®¾å¤‡ç±»åž‹ï¼ˆ0a:车载; 0b:无人机; 0c:无人船; 0d:网格化)
     */
    public String getDeviceType() {
        return deviceType;
    }
    /**
     * è®¾ç½®è®¾å¤‡ç±»åž‹ï¼ˆ0a:车载; 0b:无人机; 0c:无人船; 0d:网格化)
     *
     * @param deviceType è®¾å¤‡ç±»åž‹ï¼ˆ0a:车载; 0b:无人机; 0c:无人船; 0d:网格化)
     */
    public void setDeviceType(String deviceType) {
        this.deviceType = deviceType == null ? null : deviceType.trim();
    }
    /**
     * èŽ·å–ç›‘æµ‹å› å­id
     *
     * @return factor_id - ç›‘测因子id
     */
    public Integer getFactorId() {
        return factorId;
    }
    /**
     * è®¾ç½®ç›‘测因子id
     *
     * @param factorId ç›‘测因子id
     */
    public void setFactorId(Integer factorId) {
        this.factorId = factorId;
    }
    /**
     * èŽ·å–ç›‘æµ‹å› å­åç§°
     *
     * @return factor_name - ç›‘测因子名称
     */
    public String getFactorName() {
        return factorName;
    }
    /**
     * è®¾ç½®ç›‘测因子名称
     *
     * @param factorName ç›‘测因子名称
     */
    public void setFactorName(String factorName) {
        this.factorName = factorName == null ? null : factorName.trim();
    }
    /**
     * èŽ·å–ç›‘æµ‹å› å­æ ¡å‡†ç³»æ•°
     *
     * @return factor_scale - ç›‘测因子校准系数
     */
    public Float getFactorScale() {
        return factorScale;
    }
    /**
     * è®¾ç½®ç›‘测因子校准系数
     *
     * @param factorScale ç›‘测因子校准系数
     */
    public void setFactorScale(Float factorScale) {
        this.factorScale = factorScale;
    }
}
src/main/kotlin/com/flightfeather/uav/domain/mapper/FactorCalibrationMapper.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
package com.flightfeather.uav.domain.mapper
import com.flightfeather.uav.domain.MyMapper
import com.flightfeather.uav.domain.entity.FactorCalibration
import org.apache.ibatis.annotations.Mapper
@Mapper
interface FactorCalibrationMapper : MyMapper<FactorCalibration>
src/main/kotlin/com/flightfeather/uav/lightshare/bean/ElectricVo.kt
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.flightfeather.uav.lightshare.bean
data class ElectricVo(
    var time: String? = null,
    //产线风机
    var d1eA: Double = .0,
    var d1eB: Double = .0,
    var d1eC: Double = .0,
    var d1Status: String? = "0",
    //废气净化装置
    var d2eA: Double = .0,
    var d2eB: Double = .0,
    var d2eC: Double = .0,
    var d2Status: String? = "0"
)
src/main/kotlin/com/flightfeather/uav/lightshare/service/ElectricityService.kt
@@ -3,6 +3,7 @@
import com.flightfeather.uav.domain.entity.ElectricMinuteValue
import com.flightfeather.uav.lightshare.bean.BaseResponse
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.lightshare.bean.ElectricVo
interface ElectricityService {
@@ -11,4 +12,6 @@
    fun getMinuteData2(deviceCode: String, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>>
    fun getByCompany(cId:String):BaseResponse<List<ElectricMinuteValue>>
    fun getElectricityInfo(cId: String, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<ElectricVo>>
}
src/main/kotlin/com/flightfeather/uav/lightshare/service/RealTimeDataService.kt
@@ -25,4 +25,9 @@
     * åŽ»é™¤åŽŸå§‹æ•°æ®ä¸­çš„å¼‚å¸¸æ³¢åŠ¨å€¼
     */
    fun dataPreprocessing(): BaseResponse<String>
    /**
     * å‡å€¼è®¡ç®—,将秒级值换算为分钟均值
     */
    fun averageData(): BaseResponse<String>
}
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ElectricityServiceImpl.kt
@@ -9,12 +9,16 @@
import com.flightfeather.uav.lightshare.bean.BaseResponse
import com.flightfeather.uav.lightshare.bean.DataHead
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.lightshare.bean.ElectricVo
import com.flightfeather.uav.lightshare.service.ElectricityService
import com.flightfeather.uav.socket.bean.AirData
import com.github.pagehelper.PageHelper
import org.springframework.stereotype.Service
import tk.mybatis.mapper.entity.Example
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
@Service
class ElectricityServiceImpl(
@@ -22,6 +26,7 @@
) : ElectricityService {
    private var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private var dateFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
    override fun getMinuteData(
        deviceCode: String, startTime: String?,
@@ -86,4 +91,170 @@
        return BaseResponse(true, data = result)
    }
    override fun getElectricityInfo(cId: String, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<ElectricVo>> {
        val perP = perPage ?: 60
        val p = page ?: 1
        val sTime = startTime?.let { dateFormatter.parse(it) }
        val eTime = endTime?.let { dateFormatter.parse(it) }
        val result = mutableListOf<ElectricVo>()
        val deviceCodeList = companyDeviceMapper.selectByExample(Example(CompanyDevice::class.java).apply {
            createCriteria().andEqualTo("cdCompanyId", cId)
        })
        //产线风机
        var d1: String? = null
        //废气净化装置
        var d2: String? = null
        deviceCodeList.forEach {
            // FIXME: 2021/11/5 æ­¤å¤„暂时写死,后续修改
            if (it?.cdDeviceCode == "31011020210602" || it?.cdDeviceCode == "31011020210603") {
                d1 = it.cdDeviceCode
            }else if (it?.cdDeviceCode == "31011020210601" || it?.cdDeviceCode == "31011020210604") {
                d2 = it.cdDeviceCode
            }
        }
        var pageInfo = PageHelper.startPage<ElectricMinuteValue>(p, perP)
        val dataList1 = electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
            createCriteria().andEqualTo("mvStatCode", d1)
                .apply {
                    sTime?.let { andGreaterThanOrEqualTo("mvDataTime", it) }
                    eTime?.let { andLessThanOrEqualTo("mvDataTime", it) }
                }
            orderBy("mvDataTime").apply {
                // å½“请求接口不传递起始时间,默认获取最新的数据
                if (startTime == null && endTime == null) {
                    desc()
                }
            }
        })
        if (startTime == null && endTime == null) {
            dataList1.reverse()
        }
        pageInfo = PageHelper.startPage<ElectricMinuteValue>(p, perP)
        val dataList2 = electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
            createCriteria().andEqualTo("mvStatCode", d2)
                .apply {
                    sTime?.let { andGreaterThanOrEqualTo("mvDataTime", it) }
                    eTime?.let { andLessThanOrEqualTo("mvDataTime", it) }
                }
            orderBy("mvDataTime").apply {
                // å½“请求接口不传递起始时间,默认获取最新的数据
                if (startTime == null && endTime == null) {
                    desc()
                }
            }
        })
        if (startTime == null && endTime == null) {
            dataList2.reverse()
        }
        // FIXME: 2021/11/5 è¿”回结果需要根据两台设备的数据始末时间,选取最长的两个始末时间
        val sT = if (dataList1.isEmpty() && dataList2.isNotEmpty()) {
            dataList2[0]?.mvDataTime
        }else if (dataList1.isNotEmpty() && dataList2.isEmpty()) {
            dataList1[0]?.mvDataTime
        } else if (dataList1.isNotEmpty() && dataList2.isNotEmpty()) {
            if (dataList1[0]?.mvDataTime?.after(dataList2[0]?.mvDataTime) == true) {
                dataList2[0]?.mvDataTime
            } else {
                dataList1[0]?.mvDataTime
            }
        } else {
            null
        }
        val eT = if (dataList1.isEmpty() && dataList2.isNotEmpty()) {
            dataList2.last()?.mvDataTime
        }else if (dataList1.isNotEmpty() && dataList2.isEmpty()) {
            dataList1.last()?.mvDataTime
        } else if (dataList1.isNotEmpty() && dataList2.isNotEmpty()) {
            if (dataList1.last()?.mvDataTime?.after(dataList2.last()?.mvDataTime) == true) {
                dataList1.last()?.mvDataTime
            } else {
                dataList2.last()?.mvDataTime
            }
        } else {
            null
        }
        var lsT = LocalDateTime.ofInstant(sT?.toInstant(), ZoneId.systemDefault()).withSecond(0)
        val leT = LocalDateTime.ofInstant(eT?.toInstant(), ZoneId.systemDefault()).withSecond(0)
        if (sT != null && eT != null) {
            while (!lsT.isAfter(leT)) {
                val vo = ElectricVo(lsT.format(dateFormatter2))
                if (dataList1.isNotEmpty()) {
                    val d = dataList1[0]
                    val t = LocalDateTime.ofInstant(d?.mvDataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0)
                    if (lsT.isEqual(t)) {
                        vo.apply {
                            d1eA = d?.mvElectricityA ?: .0
                            d1eB = d?.mvElectricityB ?: .0
                            d1eC = d?.mvElectricityC ?: .0
                            d1Status = getStatus(d)
                        }
                        dataList1.removeAt(0)
                    }
                }
                if (dataList2.isNotEmpty()) {
                    val d = dataList2[0]
                    val t = LocalDateTime.ofInstant(d?.mvDataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0)
                    if (lsT.isEqual(t)) {
                        vo.apply {
                            d2eA = d?.mvElectricityA ?: .0
                            d2eB = d?.mvElectricityB ?: .0
                            d2eC = d?.mvElectricityC ?: .0
                            d2Status = getStatus(d)
                        }
                        dataList2.removeAt(0)
                    }
                }
                result.add(vo)
                lsT = lsT.plusMinutes(1)
            }
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    // FIXME: 2021/11/5 æ­¤å¤„暂时写死,后续修改
    private fun getStatus(e: ElectricMinuteValue?): String {
        var values = listOf(1, 100)
        var status = listOf("0", "2", "3")
        if (e == null) {
            return status.first()
        }
        when (e.mvStatCode) {
            "31011020210601" -> {
                values = listOf(1, 100)
                status = listOf("0", "2", "3")
            }
            "31011020210602" -> {
                values = listOf(13, 30)
                status = listOf("0", "2", "3")
            }
            "31011020210603" -> {
                values = listOf(1, 50, 80)
                status = listOf("0", "1", "2", "3")
            }
            "31011020210604" -> {
                values = listOf(15, 90, 125)
                status = listOf("0", "1", "2", "3")
            }
        }
        val electricityList = mutableListOf<Double>()
        electricityList.add(e.mvElectricityA)
        electricityList.add(e.mvElectricityB)
        electricityList.add(e.mvElectricityC)
        val avg = electricityList.average()
        for (i in values.indices) {
            if (avg < values[i]) {
                return status[i]
            }
        }
        return status.last()
    }
}
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImpl.kt
@@ -22,8 +22,11 @@
import tk.mybatis.mapper.entity.Example
import java.io.ByteArrayInputStream
import java.text.SimpleDateFormat
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.*
import javax.servlet.http.HttpServletResponse
import javax.swing.text.DateFormatter
@Service
class RealTimeDataServiceImpl(
@@ -35,6 +38,7 @@
) : RealTimeDataService {
    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>> {
@@ -42,27 +46,39 @@
        val _page = page ?: 1
        val sTime = startTime?.let { dateFormatter.parse(it) }
        val eTime = endTime?.let { dateFormatter.parse(it) }
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
//        var pageInfo = PageHelper.startPage<BaseRealTimeData>(_page, _perPage)
        var pageNum = 1
        var pages = 0
        val result = mutableListOf<DataVo>()
        when (UWDeviceType.getType(deviceCode)) {
            UWDeviceType.VEHICLE -> {
                val pageInfo = PageHelper.startPage<RealTimeDataVehicle>(_page, _perPage)
                realTimeDataVehicleMapper.selectByExample(Example(RealTimeDataVehicle::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
            UWDeviceType.UAV -> {
                val pageInfo = PageHelper.startPage<RealTimeDataUav>(_page, _perPage)
                realTimeDataUavMapper.selectByExample(Example(RealTimeDataUav::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach { result.add(it.toDataVo()) }
                pageNum = pageInfo.pageNum
                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
            }
            else -> {
                // ä»ŽåŽŸå§‹æ•°æ®è¡¨ä¸­èŽ·å–æ•°æ®
                val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
                realTimeDataMapper.selectByExample(Example(RealTimeData::class.java).apply {
                    getSecondDataExample(this, deviceCode, sTime, eTime)
                }).forEach {
@@ -71,13 +87,15 @@
                    }
                    result.add(it.toDataVo())
                }
                pageNum = pageInfo.pageNum
                pages = pageInfo.pages
            }
        }
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
        return BaseResponse(true, head = DataHead(pageNum, pages), data = result)
    }
    private fun getSecondDataExample(example: Example, deviceCode: String?, sTime: Date?, eTime: Date?) {
@@ -198,17 +216,83 @@
        return contents
    }
    private 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) }
        val eTime = endTime?.let { dateFormatter.parse(it) }
//        var pageInfo = PageHelper.startPage<BaseRealTimeData>(_page, _perPage)
        var pageNum = 1
        var pages = 0
        val result = mutableListOf<DataVo>()
        // ä»ŽåŽŸå§‹æ•°æ®è¡¨ä¸­èŽ·å–æ•°æ®
        val pageInfo = PageHelper.startPage<RealTimeData>(_page, _perPage)
        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())
        }
        pageNum = pageInfo.pageNum
        pages = pageInfo.pages
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageNum, pages), data = result)
    }
    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 page = 1
        var total = -1
        var count = 0
        dataList.forEach {
            val result = epwDataPrep.mDataPrep2(listOf(it))
        while (total == -1 || page <= total) {
            println("------start------")
            val res = getOriginData("0d0000000001", "2021-07-05 19:47:01", "2021-11-05 00:00:00", page, 50000)
            res.head?.let {
                total = it.totalPage
            }
            if (page == 1) {
                println("总页数:$total")
            }
            println("当前页数:$page")
            val dataList = res.data ?: emptyList()
            val result = epwDataPrep.mDataPrep2(dataList)
            count += airDataRepository.savePrepData2(result)
            println("[${it.deviceCode}]: [${it.time}]")
            Thread.sleep(4000)
            page++
        }
        return BaseResponse(count > 0, data = "插入数据: ${count}条")
    }
    override fun averageData(): BaseResponse<String> {
        val epwDataPrep = EPWDataPrep()
        var page = 1
        var total = -1
        var count = 0
        while (total == -1 || page <= total) {
            println("------start------")
            val res = getOriginData("0d0000000001", "2021-07-05 19:47:01", "2021-11-05 00:00:00", page, 50000)
            res.head?.let {
                total = it.totalPage
            }
            if (page == 1) {
                println("总页数:$total")
            }
            println("当前页数:$page")
            res.data?.forEach {
            }
            page++
        }
        return BaseResponse(count > 0, data = "插入数据: ${count}条")
    }
}
src/main/kotlin/com/flightfeather/uav/lightshare/web/ElectricityController.kt
@@ -34,8 +34,19 @@
        @RequestParam(value = "perPage", required = false) perPage: Int?
    ) = electricityService.getMinuteData2(deviceCode, startTime, endTime, page, perPage)
    @ApiOperation(value = "获取企业用电量最新一条分钟均值")
    @GetMapping("/company")
    fun  getByCompany(
        @ApiParam("企业id") @RequestParam(value = "cId") cId: String,
    ) = electricityService.getByCompany(cId)
    @ApiOperation(value = "获取企业用电量整合数据")
    @GetMapping("/info")
    fun  getElectricityInfo(
        @ApiParam("企业id") @RequestParam(value = "cId") cId: String,
        @ApiParam(value = "开始时间", example = "yyyy-MM-dd HH:mm:ss") @RequestParam(value = "startTime", required = false) startTime: String?,
        @ApiParam(value = "结束时间", example = "yyyy-MM-dd HH:mm:ss") @RequestParam(value = "endTime", required = false) endTime: String?,
        @RequestParam(value = "page", required = false) page: Int?,
        @RequestParam(value = "perPage", required = false) perPage: Int?
    ) = electricityService.getElectricityInfo(cId, startTime, endTime, page, perPage)
}
src/main/kotlin/com/flightfeather/uav/repository/impl/AirDataRepositoryImpl.kt
@@ -1,12 +1,8 @@
package com.flightfeather.uav.repository.impl
import com.flightfeather.uav.common.utils.GsonUtils
import com.flightfeather.uav.domain.MyMapper
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.domain.mapper.*
import com.flightfeather.uav.lightshare.bean.DataVo
import com.flightfeather.uav.repository.AirDataRepository
import com.flightfeather.uav.socket.bean.AirData
@@ -19,7 +15,11 @@
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
@@ -30,11 +30,19 @@
    private val realTimeDataMapper: RealTimeDataMapper,
    private val realTimeDataVehicleMapper: RealTimeDataVehicleMapper,
    private val realTimeDataUavMapper: RealTimeDataUavMapper,
    private val realTimeDataGridMapper: RealTimeDataGridMapper
    private val realTimeDataGridMapper: RealTimeDataGridMapper,
    private val factorCalibrationMapper: FactorCalibrationMapper
): AirDataRepository {
    // 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 {
@@ -129,10 +137,7 @@
                    dataTransform(vo, d)
                    /***************************************************************************************************/
                    // FIXME: 2021/10/27 è½¦è½½ç›‘测部分因子量级调整:NO2*0.6,H2S*0.3, SO2*0.2, O3*0.5,其他要素不变
                    d.no2 = d.no2?.times(0.6f)
                    d.h2s = d.h2s?.times(0.3f)
                    d.so2 = d.so2?.times(0.2f)
                    d.o3 = d.o3?.times(0.5f)
                    calibration(d, UWDeviceType.VEHICLE)
                    /***************************************************************************************************/
                    realTimeDataVehicleMapper.insert(d)
                    count++
@@ -165,8 +170,37 @@
                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 -> {
                }
            }
        }
@@ -267,4 +301,30 @@
        }
    }
    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)
        }
    }
}
src/main/kotlin/com/flightfeather/uav/socket/eunm/UWDeviceType.kt
@@ -6,6 +6,7 @@
enum class UWDeviceType(val value: String, val des: String) {
    UAV("0b", "无人机设备"),
    VEHICLE("0a", "车载设备"),
    BOAT("0c", "无人船"),
    GRID("0d", "网格化设备");
    companion object {
@@ -15,6 +16,7 @@
        fun getType(deviceCode: String?): UWDeviceType? = when (deviceCode?.substring(0, 2)) {
            UAV.value -> UAV
            VEHICLE.value -> VEHICLE
            BOAT.value -> BOAT
            GRID.value -> GRID
            else -> null
        }
src/main/resources/application.yml
@@ -7,9 +7,9 @@
#    password: cn.FLIGHTFEATHER
#    çº¿ä¸ŠæœåС噍
    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
#    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
#    å¼€å‘本地服务器
#    url: jdbc:mysql://localhost:3306/dronemonitor?serverTimezone=Asia/Shanghai&prepStmtCacheSize=517&cachePrepStmts=true&autoReconnect=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false
@@ -17,9 +17,9 @@
#    password: 123456
#   å¼€å‘远程服务器
#    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://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
    hikari:
      maximum-pool-size: 500
      minimum-idle: 20
src/main/resources/generator/generatorConfig.xml
@@ -54,6 +54,7 @@
<!--        <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="device_info" domainObjectName="DeviceInfo" 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"/>
    </context>
</generatorConfiguration>
src/main/resources/mapper/FactorCalibrationMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.flightfeather.uav.domain.mapper.FactorCalibrationMapper">
  <resultMap id="BaseResultMap" type="com.flightfeather.uav.domain.entity.FactorCalibration">
    <!--
      WARNING - @mbg.generated
    -->
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="device_type" jdbcType="VARCHAR" property="deviceType" />
    <result column="factor_id" jdbcType="INTEGER" property="factorId" />
    <result column="factor_name" jdbcType="VARCHAR" property="factorName" />
    <result column="factor_scale" jdbcType="REAL" property="factorScale" />
  </resultMap>
  <sql id="Base_Column_List">
    <!--
      WARNING - @mbg.generated
    -->
    id, device_type, factor_id, factor_name, factor_scale
  </sql>
</mapper>
src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/RealTimeDataServiceImplTest.kt
@@ -119,6 +119,7 @@
    @Test
    fun dataPreprocessing() {
        realTimeDataService.dataPreprocessing()
        val r = realTimeDataService.dataPreprocessing()
        println(r.data)
    }
}