package server import ( "fmt" "net/http" "strconv" "time" "weatherstation/core/internal/data" ) import "github.com/gin-gonic/gin" func handleHealth(c *gin.Context) { c.JSON(http.StatusOK, gin.H{"status": "ok", "ts": time.Now().UTC().Format(time.RFC3339)}) } func handleSystemStatus(c *gin.Context) { online := data.OnlineDevices() c.JSON(http.StatusOK, gin.H{ "online_devices": online, "server_time": time.Now().Format("2006-01-02 15:04:05"), }) } func handleStations(c *gin.Context) { stations, err := data.Stations() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("query stations failed: %v", err)}) return } for i := range stations { if len(stations[i].StationID) > 6 { hexID := stations[i].StationID[len(stations[i].StationID)-6:] if decimalID, err := strconv.ParseInt(hexID, 16, 64); err == nil { stations[i].DecimalID = strconv.FormatInt(decimalID, 10) } } } c.JSON(http.StatusOK, stations) } func handleData(c *gin.Context) { dec := c.Query("decimal_id") startTime := c.Query("start_time") endTime := c.Query("end_time") interval := c.DefaultQuery("interval", "1hour") decimalNum, err := strconv.ParseInt(dec, 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid decimal_id"}) return } hexID := fmt.Sprintf("%06X", decimalNum) stationID := fmt.Sprintf("RS485-%s", hexID) loc, _ := time.LoadLocation("Asia/Shanghai") if loc == nil { loc = time.FixedZone("CST", 8*3600) } start, err := time.ParseInLocation("2006-01-02 15:04:05", startTime, loc) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid start_time"}) return } end, err := time.ParseInLocation("2006-01-02 15:04:05", endTime, loc) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid end_time"}) return } var points interface{} if interval == "raw" { points, err = data.SeriesRaw(stationID, start, end) } else { points, err = data.SeriesFrom10Min(stationID, start, end, interval) } if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("query failed: %v", err)}) return } c.JSON(http.StatusOK, points) } func handleForecast(c *gin.Context) { stationID := c.Query("station_id") from := c.Query("from") to := c.Query("to") provider := c.Query("provider") versionsStr := c.DefaultQuery("versions", "1") versions, _ := strconv.Atoi(versionsStr) if versions <= 0 { versions = 1 } if stationID == "" { c.JSON(http.StatusBadRequest, gin.H{"error": "missing station_id"}) return } loc, _ := time.LoadLocation("Asia/Shanghai") if loc == nil { loc = time.FixedZone("CST", 8*3600) } var start, end time.Time var err error if from == "" || to == "" { now := time.Now().In(loc) start = now.Truncate(time.Hour).Add(1 * time.Hour) end = start.Add(3 * time.Hour) } else { start, err = time.ParseInLocation("2006-01-02 15:04:05", from, loc) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid from"}) return } end, err = time.ParseInLocation("2006-01-02 15:04:05", to, loc) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "invalid to"}) return } } points, err := data.Forecast(stationID, start, end, provider, versions) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("query forecast failed: %v", err)}) return } c.JSON(http.StatusOK, points) }