package api import ( "encoding/json" "log" "net/http" "rain_monitor/db" "rain_monitor/modbus" "rain_monitor/models" "time" ) func StartWebServer() { http.HandleFunc("/api/status", handleStatus) http.HandleFunc("/api/raw/latest", handleLatestRawData) http.HandleFunc("/api/trigger-query", handleTriggerQuery) http.HandleFunc("/api/data", handleQueryData) http.HandleFunc("/api/latest", handleLatestData) http.Handle("/", http.FileServer(http.Dir("static"))) log.Println("Web服务器已启动,监听端口 10003") err := http.ListenAndServe(":10003", nil) if err != nil { log.Fatalf("Web服务器启动失败: %v", err) } } func handleStatus(w http.ResponseWriter, r *http.Request) { status := modbus.GetConnectionStatus() w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(status) } func handleLatestRawData(w http.ResponseWriter, r *http.Request) { weatherData, err1 := db.GetLatestWeatherData() rainData, err2 := db.GetLatestRainGaugeData() if (weatherData == nil && rainData == nil) || (err1 != nil && err2 != nil) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusNotFound) json.NewEncoder(w).Encode(map[string]interface{}{ "error": "没有可用的数据", "details": map[string]interface{}{ "weather_error": err1, "rain_error": err2, }, }) return } result := map[string]interface{}{} if weatherData != nil && !weatherData.Timestamp.IsZero() { result["timestamp"] = weatherData.Timestamp.Format(time.RFC3339) result["formatted_time"] = weatherData.Timestamp.Format("2006-01-02 15:04:05") } else if rainData != nil && !rainData.Timestamp.IsZero() { result["timestamp"] = rainData.Timestamp.Format(time.RFC3339) result["formatted_time"] = rainData.Timestamp.Format("2006-01-02 15:04:05") } else { result["timestamp"] = time.Now().Format(time.RFC3339) result["formatted_time"] = time.Now().Format("2006-01-02 15:04:05") } if weatherData != nil { result["temperature"] = weatherData.Temperature result["humidity"] = weatherData.Humidity result["wind_speed"] = weatherData.WindSpeed result["wind_direction_8"] = weatherData.WindDirection8 result["wind_direction_360"] = weatherData.WindDirection360 result["atm_pressure"] = weatherData.AtmPressure result["solar_radiation"] = weatherData.SolarRadiation result["weather_rainfall"] = weatherData.Rainfall } if rainData != nil { result["total_rainfall"] = rainData.TotalRainfall result["daily_rainfall"] = rainData.DailyRainfall result["instant_rainfall"] = rainData.InstantRainfall } if rainData != nil { result["rainfall"] = rainData.TotalRainfall } else if weatherData != nil { result["rainfall"] = weatherData.Rainfall } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(result) } func handleTriggerQuery(w http.ResponseWriter, r *http.Request) { err1 := modbus.QueryDevice(modbus.DeviceWeatherStation) err2 := modbus.QueryDevice(modbus.DeviceRainGauge) result := map[string]interface{}{ "success": err1 == nil || err2 == nil, "timestamp": time.Now().Format(time.RFC3339), } if err1 != nil { result["weather_error"] = err1.Error() } if err2 != nil { result["rain_error"] = err2.Error() } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(result) } func handleQueryData(w http.ResponseWriter, r *http.Request) { startStr := r.URL.Query().Get("start") endStr := r.URL.Query().Get("end") interval := r.URL.Query().Get("interval") log.Printf("handleQueryData - 请求参数: start=%s, end=%s, interval=%s", startStr, endStr, interval) if startStr == "" || endStr == "" { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "缺少必要的时间参数"}) return } start, err := time.Parse(time.RFC3339, startStr) if err != nil { log.Printf("开始时间解析失败: %v", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "开始时间格式错误"}) return } end, err := time.Parse(time.RFC3339, endStr) if err != nil { log.Printf("结束时间解析失败: %v", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "结束时间格式错误"}) return } data, err := db.GetAggregatedData(start, end) if err != nil { log.Printf("查询聚合数据失败: %v", err) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode([]models.AggregatedData{}) return } log.Printf("查询成功,返回 %d 条记录", len(data)) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) } func handleLatestData(w http.ResponseWriter, r *http.Request) { startStr := r.URL.Query().Get("start") endStr := r.URL.Query().Get("end") interval := r.URL.Query().Get("interval") log.Printf("handleLatestData - 请求参数: start=%s, end=%s, interval=%s", startStr, endStr, interval) if startStr == "" || endStr == "" { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "缺少必要的时间参数"}) return } start, err := time.Parse(time.RFC3339, startStr) if err != nil { log.Printf("开始时间解析失败: %v", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "开始时间格式错误"}) return } end, err := time.Parse(time.RFC3339, endStr) if err != nil { log.Printf("结束时间解析失败: %v", err) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]interface{}{"error": "结束时间格式错误"}) return } data, err := db.GetAggregatedData(start, end) if err != nil { log.Printf("查询聚合数据失败: %v", err) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode([]models.AggregatedData{}) return } log.Printf("查询成功,返回 %d 条记录", len(data)) w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(data) }