feat: 新增 485 的解析
This commit is contained in:
parent
a6fa18f5cc
commit
523f489e11
26
main.go
26
main.go
@ -128,24 +128,36 @@ func startUDP() {
|
||||
asciiDump := asciiDump(rawData)
|
||||
log.Printf("ASCII码:\n%s", asciiDump)
|
||||
|
||||
weatherData, err := model.ParseData(rawData)
|
||||
data, deviceType, err := model.ParseData(rawData)
|
||||
if err != nil {
|
||||
log.Printf("解析数据失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
log.Println("成功解析气象站数据:")
|
||||
log.Printf("设备类型: %s", getDeviceTypeString(weatherData.DeviceType))
|
||||
log.Println(weatherData)
|
||||
log.Printf("设备类型: %s", getDeviceTypeString(deviceType))
|
||||
log.Println(data)
|
||||
|
||||
if weatherData.StationID != "" {
|
||||
model.RegisterDevice(weatherData.StationID, addr)
|
||||
log.Printf("设备 %s 已注册,IP: %s", weatherData.StationID, addr.String())
|
||||
var stationID string
|
||||
switch v := data.(type) {
|
||||
case *model.WeatherData:
|
||||
stationID = v.StationID
|
||||
case *model.RS485WeatherData:
|
||||
// 设备ID格式: HSB(21) MSB(22) LSB(1)
|
||||
hsb := rawData[21] // HSB: bit 168-175 (索引21)
|
||||
msb := rawData[22] // MSB: bit 176-183 (索引22)
|
||||
lsb := rawData[1] // LSB: bit 8-15 (索引1)
|
||||
stationID = fmt.Sprintf("RS485-%02X%02X%02X", hsb, msb, lsb)
|
||||
}
|
||||
|
||||
if stationID != "" {
|
||||
model.RegisterDevice(stationID, addr)
|
||||
log.Printf("设备 %s 已注册,IP: %s", stationID, addr.String())
|
||||
} else {
|
||||
log.Printf("警告: 收到的数据没有站点ID")
|
||||
}
|
||||
|
||||
err = model.SaveWeatherData(weatherData, string(rawData))
|
||||
err = model.SaveWeatherData(data, string(rawData))
|
||||
if err != nil {
|
||||
log.Printf("保存数据到数据库失败: %v", err)
|
||||
} else {
|
||||
|
||||
56
model/db.go
56
model/db.go
@ -92,32 +92,28 @@ func ensureStationExists(stationID, password string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func SaveWeatherData(data *WeatherData, rawData string) error {
|
||||
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
|
||||
}
|
||||
|
||||
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(`
|
||||
_, 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,
|
||||
@ -125,7 +121,7 @@ func saveWIFIWeatherData(data *WeatherData, rawData string, timestamp time.Time)
|
||||
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,
|
||||
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),
|
||||
@ -139,25 +135,21 @@ func saveWIFIWeatherData(data *WeatherData, rawData string, timestamp time.Time)
|
||||
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
|
||||
func saveRS485WeatherData(data *RS485WeatherData) error {
|
||||
err := ensureStationExists(data.StationID, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := db.Exec(`
|
||||
_, 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)
|
||||
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)
|
||||
|
||||
@ -16,8 +16,8 @@ const (
|
||||
DeviceTypeRS485
|
||||
)
|
||||
|
||||
// WeatherData 存储WIFI设备的气象数据
|
||||
type WeatherData struct {
|
||||
DeviceType DeviceType
|
||||
StationID string
|
||||
Password string
|
||||
TempF float64
|
||||
@ -47,17 +47,52 @@ type WeatherData struct {
|
||||
RTFreq int
|
||||
}
|
||||
|
||||
// RS485WeatherData 存储RS485设备的气象数据
|
||||
type RS485WeatherData struct {
|
||||
StationID string // 站点ID
|
||||
Timestamp time.Time // 时间戳
|
||||
Temperature float64 // 温度
|
||||
Humidity float64 // 湿度
|
||||
WindSpeed float64 // 风速
|
||||
WindDirection float64 // 风向
|
||||
Rainfall float64 // 雨量
|
||||
Light float64 // 光照
|
||||
UV float64 // 紫外线
|
||||
Pressure float64 // 气压
|
||||
RawData string // 原始数据
|
||||
}
|
||||
|
||||
var urlRegex = regexp.MustCompile(`/weatherstation/updateweatherstation\.php\?([^&\s]+(&[^&\s]+)*)`)
|
||||
|
||||
// ParseData 根据数据类型解析气象数据
|
||||
func ParseData(data []byte) (*WeatherData, error) {
|
||||
func ParseData(data []byte) (interface{}, DeviceType, error) {
|
||||
// 检查是否为RS485数据
|
||||
if len(data) == 25 && data[0] == 0x24 {
|
||||
return ParseRS485WeatherData(data)
|
||||
protocol := NewRS485Protocol(data)
|
||||
rs485Data, err := protocol.ParseRS485Data()
|
||||
if err != nil {
|
||||
return nil, DeviceTypeRS485, err
|
||||
}
|
||||
|
||||
weatherData := &RS485WeatherData{
|
||||
StationID: fmt.Sprintf("RS485-%02X%02X", data[1], data[2]),
|
||||
Timestamp: time.Now(),
|
||||
Temperature: rs485Data.Temperature,
|
||||
Humidity: rs485Data.Humidity,
|
||||
WindSpeed: rs485Data.WindSpeed,
|
||||
WindDirection: rs485Data.WindDirection,
|
||||
Rainfall: rs485Data.Rainfall,
|
||||
Light: rs485Data.Light,
|
||||
UV: rs485Data.UV,
|
||||
Pressure: rs485Data.Pressure,
|
||||
RawData: fmt.Sprintf("%X", data),
|
||||
}
|
||||
return weatherData, DeviceTypeRS485, nil
|
||||
}
|
||||
|
||||
// 尝试解析为WIFI数据
|
||||
return ParseWIFIWeatherData(string(data))
|
||||
wifiData, err := ParseWIFIWeatherData(string(data))
|
||||
return wifiData, DeviceTypeWIFI, err
|
||||
}
|
||||
|
||||
// ParseWIFIWeatherData 解析WIFI设备数据
|
||||
@ -73,10 +108,7 @@ func ParseWIFIWeatherData(data string) (*WeatherData, error) {
|
||||
return nil, fmt.Errorf("解析查询参数失败: %v", err)
|
||||
}
|
||||
|
||||
wd := &WeatherData{
|
||||
DeviceType: DeviceTypeWIFI,
|
||||
DateUTC: time.Now().UTC().Format("2006-01-02 15:04:05"),
|
||||
}
|
||||
wd := &WeatherData{}
|
||||
|
||||
wd.StationID = values.Get("ID")
|
||||
wd.Password = values.Get("PASSWORD")
|
||||
@ -174,48 +206,6 @@ func ParseWIFIWeatherData(data string) (*WeatherData, error) {
|
||||
return wd, nil
|
||||
}
|
||||
|
||||
// ParseRS485WeatherData 解析RS485设备数据
|
||||
func ParseRS485WeatherData(data []byte) (*WeatherData, error) {
|
||||
protocol := NewRS485Protocol(data)
|
||||
rs485Data, err := protocol.ParseRS485Data()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
wd := &WeatherData{
|
||||
DeviceType: DeviceTypeRS485,
|
||||
DateUTC: time.Now().UTC().Format("2006-01-02 15:04:05"),
|
||||
StationID: fmt.Sprintf("RS485-%02X%02X", data[1], data[2]), // 使用前两个字节作为设备ID
|
||||
}
|
||||
|
||||
// 转换温度(摄氏度到华氏度)
|
||||
wd.TempF = rs485Data.Temperature*9/5 + 32
|
||||
|
||||
// 转换湿度(直接使用)
|
||||
wd.Humidity = int(rs485Data.Humidity)
|
||||
|
||||
// 转换风向(直接使用)
|
||||
wd.WindDir = int(rs485Data.WindDirection)
|
||||
|
||||
// 转换风速(m/s到mph)
|
||||
wd.WindSpeedMph = rs485Data.WindSpeed * 2.23694
|
||||
|
||||
// 转换降雨量(mm到inch)
|
||||
wd.RainIn = rs485Data.Rainfall / 25.4
|
||||
|
||||
// 转换光照(直接使用)
|
||||
wd.SolarRadiation = rs485Data.Light
|
||||
|
||||
// 转换UV(直接使用)
|
||||
wd.UV = int(rs485Data.UV)
|
||||
|
||||
// 转换气压(hPa到inHg)
|
||||
wd.BarometerIn = rs485Data.Pressure / 33.8639
|
||||
wd.AbsBarometerIn = wd.BarometerIn
|
||||
|
||||
return wd, nil
|
||||
}
|
||||
|
||||
func (w *WeatherData) String() string {
|
||||
return fmt.Sprintf(`
|
||||
站点ID: %s
|
||||
@ -266,3 +256,28 @@ func (w *WeatherData) String() string {
|
||||
w.DateUTC,
|
||||
)
|
||||
}
|
||||
|
||||
func (w *RS485WeatherData) String() string {
|
||||
return fmt.Sprintf(`
|
||||
站点ID: %s
|
||||
温度: %.1f°C
|
||||
湿度: %.1f%%
|
||||
风向: %.1f°
|
||||
风速: %.2f m/s
|
||||
降雨量: %.2f mm
|
||||
光照: %.2f lux
|
||||
紫外线: %.2f
|
||||
气压: %.2f hPa
|
||||
时间: %s`,
|
||||
w.StationID,
|
||||
w.Temperature,
|
||||
w.Humidity,
|
||||
w.WindDirection,
|
||||
w.WindSpeed,
|
||||
w.Rainfall,
|
||||
w.Light,
|
||||
w.UV,
|
||||
w.Pressure,
|
||||
w.Timestamp.Format("2006-01-02 15:04:05"),
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user