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