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)
|
asciiDump := asciiDump(rawData)
|
||||||
log.Printf("ASCII码:\n%s", asciiDump)
|
log.Printf("ASCII码:\n%s", asciiDump)
|
||||||
|
|
||||||
weatherData, err := model.ParseData(rawData)
|
data, deviceType, err := model.ParseData(rawData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("解析数据失败: %v", err)
|
log.Printf("解析数据失败: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("成功解析气象站数据:")
|
log.Println("成功解析气象站数据:")
|
||||||
log.Printf("设备类型: %s", getDeviceTypeString(weatherData.DeviceType))
|
log.Printf("设备类型: %s", getDeviceTypeString(deviceType))
|
||||||
log.Println(weatherData)
|
log.Println(data)
|
||||||
|
|
||||||
if weatherData.StationID != "" {
|
var stationID string
|
||||||
model.RegisterDevice(weatherData.StationID, addr)
|
switch v := data.(type) {
|
||||||
log.Printf("设备 %s 已注册,IP: %s", weatherData.StationID, addr.String())
|
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 {
|
} else {
|
||||||
log.Printf("警告: 收到的数据没有站点ID")
|
log.Printf("警告: 收到的数据没有站点ID")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = model.SaveWeatherData(weatherData, string(rawData))
|
err = model.SaveWeatherData(data, string(rawData))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("保存数据到数据库失败: %v", err)
|
log.Printf("保存数据到数据库失败: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
56
model/db.go
56
model/db.go
@ -92,32 +92,28 @@ func ensureStationExists(stationID, password string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SaveWeatherData(data *WeatherData, rawData string) error {
|
func SaveWeatherData(data interface{}, rawData string) error {
|
||||||
if db == nil {
|
if db == nil {
|
||||||
return fmt.Errorf("数据库未初始化")
|
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)
|
err := ensureStationExists(data.StationID, data.Password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
cst := time.FixedZone("CST", 8*60*60)
|
_, err = db.Exec(`
|
||||||
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 (
|
INSERT INTO weather_data (
|
||||||
station_id, timestamp, temp_f, humidity, dewpoint_f, windchill_f,
|
station_id, timestamp, temp_f, humidity, dewpoint_f, windchill_f,
|
||||||
wind_dir, wind_speed_mph, wind_gust_mph, rain_in, daily_rain_in,
|
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,
|
solar_radiation, uv, indoor_temp_f, indoor_humidity,
|
||||||
abs_barometer_in, barometer_in, low_battery, raw_data
|
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)`,
|
) 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),
|
int(data.TempF*10), data.Humidity, int(data.DewpointF*10), int(data.WindchillF*10),
|
||||||
data.WindDir, int(data.WindSpeedMph*100), int(data.WindGustMph*100),
|
data.WindDir, int(data.WindSpeedMph*100), int(data.WindGustMph*100),
|
||||||
int(data.RainIn*1000), int(data.DailyRainIn*1000), int(data.WeeklyRainIn*1000),
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func saveRS485WeatherData(data *WeatherData, rawData string, timestamp time.Time) error {
|
func saveRS485WeatherData(data *RS485WeatherData) error {
|
||||||
// 将华氏度转换回摄氏度
|
err := ensureStationExists(data.StationID, "")
|
||||||
tempC := (data.TempF - 32) * 5 / 9
|
if err != nil {
|
||||||
// 将mph转换回m/s
|
return err
|
||||||
windSpeedMS := data.WindSpeedMph / 2.23694
|
}
|
||||||
// 将inch转换回mm
|
|
||||||
rainfallMM := data.RainIn * 25.4
|
|
||||||
// 将inHg转换回hPa
|
|
||||||
pressureHPa := data.BarometerIn * 33.8639
|
|
||||||
|
|
||||||
_, err := db.Exec(`
|
_, err = db.Exec(`
|
||||||
INSERT INTO rs485_weather_data (
|
INSERT INTO rs485_weather_data (
|
||||||
station_id, timestamp, temperature, humidity, wind_speed,
|
station_id, timestamp, temperature, humidity, wind_speed,
|
||||||
wind_direction, rainfall, light, uv, pressure, raw_data
|
wind_direction, rainfall, light, uv, pressure, raw_data
|
||||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
|
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`,
|
||||||
data.StationID, timestamp,
|
data.StationID, data.Timestamp,
|
||||||
tempC, data.Humidity, windSpeedMS,
|
data.Temperature, data.Humidity, data.WindSpeed,
|
||||||
data.WindDir, rainfallMM, data.SolarRadiation,
|
data.WindDirection, data.Rainfall, data.Light,
|
||||||
data.UV, pressureHPa, rawData)
|
data.UV, data.Pressure, data.RawData)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("保存RS485气象数据失败: %v", err)
|
return fmt.Errorf("保存RS485气象数据失败: %v", err)
|
||||||
|
|||||||
@ -16,8 +16,8 @@ const (
|
|||||||
DeviceTypeRS485
|
DeviceTypeRS485
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// WeatherData 存储WIFI设备的气象数据
|
||||||
type WeatherData struct {
|
type WeatherData struct {
|
||||||
DeviceType DeviceType
|
|
||||||
StationID string
|
StationID string
|
||||||
Password string
|
Password string
|
||||||
TempF float64
|
TempF float64
|
||||||
@ -47,17 +47,52 @@ type WeatherData struct {
|
|||||||
RTFreq int
|
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]+)*)`)
|
var urlRegex = regexp.MustCompile(`/weatherstation/updateweatherstation\.php\?([^&\s]+(&[^&\s]+)*)`)
|
||||||
|
|
||||||
// ParseData 根据数据类型解析气象数据
|
// ParseData 根据数据类型解析气象数据
|
||||||
func ParseData(data []byte) (*WeatherData, error) {
|
func ParseData(data []byte) (interface{}, DeviceType, error) {
|
||||||
// 检查是否为RS485数据
|
// 检查是否为RS485数据
|
||||||
if len(data) == 25 && data[0] == 0x24 {
|
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数据
|
// 尝试解析为WIFI数据
|
||||||
return ParseWIFIWeatherData(string(data))
|
wifiData, err := ParseWIFIWeatherData(string(data))
|
||||||
|
return wifiData, DeviceTypeWIFI, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseWIFIWeatherData 解析WIFI设备数据
|
// ParseWIFIWeatherData 解析WIFI设备数据
|
||||||
@ -73,10 +108,7 @@ func ParseWIFIWeatherData(data string) (*WeatherData, error) {
|
|||||||
return nil, fmt.Errorf("解析查询参数失败: %v", err)
|
return nil, fmt.Errorf("解析查询参数失败: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
wd := &WeatherData{
|
wd := &WeatherData{}
|
||||||
DeviceType: DeviceTypeWIFI,
|
|
||||||
DateUTC: time.Now().UTC().Format("2006-01-02 15:04:05"),
|
|
||||||
}
|
|
||||||
|
|
||||||
wd.StationID = values.Get("ID")
|
wd.StationID = values.Get("ID")
|
||||||
wd.Password = values.Get("PASSWORD")
|
wd.Password = values.Get("PASSWORD")
|
||||||
@ -174,48 +206,6 @@ func ParseWIFIWeatherData(data string) (*WeatherData, error) {
|
|||||||
return wd, nil
|
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 {
|
func (w *WeatherData) String() string {
|
||||||
return fmt.Sprintf(`
|
return fmt.Sprintf(`
|
||||||
站点ID: %s
|
站点ID: %s
|
||||||
@ -266,3 +256,28 @@ func (w *WeatherData) String() string {
|
|||||||
w.DateUTC,
|
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