package model import ( "fmt" "net/url" "regexp" "strconv" ) type WeatherData struct { StationID string Password string TempF float64 Humidity int DewpointF float64 WindchillF float64 WindDir int WindSpeedMph float64 WindGustMph float64 RainIn float64 DailyRainIn float64 WeeklyRainIn float64 MonthlyRainIn float64 YearlyRainIn float64 TotalRainIn float64 SolarRadiation float64 UV int IndoorTempF float64 IndoorHumidity int AbsBarometerIn float64 BarometerIn float64 LowBattery bool SoftwareType string DateUTC string Action string RealTime int RTFreq int } var urlRegex = regexp.MustCompile(`/weatherstation/updateweatherstation\.php\?([^&\s]+(&[^&\s]+)*)`) func ParseWeatherData(data string) (*WeatherData, error) { matches := urlRegex.FindStringSubmatch(data) if len(matches) < 2 { return nil, fmt.Errorf("无法找到有效的气象站数据URL") } queryString := matches[1] values, err := url.ParseQuery(queryString) if err != nil { return nil, fmt.Errorf("解析查询参数失败: %v", err) } wd := &WeatherData{} wd.StationID = values.Get("ID") wd.Password = values.Get("PASSWORD") wd.DateUTC = values.Get("dateutc") wd.SoftwareType = values.Get("softwaretype") wd.Action = values.Get("action") if tempF, err := strconv.ParseFloat(values.Get("tempf"), 64); err == nil { wd.TempF = tempF } if humidity, err := strconv.Atoi(values.Get("humidity")); err == nil { wd.Humidity = humidity } if dewpointF, err := strconv.ParseFloat(values.Get("dewptf"), 64); err == nil { wd.DewpointF = dewpointF } if windchillF, err := strconv.ParseFloat(values.Get("windchillf"), 64); err == nil { wd.WindchillF = windchillF } if windDir, err := strconv.Atoi(values.Get("winddir")); err == nil { wd.WindDir = windDir } if windSpeedMph, err := strconv.ParseFloat(values.Get("windspeedmph"), 64); err == nil { wd.WindSpeedMph = windSpeedMph } if windGustMph, err := strconv.ParseFloat(values.Get("windgustmph"), 64); err == nil { wd.WindGustMph = windGustMph } if rainIn, err := strconv.ParseFloat(values.Get("rainin"), 64); err == nil { wd.RainIn = rainIn } if dailyRainIn, err := strconv.ParseFloat(values.Get("dailyrainin"), 64); err == nil { wd.DailyRainIn = dailyRainIn } if weeklyRainIn, err := strconv.ParseFloat(values.Get("weeklyrainin"), 64); err == nil { wd.WeeklyRainIn = weeklyRainIn } if monthlyRainIn, err := strconv.ParseFloat(values.Get("monthlyrainin"), 64); err == nil { wd.MonthlyRainIn = monthlyRainIn } if yearlyRainIn, err := strconv.ParseFloat(values.Get("yearlyrainin"), 64); err == nil { wd.YearlyRainIn = yearlyRainIn } if totalRainIn, err := strconv.ParseFloat(values.Get("totalrainin"), 64); err == nil { wd.TotalRainIn = totalRainIn } if solarRadiation, err := strconv.ParseFloat(values.Get("solarradiation"), 64); err == nil { wd.SolarRadiation = solarRadiation } if uv, err := strconv.Atoi(values.Get("UV")); err == nil { wd.UV = uv } if indoorTempF, err := strconv.ParseFloat(values.Get("indoortempf"), 64); err == nil { wd.IndoorTempF = indoorTempF } if indoorHumidity, err := strconv.Atoi(values.Get("indoorhumidity")); err == nil { wd.IndoorHumidity = indoorHumidity } if absBarometerIn, err := strconv.ParseFloat(values.Get("absbaromin"), 64); err == nil { wd.AbsBarometerIn = absBarometerIn } if barometerIn, err := strconv.ParseFloat(values.Get("baromin"), 64); err == nil { wd.BarometerIn = barometerIn } if lowBatt, err := strconv.Atoi(values.Get("lowbatt")); err == nil { wd.LowBattery = lowBatt != 0 } if realTime, err := strconv.Atoi(values.Get("realtime")); err == nil { wd.RealTime = realTime } if rtFreq, err := strconv.Atoi(values.Get("rtfreq")); err == nil { wd.RTFreq = rtFreq } return wd, nil } func (w *WeatherData) String() string { return fmt.Sprintf(` 站点ID: %s 温度: %.1f°F (%.1f°C) 湿度: %d%% 露点: %.1f°F (%.1f°C) 风寒指数: %.1f°F (%.1f°C) 风向: %d° 风速: %.2f mph (%.2f km/h) 阵风: %.2f mph (%.2f km/h) 降雨量: %.3f 英寸 (%.2f mm) 日降雨量: %.3f 英寸 (%.2f mm) 周降雨量: %.3f 英寸 (%.2f mm) 月降雨量: %.3f 英寸 (%.2f mm) 年降雨量: %.3f 英寸 (%.2f mm) 总降雨量: %.3f 英寸 (%.2f mm) 太阳辐射: %.2f W/m² 紫外线指数: %d 室内温度: %.1f°F (%.1f°C) 室内湿度: %d%% 绝对气压: %.3f 英寸汞柱 (%.2f hPa) 相对气压: %.3f 英寸汞柱 (%.2f hPa) 低电量: %v 软件类型: %s 日期UTC: %s`, w.StationID, w.TempF, (w.TempF-32)*5/9, w.Humidity, w.DewpointF, (w.DewpointF-32)*5/9, w.WindchillF, (w.WindchillF-32)*5/9, w.WindDir, w.WindSpeedMph, w.WindSpeedMph*1.60934, w.WindGustMph, w.WindGustMph*1.60934, w.RainIn, w.RainIn*25.4, w.DailyRainIn, w.DailyRainIn*25.4, w.WeeklyRainIn, w.WeeklyRainIn*25.4, w.MonthlyRainIn, w.MonthlyRainIn*25.4, w.YearlyRainIn, w.YearlyRainIn*25.4, w.TotalRainIn, w.TotalRainIn*25.4, w.SolarRadiation, w.UV, w.IndoorTempF, (w.IndoorTempF-32)*5/9, w.IndoorHumidity, w.AbsBarometerIn, w.AbsBarometerIn*33.8639, w.BarometerIn, w.BarometerIn*33.8639, w.LowBattery, w.SoftwareType, w.DateUTC, ) }