2025-11-05 18:25:34 +08:00

148 lines
3.7 KiB
Go

package server
import (
"fmt"
"net/http"
"strconv"
"strings"
"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) {
idParam := c.Query("hex_id")
startTime := c.Query("start_time")
endTime := c.Query("end_time")
interval := c.DefaultQuery("interval", "1hour")
if idParam == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "missing hex_id"})
return
}
upper := strings.ToUpper(idParam)
var b strings.Builder
for i := 0; i < len(upper); i++ {
ch := upper[i]
if (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'F') {
b.WriteByte(ch)
}
}
hex := b.String()
if hex == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid hex_id"})
return
}
if len(hex) < 6 {
hex = strings.Repeat("0", 6-len(hex)) + hex
} else if len(hex) > 6 {
hex = hex[len(hex)-6:]
}
stationID := fmt.Sprintf("RS485-%s", hex)
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)
}