package com.flightfeather.uav.domain.entity
|
|
import com.flightfeather.uav.biz.dataprocess.AvgPair
|
import com.flightfeather.uav.common.utils.DateUtil
|
import com.flightfeather.uav.lightshare.bean.DataVo
|
import com.flightfeather.uav.socket.bean.AirData
|
import com.flightfeather.uav.socket.eunm.FactorType
|
import java.io.Serializable
|
import java.math.BigDecimal
|
import java.time.LocalDateTime
|
import java.time.ZoneId
|
import java.util.*
|
import javax.persistence.Column
|
import javax.persistence.GeneratedValue
|
import javax.persistence.GenerationType
|
import javax.persistence.Id
|
import kotlin.math.atan
|
import kotlin.math.cos
|
import kotlin.math.round
|
import kotlin.math.sin
|
|
/**
|
* 实时监测数据基类
|
*/
|
open class BaseRealTimeData : Serializable {
|
@Id
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
var id: Int? = null
|
|
@Column(name = "device_code")
|
var deviceCode: String? = null
|
|
var latitude: BigDecimal? = null
|
|
var longitude: BigDecimal? = null
|
|
var altitude: Float? = null
|
|
@Column(name = "data_time")
|
var dataTime: Date? = null
|
|
@Column(name = "create_time")
|
var createTime: Date? = null
|
|
@Column(name = "NO2")
|
var no2: Float? = null
|
|
@Column(name = "CO")
|
var co: Float? = null
|
|
@Column(name = "H2S")
|
var h2s: Float? = null
|
|
@Column(name = "SO2")
|
var so2: Float? = null
|
|
@Column(name = "O3")
|
var o3: Float? = null
|
|
@Column(name = "PM25")
|
var pm25: Float? = null
|
|
@Column(name = "PM10")
|
var pm10: Float? = null
|
|
var temperature: Float? = null
|
|
var humidity: Float? = null
|
|
@Column(name = "VOC")
|
var voc: Float? = null
|
|
@Column(name = "NOI")
|
var noi: Float? = null
|
|
@Column(name = "NO")
|
var no: Float? = null
|
|
var velocity: Float? = null
|
|
@Column(name = "wind_speed")
|
var windSpeed: Float? = null
|
|
@Column(name = "wind_direction")
|
var windDirection: Float? = null
|
|
var height: Float? = null
|
|
fun toDataVo() = DataVo().apply {
|
this.time = DateUtil.instance.dateToString(dataTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS)
|
this.deviceCode = this@BaseRealTimeData.deviceCode
|
this.lng = longitude?.toDouble()
|
this.lat = latitude?.toDouble()
|
this.values = mutableListOf<AirData>().apply {
|
add(AirData().apply { setData(FactorType.NO2, no2) })
|
add(AirData().apply { setData(FactorType.CO, co) })
|
add(AirData().apply { setData(FactorType.H2S, h2s) })
|
add(AirData().apply { setData(FactorType.SO2, so2) })
|
add(AirData().apply { setData(FactorType.O3, o3) })
|
|
add(AirData().apply { setData(FactorType.PM25, pm25) })
|
add(AirData().apply { setData(FactorType.PM10, pm10) })
|
add(AirData().apply { setData(FactorType.TEMPERATURE, temperature) })
|
add(AirData().apply { setData(FactorType.HUMIDITY, humidity) })
|
add(AirData().apply { setData(FactorType.VOC, voc) })
|
|
add(AirData().apply { setData(FactorType.NOI, noi) })
|
add(AirData().apply { setData(FactorType.LNG, lng) })
|
add(AirData().apply { setData(FactorType.LAT, lat) })
|
add(AirData().apply { setData(FactorType.VELOCITY, velocity) })
|
add(AirData().apply {
|
setData(FactorType.TIME, dataTime?.time?.toDouble())
|
statusList = listOf(time ?: "")
|
})
|
add(AirData().apply { setData(FactorType.WIND_SPEED, windSpeed) })
|
add(AirData().apply { setData(FactorType.WIND_DIRECTION, windDirection) })
|
add(AirData().apply { setData(FactorType.HEIGHT, height) })
|
add(AirData().apply { setData(FactorType.NO, no) })
|
}
|
}
|
|
fun getByFactorType(type: FactorType?): Float? {
|
return when (type) {
|
FactorType.NO2 -> no2
|
FactorType.CO -> co
|
FactorType.H2S -> h2s
|
FactorType.SO2 -> so2
|
FactorType.O3 -> o3
|
FactorType.PM25 -> pm25
|
FactorType.PM10 -> pm10
|
FactorType.TEMPERATURE -> temperature
|
FactorType.HUMIDITY -> humidity
|
FactorType.VOC -> voc
|
FactorType.NOI -> noi
|
FactorType.LNG -> longitude?.toFloat()
|
FactorType.LAT -> latitude?.toFloat()
|
FactorType.VELOCITY -> velocity
|
// FactorType.TIME -> dataTime?.time?.toFloat()
|
FactorType.WIND_SPEED -> windSpeed
|
FactorType.WIND_DIRECTION -> windDirection
|
FactorType.HEIGHT -> height
|
FactorType.NO -> no
|
else -> null
|
}
|
}
|
|
}
|
|
fun List<BaseRealTimeData>.avg(): BaseRealTimeData {
|
if (isEmpty()) {
|
return BaseRealTimeData()
|
}
|
//风向采用单位矢量法求取均值
|
var u = .0//东西方位分量总和
|
var v = .0//南北方位分量总和
|
var c = 0//风向数据计数
|
|
//除风向外的其他因子采用算术平均法求取均值
|
val tmpList = mutableListOf<AvgPair>()
|
repeat(18) {
|
tmpList.add(AvgPair(0f, 0))
|
}
|
|
forEach {
|
//风向
|
it.windDirection?.let {w ->
|
val r = Math.toRadians(w.toDouble())
|
u += sin(r)
|
v += cos(r)
|
c++
|
}
|
//其余因子
|
tmpList[0].apply {
|
it.latitude?.let {
|
t += it.toFloat()
|
this.c++
|
}
|
}
|
tmpList[1].apply {
|
it.longitude?.let {
|
t += it.toFloat()
|
this.c++
|
}
|
}
|
tmpList[2].apply {
|
it.altitude?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[3].apply {
|
it.no2?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[4].apply {
|
it.co?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[5].apply {
|
it.h2s?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[6].apply {
|
it.so2?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[7].apply {
|
it.o3?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[8].apply {
|
it.pm25?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[9].apply {
|
it.pm10?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[10].apply {
|
it.temperature?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[11].apply {
|
it.humidity?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[12].apply {
|
it.voc?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[13].apply {
|
it.noi?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[14].apply {
|
it.velocity?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[15].apply {
|
it.windSpeed?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[16].apply {
|
it.height?.let {
|
t += it
|
this.c++
|
}
|
}
|
tmpList[17].apply {
|
it.no?.let {
|
t += it
|
this.c++
|
}
|
}
|
}
|
|
return RealTimeDataGridMin().apply {
|
val time = LocalDateTime
|
.ofInstant(get(0).dataTime?.toInstant() ?: Date().toInstant(), ZoneId.systemDefault())
|
.withSecond(0)
|
deviceCode = get(0).deviceCode
|
dataTime = Date.from(time.atZone(ZoneId.systemDefault()).toInstant())
|
createTime = dataTime
|
latitude = tmpList[0].avg().toBigDecimal()
|
longitude = tmpList[1].avg().toBigDecimal()
|
altitude = tmpList[2].avg()
|
no2 = tmpList[3].avg()
|
co = tmpList[4].avg()
|
h2s = tmpList[5].avg()
|
so2 = tmpList[6].avg()
|
o3 = tmpList[7].avg()
|
pm25 = tmpList[8].avg()
|
pm10 = tmpList[9].avg()
|
temperature = tmpList[10].avg()
|
humidity = tmpList[11].avg()
|
voc = tmpList[12].avg()
|
noi = tmpList[13].avg()
|
velocity = tmpList[14].avg()
|
windSpeed = tmpList[15].avg()
|
height = tmpList[16].avg()
|
no = tmpList[17].avg()
|
|
if (c != 0) {
|
val avgU = u / c
|
val avgV = v / c
|
var a = atan(avgU / avgV)
|
a = Math.toDegrees(a)
|
/**
|
* avgU>0;avgV>0: 真实角度处于第一象限,修正值为+0°
|
* avgU>0;avgV<0: 真实角度处于第二象限,修正值为+180°
|
* avgU<0;avgV<0: 真实角度处于第三象限,修正值为+180°
|
* avgU<0;avgV>0: 真实角度处于第四象限,修正值为+360°
|
*/
|
a += if (avgV > 0) {
|
if (avgU > 0) 0 else 360
|
} else {
|
180
|
}
|
windDirection = round(a.toFloat())
|
}
|
}
|
}
|