70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package server
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
"weatherstation/core/internal/data"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// GET /api/radar/weather_nearest?lat=..&lon=..&dt=YYYY-MM-DD HH:MM:SS
|
|
func handleRadarWeatherNearest(c *gin.Context) {
|
|
latStr := c.Query("lat")
|
|
lonStr := c.Query("lon")
|
|
if latStr == "" || lonStr == "" {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "missing lat/lon"})
|
|
return
|
|
}
|
|
lat, err1 := strconv.ParseFloat(latStr, 64)
|
|
lon, err2 := strconv.ParseFloat(lonStr, 64)
|
|
if err1 != nil || err2 != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid lat/lon"})
|
|
return
|
|
}
|
|
dtStr := c.Query("dt")
|
|
loc, _ := time.LoadLocation("Asia/Shanghai")
|
|
if loc == nil {
|
|
loc = time.FixedZone("CST", 8*3600)
|
|
}
|
|
dt := time.Now().In(loc)
|
|
if dtStr != "" {
|
|
if x, err := time.ParseInLocation("2006-01-02 15:04:05", dtStr, loc); err == nil {
|
|
dt = x
|
|
}
|
|
}
|
|
// search window +/- 6h
|
|
rw, err := data.RadarWeatherNearest(lat, lon, dt, 6*time.Hour)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": "query failed"})
|
|
return
|
|
}
|
|
if rw == nil {
|
|
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
|
|
return
|
|
}
|
|
c.JSON(http.StatusOK, gin.H{
|
|
"alias": rw.Alias,
|
|
"lat": rw.Lat,
|
|
"lon": rw.Lon,
|
|
"dt": rw.DT.In(loc).Format("2006-01-02 15:04:05"),
|
|
"temperature": f64(rw.Temperature),
|
|
"humidity": f64(rw.Humidity),
|
|
"cloudrate": f64(rw.CloudRate),
|
|
"visibility": f64(rw.Visibility),
|
|
"dswrf": f64(rw.DSWRF),
|
|
"wind_speed": f64(rw.WindSpeed),
|
|
"wind_direction": f64(rw.WindDirection),
|
|
"pressure": f64(rw.Pressure),
|
|
})
|
|
}
|
|
|
|
func f64(v sql.NullFloat64) interface{} {
|
|
if v.Valid {
|
|
return v.Float64
|
|
}
|
|
return nil
|
|
}
|