167 lines
4.8 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 *WeatherData, rawData string) error {
if db == nil {
return fmt.Errorf("数据库未初始化")
}
err := ensureStationExists(data.StationID, data.Password)
if err != nil {
return err
}
cst := time.FixedZone("CST", 8*60*60)
timestamp := time.Now().In(cst)
// 根据设备类型选择不同的保存方法
switch data.DeviceType {
case DeviceTypeWIFI:
return saveWIFIWeatherData(data, rawData, timestamp)
case DeviceTypeRS485:
return saveRS485WeatherData(data, rawData, timestamp)
default:
return fmt.Errorf("未知的设备类型")
}
}
func saveWIFIWeatherData(data *WeatherData, rawData string, timestamp time.Time) error {
_, 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, timestamp,
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 *WeatherData, rawData string, timestamp time.Time) error {
// 将华氏度转换回摄氏度
tempC := (data.TempF - 32) * 5 / 9
// 将mph转换回m/s
windSpeedMS := data.WindSpeedMph / 2.23694
// 将inch转换回mm
rainfallMM := data.RainIn * 25.4
// 将inHg转换回hPa
pressureHPa := data.BarometerIn * 33.8639
_, 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, timestamp,
tempC, data.Humidity, windSpeedMS,
data.WindDir, rainfallMM, data.SolarRadiation,
data.UV, pressureHPa, rawData)
if err != nil {
return fmt.Errorf("保存RS485气象数据失败: %v", err)
}
return nil
}