122 lines
3.1 KiB
Go
122 lines
3.1 KiB
Go
package dao
|
||
|
||
import (
|
||
"database/sql"
|
||
"time"
|
||
|
||
"go_rain_dtu/internal/model"
|
||
"go_rain_dtu/pkg/logger"
|
||
)
|
||
|
||
type SensorDAO struct {
|
||
db *sql.DB
|
||
}
|
||
|
||
func NewSensorDAO(db *sql.DB) *SensorDAO {
|
||
return &SensorDAO{db: db}
|
||
}
|
||
|
||
// 插入传感器数据
|
||
func (dao *SensorDAO) Insert(data *model.SensorData) error {
|
||
query := `
|
||
INSERT INTO sensor_data (
|
||
timestamp, wind_speed, wind_force, wind_direction_8,
|
||
wind_direction_360, humidity, temperature, atm_pressure,
|
||
solar_radiation, rainfall
|
||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||
`
|
||
|
||
_, err := dao.db.Exec(query,
|
||
data.Timestamp, data.WindSpeed, data.WindForce, data.WindDirection8,
|
||
data.WindDirection360, data.Humidity, data.Temperature, data.AtmPressure,
|
||
data.SolarRadiation, data.Rainfall,
|
||
)
|
||
|
||
if err != nil {
|
||
logger.Logger.Printf("插入传感器数据失败: %v", err)
|
||
return err
|
||
}
|
||
|
||
return nil
|
||
}
|
||
|
||
// 获取聚合数据
|
||
func (dao *SensorDAO) GetAggregatedData(start, end time.Time, interval string) ([]model.AggregatedData, error) {
|
||
// 参数化时间间隔
|
||
var intervalMinutes int
|
||
|
||
switch interval {
|
||
case "5min":
|
||
intervalMinutes = 5
|
||
case "30min":
|
||
intervalMinutes = 30
|
||
default: // 1hour
|
||
intervalMinutes = 60
|
||
}
|
||
|
||
// 使用时间桶函数创建标准化的时间戳,并将其包含在GROUP BY子句中
|
||
query := `
|
||
SELECT
|
||
DATE_FORMAT(
|
||
DATE_ADD(
|
||
DATE(timestamp),
|
||
INTERVAL (HOUR(timestamp) * 60 + FLOOR(MINUTE(timestamp) / ?) * ?) MINUTE
|
||
),
|
||
'%Y-%m-%dT%H:%i:00'
|
||
) AS bucket_time,
|
||
ROUND(AVG(temperature)/10, 1) AS avg_temp,
|
||
MAX(rainfall) - MIN(rainfall) AS rainfall,
|
||
ROUND(AVG(humidity)/10, 1) AS avg_humidity,
|
||
ROUND(AVG(wind_speed)/10, 1) AS avg_wind_speed,
|
||
ROUND(AVG(atm_pressure)/10, 1) AS avg_atm_pressure,
|
||
ROUND(AVG(solar_radiation)/10, 1) AS avg_solar_radiation
|
||
FROM sensor_data
|
||
WHERE timestamp BETWEEN ? AND ?
|
||
GROUP BY bucket_time
|
||
ORDER BY bucket_time DESC
|
||
`
|
||
|
||
// 执行查询
|
||
rows, err := dao.db.Query(
|
||
query,
|
||
intervalMinutes, intervalMinutes, // 时间桶计算参数
|
||
start, end) // 时间范围
|
||
|
||
if err != nil {
|
||
logger.Logger.Printf("查询聚合数据失败: %v (间隔=%s, 开始=%s, 结束=%s)",
|
||
err, interval, start.Format(time.RFC3339), end.Format(time.RFC3339))
|
||
return nil, err
|
||
}
|
||
defer rows.Close()
|
||
|
||
var result []model.AggregatedData
|
||
for rows.Next() {
|
||
var data model.AggregatedData
|
||
var tsStr string
|
||
err := rows.Scan(&tsStr, &data.AvgTemperature, &data.Rainfall,
|
||
&data.AvgHumidity, &data.AvgWindSpeed, &data.AvgAtmPressure, &data.AvgSolarRadiation)
|
||
if err != nil {
|
||
logger.Logger.Printf("扫描数据行失败: %v", err)
|
||
continue
|
||
}
|
||
|
||
// 解析ISO格式的时间字符串
|
||
data.Timestamp, err = time.Parse("2006-01-02T15:04:00", tsStr)
|
||
if err != nil {
|
||
logger.Logger.Printf("解析时间失败: %v, 原始字符串: %s", err, tsStr)
|
||
continue
|
||
}
|
||
|
||
result = append(result, data)
|
||
}
|
||
|
||
// 检查是否有游标错误
|
||
if err = rows.Err(); err != nil {
|
||
logger.Logger.Printf("查询游标错误: %v", err)
|
||
return nil, err
|
||
}
|
||
|
||
logger.Logger.Printf("聚合查询成功: 返回%d条记录 (间隔=%s)", len(result), interval)
|
||
return result, nil
|
||
}
|