fengyarnom 94308d81a0 init
2025-06-27 18:09:37 +08:00

226 lines
6.3 KiB
Go

package db
import (
"database/sql"
"fmt"
"log"
"rain_monitor/models"
"time"
_ "github.com/go-sql-driver/mysql"
)
var db *sql.DB
type DBConfig struct {
Host string
Port int
User string
Password string
DBName string
}
func InitDB(config DBConfig) error {
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=true&loc=Local",
config.User, config.Password, config.Host, config.Port, config.DBName)
var err error
db, err = sql.Open("mysql", dsn)
if err != nil {
return fmt.Errorf("数据库连接失败: %v", err)
}
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
db.SetConnMaxLifetime(time.Hour)
if err = db.Ping(); err != nil {
return fmt.Errorf("数据库Ping失败: %v", err)
}
if err = createTables(); err != nil {
return fmt.Errorf("创建表失败: %v", err)
}
log.Println("数据库连接成功")
return nil
}
func CloseDB() {
if db != nil {
db.Close()
}
}
func createTables() error {
_, err := db.Exec(models.CreateWeatherDataTable)
if err != nil {
return fmt.Errorf("创建气象站数据表失败: %v", err)
}
_, err = db.Exec(models.CreateRainGaugeDataTable)
if err != nil {
return fmt.Errorf("创建雨量计数据表失败: %v", err)
}
return nil
}
func SaveWeatherData(data *models.WeatherData) (int64, error) {
result, err := db.Exec(models.InsertWeatherDataSQL,
data.Timestamp, data.WindSpeed, data.WindForce, data.WindDirection8, data.WindDirection360,
data.Humidity, data.Temperature, data.Noise, data.PM25, data.PM10, data.AtmPressure,
data.LuxHigh, data.LuxLow, data.LightIntensity, data.Rainfall, data.CompassAngle, data.SolarRadiation)
if err != nil {
return 0, fmt.Errorf("保存气象站数据失败: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("获取插入ID失败: %v", err)
}
return id, nil
}
func SaveRainGaugeData(data *models.RainGaugeData) (int64, error) {
result, err := db.Exec(models.InsertRainGaugeDataSQL,
data.Timestamp, data.DailyRainfall, data.InstantRainfall, data.YesterdayRainfall,
data.TotalRainfall, data.HourlyRainfall, data.LastHourRainfall, data.Max24hRainfall,
data.Max24hRainfallPeriod, data.Min24hRainfall, data.Min24hRainfallPeriod)
if err != nil {
return 0, fmt.Errorf("保存雨量计数据失败: %v", err)
}
id, err := result.LastInsertId()
if err != nil {
return 0, fmt.Errorf("获取插入ID失败: %v", err)
}
return id, nil
}
func GetWeatherDataByTimeRange(start, end time.Time) ([]models.WeatherData, error) {
rows, err := db.Query(models.QueryWeatherDataByTimeRangeSQL, start, end)
if err != nil {
return nil, fmt.Errorf("查询气象站数据失败: %v", err)
}
defer rows.Close()
var result []models.WeatherData
for rows.Next() {
var data models.WeatherData
err := rows.Scan(
&data.ID, &data.Timestamp, &data.WindSpeed, &data.WindForce, &data.WindDirection8,
&data.WindDirection360, &data.Humidity, &data.Temperature, &data.Noise, &data.PM25,
&data.PM10, &data.AtmPressure, &data.LuxHigh, &data.LuxLow, &data.LightIntensity,
&data.Rainfall, &data.CompassAngle, &data.SolarRadiation,
)
if err != nil {
return nil, fmt.Errorf("扫描气象站数据失败: %v", err)
}
result = append(result, data)
}
return result, nil
}
func GetRainGaugeDataByTimeRange(start, end time.Time) ([]models.RainGaugeData, error) {
rows, err := db.Query(models.QueryRainGaugeDataByTimeRangeSQL, start, end)
if err != nil {
return nil, fmt.Errorf("查询雨量计数据失败: %v", err)
}
defer rows.Close()
var result []models.RainGaugeData
for rows.Next() {
var data models.RainGaugeData
err := rows.Scan(
&data.ID, &data.Timestamp, &data.DailyRainfall, &data.InstantRainfall,
&data.YesterdayRainfall, &data.TotalRainfall, &data.HourlyRainfall,
&data.LastHourRainfall, &data.Max24hRainfall, &data.Max24hRainfallPeriod,
&data.Min24hRainfall, &data.Min24hRainfallPeriod,
)
if err != nil {
return nil, fmt.Errorf("扫描雨量计数据失败: %v", err)
}
result = append(result, data)
}
return result, nil
}
func GetLatestWeatherData() (*models.WeatherData, error) {
row := db.QueryRow(models.QueryLatestWeatherDataSQL)
if row == nil {
return nil, fmt.Errorf("没有气象站数据")
}
data := &models.WeatherData{}
err := row.Scan(
&data.ID, &data.Timestamp, &data.WindSpeed, &data.WindForce, &data.WindDirection8,
&data.WindDirection360, &data.Humidity, &data.Temperature, &data.Noise, &data.PM25,
&data.PM10, &data.AtmPressure, &data.LuxHigh, &data.LuxLow, &data.LightIntensity,
&data.Rainfall, &data.CompassAngle, &data.SolarRadiation,
)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
return nil, fmt.Errorf("扫描最新气象站数据失败: %v", err)
}
return data, nil
}
func GetLatestRainGaugeData() (*models.RainGaugeData, error) {
row := db.QueryRow(models.QueryLatestRainGaugeDataSQL)
if row == nil {
return nil, fmt.Errorf("没有雨量计数据")
}
data := &models.RainGaugeData{}
err := row.Scan(
&data.ID, &data.Timestamp, &data.DailyRainfall, &data.InstantRainfall,
&data.YesterdayRainfall, &data.TotalRainfall, &data.HourlyRainfall,
&data.LastHourRainfall, &data.Max24hRainfall, &data.Max24hRainfallPeriod,
&data.Min24hRainfall, &data.Min24hRainfallPeriod,
)
if err == sql.ErrNoRows {
return nil, nil
} else if err != nil {
return nil, fmt.Errorf("扫描最新雨量计数据失败: %v", err)
}
return data, nil
}
func GetAggregatedData(start, end time.Time) ([]models.AggregatedData, error) {
log.Printf("GetAggregatedData调用 - 时间范围: 开始=%v, 结束=%v", start, end)
rows, err := db.Query(models.QueryAggregatedDataSQL, start, end, start, end)
if err != nil {
log.Printf("SQL查询失败: %v", err)
return nil, fmt.Errorf("查询聚合数据失败: %v", err)
}
defer rows.Close()
var result []models.AggregatedData
for rows.Next() {
var data models.AggregatedData
var timestampStr string
err := rows.Scan(
&timestampStr, &data.Rainfall, &data.AvgTemperature, &data.AvgHumidity,
&data.AvgWindSpeed, &data.AtmPressure, &data.SolarRadiation,
)
if err != nil {
log.Printf("扫描行数据失败: %v", err)
return nil, fmt.Errorf("扫描聚合数据失败: %v", err)
}
data.FormattedTime = timestampStr
result = append(result, data)
}
log.Printf("查询结果: 找到 %d 条记录", len(result))
return result, nil
}