From c216cfb46dbafe4a396ebb1694d4c2caa74a8e84 Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Tue, 26 Nov 2024 19:10:11 +0100 Subject: [PATCH] display next rain --- img.go | 50 ++++++++++++++++++++++++++++++++++++---------- weather/weather.go | 25 +++++++++++++++++++++-- 2 files changed, 63 insertions(+), 12 deletions(-) diff --git a/img.go b/img.go index e543f0e..3fe6af5 100644 --- a/img.go +++ b/img.go @@ -159,27 +159,57 @@ func drawWeather(ctx context.Context, gc *draw2dimg.GraphicContext, wthr *weathe dailyLen := len(wthr.Daily) dailyWeatherLen := len(wthr.Daily[0].Weather) - if dailyLen == 0 || dailyWeatherLen == 0 { - slog.ErrorContext(ctx, "missing daily or daily weather", "daily_len", dailyLen, "daily_weather_len", dailyWeatherLen) + currentWeatherLen := len(wthr.Current.Weather) + if dailyLen == 0 || dailyWeatherLen == 0 || currentWeatherLen == 0 { + slog.ErrorContext(ctx, "missing daily or daily weather or current weather", "daily_len", dailyLen, "daily_weather_len", dailyWeatherLen, "current_weather_len", currentWeatherLen) return } - daily := wthr.Daily[0] - dailyWeather := daily.Weather[0] - err := drawWeatherIcon(gc, wthr.Current.Weather[0]) + current := wthr.Current + currentWeather := current.Weather[0] + err := drawWeatherIcon(gc, currentWeather) if err != nil { slog.ErrorContext(ctx, "Failed to draw weather icon", "err", err) } - text(gc, formatTemp(wthr.Current.Temp), 23, leftX, 125, fonts.Regular) + text(gc, formatTemp(current.Temp), 23, leftX, 125, fonts.Regular) + text(gc, fmt.Sprintf("(%v)", formatTemp(current.FeelsLike)), 15, leftX+5, 150, fonts.Regular) - const xAlign = 120 + daily := wthr.Daily[0] + dailyWeather := daily.Weather[0] + + const xAlign = 140 const fontSize = 18 text(gc, "journée", fontSize, xAlign, 35, fonts.Bold) - text(gc, "max "+formatTemp(daily.Temp.Max), fontSize, xAlign, 65, fonts.Regular) - text(gc, fmt.Sprintf("pluie %v%%", int(math.Round(daily.Pop*100))), fontSize, xAlign, 95, fonts.Regular) - text(gc, dailyWeather.Description, fontSize, xAlign, 125, fonts.Regular) + text(gc, dailyWeather.Description, fontSize, xAlign, 65, fonts.Regular) + text(gc, "max "+formatTemp(daily.Temp.Max), fontSize, xAlign, 95, fonts.Regular) + text(gc, fmt.Sprintf("pluie %v%%", formatPct(daily.Pop)), fontSize, xAlign, 125, fonts.Regular) + + nextRainTime, nextRainProba := findNextRain(wthr.Hourly) // limit search to next 12 hours + if nextRainProba > 0 { + text(gc, "\uE06C", 14, xAlign, 155, fonts.Icons) + text(gc, fmt.Sprintf("%v (%v%%)", nextRainTime.Format("15h"), formatPct(nextRainProba)), 14, xAlign+fonts.IconXOffset, 155, fonts.Regular) + } +} + +func formatPct(pct float64) int { + return int(math.Round(pct * 100)) +} + +// return next timestamp & pop where pop > 0 +func findNextRain(hourly []weather.Hourly) (time.Time, float64) { + if len(hourly) > 12 { + hourly = hourly[:12] + } + + for _, h := range hourly { + if h.Pop > 0 { + return time.Unix(int64(h.Dt), 0), h.Pop + } + } + + return time.Time{}, 0 } func drawWeatherIcon(gc *draw2dimg.GraphicContext, dailyWeather weather.Weather) error { diff --git a/weather/weather.go b/weather/weather.go index e82be5f..a5e6979 100644 --- a/weather/weather.go +++ b/weather/weather.go @@ -55,8 +55,12 @@ type Prevision struct { Description string `json:"description"` Icon string `json:"icon"` } `json:"weather"` + Rain struct { + OneHour float64 `json:"1h"` + } `json:"rain"` } `json:"current"` - Daily []Daily `json:"daily"` + Daily []Daily `json:"daily"` + Hourly []Hourly `json:"hourly"` Alerts []struct { SenderName string `json:"sender_name"` Event string `json:"event"` @@ -150,6 +154,23 @@ type Weather struct { Icon string `json:"icon"` } +type Hourly struct { + Dt int `json:"dt"` + Temp float64 `json:"temp"` + FeelsLike float64 `json:"feels_like"` + Pressure int `json:"pressure"` + Humidity int `json:"humidity"` + DewPoint float64 `json:"dew_point"` + Uvi float64 `json:"uvi"` + Clouds int `json:"clouds"` + Visibility int `json:"visibility"` + WindSpeed float64 `json:"wind_speed"` + WindDeg int `json:"wind_deg"` + WindGust float64 `json:"wind_gust"` + Weather []Weather `json:"weather"` + Pop float64 `json:"pop"` +} + func (c *Client) GetWeather(ctx context.Context) (res *Prevision, err error) { if val, err := loadFromDisk(c.config.CacheLocation); nil == err { slog.InfoContext(ctx, "found weather in cache") @@ -165,7 +186,7 @@ func (c *Client) GetWeather(ctx context.Context) (res *Prevision, err error) { Param("appid", c.config.APIKey). Param("units", "metric"). Param("lang", "fr"). - Param("exclude", "minutely,hourly"). + Param("exclude", "minutely"). ToJSON(&res). Fetch(ctx) if err != nil {