2025-05-15 17:40:28 +08:00

120 lines
3.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
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)
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
}