159 lines
4.4 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 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
}