package model import ( "database/sql" "fmt" "time" "weatherstation/config" _ "github.com/lib/pq" ) var db *sql.DB func InitDB() error { cfg := config.GetConfig() connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", cfg.Database.Host, cfg.Database.Port, cfg.Database.User, cfg.Database.Password, cfg.Database.DBName, cfg.Database.SSLMode) var err error db, err = sql.Open("postgres", connStr) if err != nil { return fmt.Errorf("无法连接到数据库: %v", err) } err = db.Ping() if err != nil { return fmt.Errorf("数据库连接测试失败: %v", err) } // 创建RS485数据表 err = createRS485Table() if err != nil { return fmt.Errorf("创建RS485数据表失败: %v", err) } return nil } func createRS485Table() error { _, err := db.Exec(` CREATE TABLE IF NOT EXISTS rs485_weather_data ( id SERIAL PRIMARY KEY, station_id VARCHAR(50) NOT NULL, timestamp TIMESTAMP NOT NULL, temperature DECIMAL(5,2), -- 温度(摄氏度) humidity DECIMAL(5,2), -- 湿度(%) wind_speed DECIMAL(5,2), -- 风速(m/s) wind_direction DECIMAL(5,2), -- 风向(度) rainfall DECIMAL(5,2), -- 降雨量(mm) light DECIMAL(10,2), -- 光照(lux) uv DECIMAL(5,2), -- 紫外线 pressure DECIMAL(7,2), -- 气压(hPa) raw_data TEXT, -- 原始数据 FOREIGN KEY (station_id) REFERENCES stations(station_id) )`) return err } func CloseDB() { if db != nil { db.Close() } } func ensureStationExists(stationID, password string) error { if db == nil { return fmt.Errorf("数据库未初始化") } var count int err := db.QueryRow("SELECT COUNT(*) FROM stations WHERE station_id = $1", stationID).Scan(&count) if err != nil { return fmt.Errorf("查询站点失败: %v", err) } if count == 0 { _, err = db.Exec("INSERT INTO stations (station_id, password) VALUES ($1, $2)", stationID, password) if err != nil { return fmt.Errorf("添加站点失败: %v", err) } } else { _, err = db.Exec("UPDATE stations SET password = $1, last_update = $2 WHERE station_id = $3", password, time.Now(), stationID) if err != nil { return fmt.Errorf("更新站点失败: %v", err) } } return nil } func SaveWeatherData(data interface{}, rawData string) error { if db == nil { return fmt.Errorf("数据库未初始化") } switch v := data.(type) { case *WeatherData: return saveWIFIWeatherData(v, rawData) case *RS485WeatherData: return saveRS485WeatherData(v) default: return fmt.Errorf("未知的数据类型") } } func saveWIFIWeatherData(data *WeatherData, rawData string) error { err := ensureStationExists(data.StationID, data.Password) if err != nil { return err } _, err = db.Exec(` INSERT INTO weather_data ( station_id, timestamp, temp_f, humidity, dewpoint_f, windchill_f, wind_dir, wind_speed_mph, wind_gust_mph, rain_in, daily_rain_in, weekly_rain_in, monthly_rain_in, yearly_rain_in, total_rain_in, solar_radiation, uv, indoor_temp_f, indoor_humidity, abs_barometer_in, barometer_in, low_battery, raw_data ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23)`, data.StationID, time.Now(), int(data.TempF*10), data.Humidity, int(data.DewpointF*10), int(data.WindchillF*10), data.WindDir, int(data.WindSpeedMph*100), int(data.WindGustMph*100), int(data.RainIn*1000), int(data.DailyRainIn*1000), int(data.WeeklyRainIn*1000), int(data.MonthlyRainIn*1000), int(data.YearlyRainIn*1000), int(data.TotalRainIn*1000), int(data.SolarRadiation*100), data.UV, int(data.IndoorTempF*10), data.IndoorHumidity, int(data.AbsBarometerIn*1000), int(data.BarometerIn*1000), data.LowBattery, rawData) if err != nil { return fmt.Errorf("保存WIFI气象数据失败: %v", err) } return nil } func saveRS485WeatherData(data *RS485WeatherData) error { err := ensureStationExists(data.StationID, "") if err != nil { return err } _, err = db.Exec(` INSERT INTO rs485_weather_data ( station_id, timestamp, temperature, humidity, wind_speed, wind_direction, rainfall, light, uv, pressure, raw_data ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, data.StationID, data.Timestamp, data.Temperature, data.Humidity, data.WindSpeed, data.WindDirection, data.Rainfall, data.Light, data.UV, data.Pressure, data.RawData) if err != nil { return fmt.Errorf("保存RS485气象数据失败: %v", err) } return nil }