riku
2025-08-28 3bb4fb15c664d29d179083698fdad35a661b1d7f
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/ElectricityServiceImpl.kt
@@ -1,24 +1,34 @@
package com.flightfeather.uav.lightshare.service.impl
import com.flightfeather.uav.common.utils.DateUtil
import com.flightfeather.uav.biz.dataprocess.ElectricDailyAnalysis
import com.flightfeather.uav.domain.entity.CompanyDevice
import com.flightfeather.uav.domain.entity.ElectricMinuteValue
import com.flightfeather.uav.domain.entity.toAirData
import com.flightfeather.uav.domain.mapper.CompanyDeviceMapper
import com.flightfeather.uav.domain.mapper.ElectricMinuteValueMapper
import com.flightfeather.uav.lightshare.bean.BaseResponse
import com.flightfeather.uav.lightshare.bean.DataHead
import com.flightfeather.uav.lightshare.bean.*
import com.flightfeather.uav.lightshare.eunm.ElectricityType
import com.flightfeather.uav.lightshare.service.ElectricityService
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
import java.time.format.DateTimeParseException
@Service
class ElectricityServiceImpl(private val electricMinuteValueMapper: ElectricMinuteValueMapper) : ElectricityService {
class ElectricityServiceImpl(
    private val electricMinuteValueMapper: ElectricMinuteValueMapper, private val companyDeviceMapper: CompanyDeviceMapper
) : ElectricityService {
    private var dateFormatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
    private var dateFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
    private var dateFormatter3 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
    override fun getMinuteData(
        deviceCode: String, startTime: String?,
        endTime: String?, page: Int?, perPage: Int?
    ): BaseResponse<List<ElectricMinuteValue>> {
    override fun getMinuteData(deviceCode: String, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<ElectricMinuteValue>> {
        val perP = perPage ?: 60
        val p = page ?: 1
        val sTime = startTime?.let { dateFormatter.parse(it) }
@@ -31,10 +41,333 @@
                    sTime?.let { andGreaterThanOrEqualTo("mvDataTime", it) }
                    eTime?.let { andLessThanOrEqualTo("mvDataTime", it) }
                }
            orderBy("mvDataTime")
            orderBy("mvDataTime").apply {
                // 当请求接口不传递起始时间,默认获取最新的数据
                if (startTime == null && endTime == null) {
                    desc()
                }
            }
        }).forEach {
            it?.let { result.add(it) }
        }
        if (startTime == null && endTime == null) {
            result.reverse()
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    override fun getMinuteData2(deviceCode: String, startTime: String?, endTime: String?, page: Int?, perPage: Int?): BaseResponse<List<DataVo>> {
        val result = mutableListOf<DataVo>()
        getMinuteData(deviceCode, startTime, endTime, page, perPage).run {
            data?.forEach {
                result.add(DataVo(
                    DateUtil.instance.dateToString(it.mvDataTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
                    it.mvStatCode,
                    it.toAirData()
                ))
            }
            return BaseResponse(success, head = head, data = result)
        }
    }
    override fun getByCompany(cId: String): BaseResponse<List<ElectricMinuteValue>> {
        val result = mutableListOf<ElectricMinuteValue>()
        companyDeviceMapper.selectByExample(Example(CompanyDevice::class.java).apply {
            createCriteria().andEqualTo("cdCompanyId", cId)
        }).forEach {
            val p = PageHelper.startPage<ElectricMinuteValue>(1, 1)
            electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
                createCriteria().andEqualTo("mvStatCode", it?.cdDeviceCode)
                orderBy("mvDataTime").desc()
            })?.let {
                if (it.isNotEmpty()) {
                    it[0]?.let {e-> result.add(e) }
                }
            }
        }
        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: CompanyDevice? = null
        //废气净化装置
        var d2: CompanyDevice? = null
        deviceCodeList.forEach {
            if (it?.cdType == ElectricityType.ProductionLine.value) {
                d1 = it
            }else if (it?.cdType == ElectricityType.Purify.value) {
                d2 = it
            }
        }
        var pageInfo = PageHelper.startPage<ElectricMinuteValue>(p, perP)
        val dataList1 = electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
            createCriteria().andEqualTo("mvStatCode", d1?.cdDeviceCode)
                .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()
        }
        if (dataList1.isEmpty()) return BaseResponse(true, data = result)
//        pageInfo = PageHelper.startPage<ElectricMinuteValue>(p, perP)
        val dataList2 = electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
            createCriteria().andEqualTo("mvStatCode", d2?.cdDeviceCode)
                .apply {
                    andGreaterThanOrEqualTo("mvDataTime", sTime ?: dataList1[0].mvDataTime)
                    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
        }
        if (sT == null || eT == null) {
            return BaseResponse(true, data = result)
        }
        var lsT = LocalDateTime.ofInstant(sT.toInstant(), ZoneId.systemDefault()).withSecond(0)
        val leT = LocalDateTime.ofInstant(eT.toInstant(), ZoneId.systemDefault()).withSecond(0)
        // 根据两台设备的最长起始时间,计算其中每一分钟的对应均值
        while (!lsT.isAfter(leT)) {
            // FIXME: 2021/11/22 此处由于前端设备的采样时间不标准 ,采样周期并不是严格的1分钟,导致采样时间有时会缺少1分钟的数据
            // FIXME: 2021/11/22 因此,当某一分钟该设备数据轮空时,采用前一个数据作为填充
            val data1 = if (dataList1.isNotEmpty()) dataList1[0] else null
            val t1 = data1?.let {  LocalDateTime.ofInstant(it.mvDataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0) }
            val data2 = if (dataList2.isNotEmpty()) dataList2[0] else null
            val t2 = data2?.let { LocalDateTime.ofInstant(it.mvDataTime?.toInstant(), ZoneId.systemDefault()).withSecond(0) }
            if ((data1 == null || !lsT.isEqual(t1))
                && (data2 == null || !lsT.isEqual(t2))
            ) {
            } else {
                // 两台设备的数据根据时间合并为一个结构体
                val vo = ElectricVo(lsT.format(dateFormatter2))
                if (data1 == null || !lsT.isEqual(t1)) {
                    result.lastOrNull()?.let {
                        vo.apply {
                            d1eA = it.d1eA
                            d1eB = it.d1eB
                            d1eC = it.d1eC
                            d1Status = it.d1Status
                            d1StatusName = it.d1StatusName
                            d1Avg = it.d1Avg
                        }
                    }
                } else {
                    vo.apply {
                        d1eA = data1.mvElectricityA ?: .0
                        d1eB = data1.mvElectricityB ?: .0
                        d1eC = data1.mvElectricityC ?: .0
                        val s = ElectricDailyAnalysis.getStatus(data1, d1)
                        d1Status = s.first
                        d1StatusName = s.second
                        d1Avg = s.third
                    }
                    dataList1.removeAt(0)
                }
                if (data2 == null || !lsT.isEqual(t2)) {
                    result.lastOrNull()?.let {
                        vo.apply {
                            d2eA = it.d2eA
                            d2eB = it.d2eB
                            d2eC = it.d2eC
                            d2Status = it.d2Status
                            d2StatusName = it.d2StatusName
                            d2Avg = it.d2Avg
                        }
                    }
                } else {
                    vo.apply {
                        d2eA = data2.mvElectricityA ?: .0
                        d2eB = data2.mvElectricityB ?: .0
                        d2eC = data2.mvElectricityC ?: .0
                        val s = ElectricDailyAnalysis.getStatus(data2, d2)
                        d2Status = s.first
                        d2StatusName = s.second
                        d2Avg = s.third
                    }
                    dataList2.removeAt(0)
                }
                result.add(vo)
            }
//            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
//                        val s = ElectricDailyAnalysis.getStatus(d, d1)
//                        d1Status = s.first
//                        d1StatusName = s.second
//                        d1Avg = s.third
//                    }
//                    dataList1.removeAt(0)
//                } else {
//                    result.lastOrNull()?.let {
//                        vo.apply {
//                            d1eA = it.d1eA
//                            d1eB = it.d1eB
//                            d1eC = it.d1eC
//                            d1Status = it.d1Status
//                            d1StatusName = it.d1StatusName
//                            d1Avg = it.d1Avg
//                        }
//                    }
//                }
//            } else {
//                result.lastOrNull()?.let {
//                    vo.apply {
//                        d1eA = it.d1eA
//                        d1eB = it.d1eB
//                        d1eC = it.d1eC
//                        d1Status = it.d1Status
//                        d1StatusName = it.d1StatusName
//                        d1Avg = it.d1Avg
//                    }
//                }
//            }
//            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
//                        val s = ElectricDailyAnalysis.getStatus(d, d2)
//                        d2Status = s.first
//                        d2StatusName = s.second
//                        d2Avg = s.third
//                    }
//                    dataList2.removeAt(0)
//                } else {
//                    result.lastOrNull()?.let {
//                        vo.apply {
//                            d2eA = it.d2eA
//                            d2eB = it.d2eB
//                            d2eC = it.d2eC
//                            d2Status = it.d2Status
//                            d2StatusName = it.d2StatusName
//                            d2Avg = it.d2Avg
//                        }
//                    }
//                }
//            } else {
//                result.lastOrNull()?.let {
//                    vo.apply {
//                        d2eA = it.d2eA
//                        d2eB = it.d2eB
//                        d2eC = it.d2eC
//                        d2Status = it.d2Status
//                        d2StatusName = it.d2StatusName
//                        d2Avg = it.d2Avg
//                    }
//                }
//            }
            lsT = lsT.plusMinutes(1)
        }
        return BaseResponse(true, head = DataHead(pageInfo.pageNum, pageInfo.pages), data = result)
    }
    override fun dailyAnalysis(cId: String, startTime: String?, endTime: String?): BaseResponse<List<ElectricDailyInfo>> {
        // 根据企业id获取对应设备
        val devices = companyDeviceMapper.selectByExample(Example(CompanyDevice::class.java).apply {
            createCriteria().andEqualTo("cdCompanyId", cId)
        })
        val deviceCodeList = mutableListOf<String>()
        devices.forEach { it?.let { deviceCodeList.add(it.cdDeviceCode) }}
        val st:LocalDateTime
        val et:LocalDateTime
        // 当没有开始或结束时间时,使用最新一条数据时间的当天作为统计时间
        if (startTime == null || endTime == null) {
            val em = electricMinuteValueMapper.selectOneByExample(Example(ElectricMinuteValue::class.java).apply {
                createCriteria().andIn("mvStatCode", deviceCodeList)
                orderBy("mvDataTime").desc()
            })
            val dataTime = LocalDateTime.ofInstant(em?.mvDataTime?.toInstant(), ZoneId.systemDefault())
            st = dataTime.withHour(0).withMinute(0).withSecond(0)
            et = dataTime.withHour(23).withMinute(59).withSecond(59)
        }
        // 当有开始结束时间时,判断格式是否正确
        else {
            try {
                st = LocalDateTime.parse("$startTime 00:00:00", dateFormatter3)
                et = LocalDateTime.parse("$endTime 23:59:59", dateFormatter3)
            } catch (e: DateTimeParseException) {
                return BaseResponse(false, "时间格式错误,应为yyyy-MM-dd")
            }
        }
        val dataList = electricMinuteValueMapper.selectByExample(Example(ElectricMinuteValue::class.java).apply {
            createCriteria().andIn("mvStatCode", deviceCodeList)
                .andBetween("mvDataTime", st, et)
            orderBy("mvDataTime")
        })
        val result = ElectricDailyAnalysis.analysis(devices, dataList)
        return BaseResponse(true, data = result)
    }
}