display weather & resize
|
@ -317,5 +317,5 @@ func (e *EPD) sendImg(img image.Image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isdark(r, g, b, _ uint32) bool {
|
func isdark(r, g, b, _ uint32) bool {
|
||||||
return r < 255 || g < 255 || b < 255
|
return r < 65535 || g < 65535 || b < 65535
|
||||||
}
|
}
|
||||||
|
|
BIN
icons/01d.png
Normal file
After Width: | Height: | Size: 945 B |
BIN
icons/02d.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
icons/03d.png
Normal file
After Width: | Height: | Size: 837 B |
BIN
icons/04d.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
icons/09d.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
icons/10d.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
icons/11d.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
icons/13d.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
icons/50d.png
Normal file
After Width: | Height: | Size: 650 B |
152
img.go
|
@ -2,43 +2,52 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/Crocmagnon/display-epaper/epd"
|
"github.com/Crocmagnon/display-epaper/epd"
|
||||||
"github.com/Crocmagnon/display-epaper/fete"
|
"github.com/Crocmagnon/display-epaper/fete"
|
||||||
"github.com/Crocmagnon/display-epaper/transports"
|
"github.com/Crocmagnon/display-epaper/transports"
|
||||||
|
"github.com/Crocmagnon/display-epaper/weather"
|
||||||
"github.com/llgcode/draw2d"
|
"github.com/llgcode/draw2d"
|
||||||
"github.com/llgcode/draw2d/draw2dimg"
|
"github.com/llgcode/draw2d/draw2dimg"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
|
"log"
|
||||||
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getBlack(
|
//go:embed icons
|
||||||
ctx context.Context,
|
var icons embed.FS
|
||||||
nowFunc func() time.Time,
|
|
||||||
transportsClient *transports.Client,
|
const (
|
||||||
feteClient *fete.Client,
|
leftX = 20
|
||||||
) (*image.RGBA, error) {
|
rightX = 530
|
||||||
|
)
|
||||||
|
|
||||||
|
func getBlack(ctx context.Context, nowFunc func() time.Time, transportsClient *transports.Client, feteClient *fete.Client, weatherClient *weather.Client) (*image.RGBA, error) {
|
||||||
bus, err := transportsClient.GetTCLPassages(ctx, 290)
|
bus, err := transportsClient.GetTCLPassages(ctx, 290)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting bus: %w", err)
|
log.Println("error getting bus:", err)
|
||||||
}
|
}
|
||||||
tram, err := transportsClient.GetTCLPassages(ctx, 34068)
|
tram, err := transportsClient.GetTCLPassages(ctx, 34068)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting tram: %w", err)
|
log.Println("error getting tram:", err)
|
||||||
}
|
}
|
||||||
velovRoc, err := transportsClient.GetVelovStation(ctx, 10044)
|
velovRoc, err := transportsClient.GetVelovStation(ctx, 10044)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting velov: %w", err)
|
log.Println("error getting velov:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fetes, err := feteClient.GetFete(ctx, nowFunc())
|
fetes, err := feteClient.GetFete(ctx, nowFunc())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("getting fetes: %w", err)
|
log.Println("error getting fetes:", err)
|
||||||
|
}
|
||||||
|
wthr, err := weatherClient.GetWeather(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error getting weather:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = fetes
|
|
||||||
|
|
||||||
img := newWhite()
|
img := newWhite()
|
||||||
|
|
||||||
|
@ -48,35 +57,93 @@ func getBlack(
|
||||||
gc.SetFillColor(color.RGBA{255, 255, 255, 255})
|
gc.SetFillColor(color.RGBA{255, 255, 255, 255})
|
||||||
gc.SetStrokeColor(color.RGBA{0, 0, 0, 255})
|
gc.SetStrokeColor(color.RGBA{0, 0, 0, 255})
|
||||||
|
|
||||||
rect(gc, 0, 0, 800, 480)
|
drawTCL(gc, bus, 55)
|
||||||
|
drawTCL(gc, tram, 190)
|
||||||
drawTCL(gc, bus, 30)
|
|
||||||
drawTCL(gc, tram, 180)
|
|
||||||
drawVelov(gc, velovRoc, 350)
|
drawVelov(gc, velovRoc, 350)
|
||||||
drawDateFete(gc, fetes, nowFunc())
|
drawDate(gc, nowFunc())
|
||||||
|
drawFete(gc, fetes)
|
||||||
|
drawWeather(gc, wthr)
|
||||||
|
|
||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawVelov(gc *draw2dimg.GraphicContext, station *transports.Station, yOffset float64) {
|
func drawWeather(gc *draw2dimg.GraphicContext, wthr *weather.Prevision) {
|
||||||
x := float64(600)
|
if wthr == nil {
|
||||||
text(gc, station.Name, 15, x, yOffset)
|
return
|
||||||
text(gc, fmt.Sprintf("V : %v - P : %v", station.BikesAvailable, station.DocksAvailable), 15, x, yOffset+30)
|
}
|
||||||
|
|
||||||
|
if len(wthr.Daily) == 0 || len(wthr.Daily[0].Weather) == 0 {
|
||||||
|
log.Println("missing daily or daily weather")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
daily := wthr.Daily[0]
|
||||||
|
dailyWeather := daily.Weather[0]
|
||||||
|
err := drawWeatherIcon(gc, dailyWeather)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Failed to draw weather icon:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
text(gc, formatTemp("Act", wthr.Current.Temp), 18, 100, 45)
|
||||||
|
text(gc, formatTemp("Max", daily.Temp.Max), 18, 220, 45)
|
||||||
|
text(gc, fmt.Sprintf("Pluie : %v%%", int(math.Round(daily.Pop))), 18, 100, 75)
|
||||||
|
text(gc, dailyWeather.Description, 18, leftX, 110)
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawDateFete(gc *draw2dimg.GraphicContext, fetes *fete.Fete, now time.Time) {
|
func drawWeatherIcon(gc *draw2dimg.GraphicContext, dailyWeather weather.Weather) error {
|
||||||
text(gc, now.Format("15:04"), 40, 20, 190)
|
icon := strings.TrimSuffix(dailyWeather.Icon, "d")
|
||||||
text(gc, getDate(now), 50, 20, 255)
|
icon = strings.TrimSuffix(icon, "n")
|
||||||
text(gc, fmt.Sprintf("On fête les %s", fetes.Name), 17, 20, 400)
|
f, err := icons.Open(fmt.Sprintf("icons/%sd.png", icon))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("opening icon: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
img, _, err := image.Decode(f)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("decoding icon: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
gc.DrawImage(img)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatTemp(name string, temp float64) string {
|
||||||
|
return fmt.Sprintf("%v : %v°C", name, int(math.Round(temp)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawVelov(gc *draw2dimg.GraphicContext, station *transports.Station, yOffset float64) {
|
||||||
|
if station == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
text(gc, station.Name, 23, rightX, yOffset)
|
||||||
|
text(gc, fmt.Sprintf("V : %v - P : %v", station.BikesAvailable, station.DocksAvailable), 23, rightX, yOffset+30)
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawDate(gc *draw2dimg.GraphicContext, now time.Time) {
|
||||||
|
text(gc, now.Format("15:04"), 60, leftX, 240)
|
||||||
|
text(gc, getDate(now), 30, leftX, 285)
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawFete(gc *draw2dimg.GraphicContext, fetes *fete.Fete) {
|
||||||
|
if fetes == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
text(gc, fmt.Sprintf("On fête les %s", fetes.Name), 18, leftX, 400)
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawTCL(gc *draw2dimg.GraphicContext, passages *transports.Passages, yoffset float64) {
|
func drawTCL(gc *draw2dimg.GraphicContext, passages *transports.Passages, yoffset float64) {
|
||||||
|
if passages == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for i, passage := range passages.Passages {
|
for i, passage := range passages.Passages {
|
||||||
x := float64(600 + i*100)
|
x := float64(rightX + i*120)
|
||||||
text(gc, passage.Ligne, 15, x, yoffset)
|
text(gc, passage.Ligne, 23, x, yoffset)
|
||||||
for j, delay := range passage.Delays {
|
for j, delay := range passage.Delays {
|
||||||
y := yoffset + float64(j+1)*30
|
y := yoffset + float64(j+1)*35
|
||||||
text(gc, delay, 15, x, y)
|
text(gc, delay, 23, x, y)
|
||||||
if j >= 2 { // limit number of delays displayed
|
if j >= 2 { // limit number of delays displayed
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -89,8 +156,6 @@ func text(gc *draw2dimg.GraphicContext, s string, size, x, y float64) {
|
||||||
gc.SetFontData(draw2d.FontData{Name: fontName})
|
gc.SetFontData(draw2d.FontData{Name: fontName})
|
||||||
gc.SetFontSize(size)
|
gc.SetFontSize(size)
|
||||||
gc.FillStringAt(s, x, y)
|
gc.FillStringAt(s, x, y)
|
||||||
gc.SetLineWidth(2)
|
|
||||||
gc.StrokeStringAt(s, x, y)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWhite() *image.RGBA {
|
func newWhite() *image.RGBA {
|
||||||
|
@ -114,7 +179,28 @@ func rect(gc *draw2dimg.GraphicContext, x1, y1, x2, y2 float64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDate(now time.Time) string {
|
func getDate(now time.Time) string {
|
||||||
return fmt.Sprintf("%v %v", getDay(now), getMonth(now))
|
return fmt.Sprintf("%v %v %v", getDow(now), getDay(now), getMonth(now))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDow(now time.Time) string {
|
||||||
|
switch now.Weekday() {
|
||||||
|
case time.Monday:
|
||||||
|
return "lun"
|
||||||
|
case time.Tuesday:
|
||||||
|
return "mar"
|
||||||
|
case time.Wednesday:
|
||||||
|
return "mer"
|
||||||
|
case time.Thursday:
|
||||||
|
return "jeu"
|
||||||
|
case time.Friday:
|
||||||
|
return "ven"
|
||||||
|
case time.Saturday:
|
||||||
|
return "sam"
|
||||||
|
case time.Sunday:
|
||||||
|
return "dim"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "?"
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDay(now time.Time) string {
|
func getDay(now time.Time) string {
|
||||||
|
|
7
main.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/Crocmagnon/display-epaper/fete"
|
"github.com/Crocmagnon/display-epaper/fete"
|
||||||
"github.com/Crocmagnon/display-epaper/transports"
|
"github.com/Crocmagnon/display-epaper/transports"
|
||||||
|
"github.com/Crocmagnon/display-epaper/weather"
|
||||||
"github.com/golang/freetype/truetype"
|
"github.com/golang/freetype/truetype"
|
||||||
"github.com/llgcode/draw2d"
|
"github.com/llgcode/draw2d"
|
||||||
_ "golang.org/x/image/bmp"
|
_ "golang.org/x/image/bmp"
|
||||||
|
@ -34,7 +35,11 @@ func main() {
|
||||||
CacheLocation: os.Getenv("FETE_CACHE_LOCATION"),
|
CacheLocation: os.Getenv("FETE_CACHE_LOCATION"),
|
||||||
})
|
})
|
||||||
|
|
||||||
if err := run(ctx, transportsClient, feteClient); err != nil {
|
weatherClient := weather.New(nil, weather.Config{
|
||||||
|
APIKey: os.Getenv("WEATHER_API_KEY"),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := run(ctx, transportsClient, feteClient, weatherClient); err != nil {
|
||||||
log.Fatal("error: ", err)
|
log.Fatal("error: ", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,25 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/Crocmagnon/display-epaper/fete"
|
"github.com/Crocmagnon/display-epaper/fete"
|
||||||
"github.com/Crocmagnon/display-epaper/transports"
|
"github.com/Crocmagnon/display-epaper/transports"
|
||||||
|
"github.com/Crocmagnon/display-epaper/weather"
|
||||||
"github.com/llgcode/draw2d/draw2dimg"
|
"github.com/llgcode/draw2d/draw2dimg"
|
||||||
"log"
|
"log"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func run(ctx context.Context, transportsClient *transports.Client, feteClient *fete.Client) error {
|
func run(
|
||||||
|
ctx context.Context,
|
||||||
|
transportsClient *transports.Client,
|
||||||
|
feteClient *fete.Client,
|
||||||
|
weatherClient *weather.Client,
|
||||||
|
) error {
|
||||||
img, err := getBlack(ctx, func() time.Time {
|
img, err := getBlack(ctx, func() time.Time {
|
||||||
t, err := time.Parse(time.DateOnly, "2024-08-01zzz")
|
t, err := time.Parse(time.DateOnly, "2024-08-01zzz")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Now()
|
return time.Now()
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
}, transportsClient, feteClient)
|
}, transportsClient, feteClient, weatherClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +30,5 @@ func run(ctx context.Context, transportsClient *transports.Client, feteClient *f
|
||||||
log.Fatalf("error saving image: %v", err)
|
log.Fatalf("error saving image: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Println("done")
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,18 @@ import (
|
||||||
"github.com/Crocmagnon/display-epaper/epd"
|
"github.com/Crocmagnon/display-epaper/epd"
|
||||||
"github.com/Crocmagnon/display-epaper/fete"
|
"github.com/Crocmagnon/display-epaper/fete"
|
||||||
"github.com/Crocmagnon/display-epaper/transports"
|
"github.com/Crocmagnon/display-epaper/transports"
|
||||||
|
"github.com/Crocmagnon/display-epaper/weather"
|
||||||
"log"
|
"log"
|
||||||
"periph.io/x/host/v3"
|
"periph.io/x/host/v3"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func run(ctx context.Context, transportsClient *transports.Client, feteClient *fete.Client) error {
|
func run(
|
||||||
|
ctx context.Context,
|
||||||
|
transportsClient *transports.Client,
|
||||||
|
feteClient *fete.Client,
|
||||||
|
weatherClient *weather.Client,
|
||||||
|
) error {
|
||||||
_, err := host.Init()
|
_, err := host.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("initializing host: %w", err)
|
return fmt.Errorf("initializing host: %w", err)
|
||||||
|
@ -30,7 +36,7 @@ func run(ctx context.Context, transportsClient *transports.Client, feteClient *f
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
err = loop(ctx, display, transportsClient, feteClient)
|
err = loop(ctx, display, transportsClient, feteClient, weatherClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error looping: %v\n", err)
|
log.Printf("error looping: %v\n", err)
|
||||||
}
|
}
|
||||||
|
@ -45,6 +51,7 @@ func loop(
|
||||||
display *epd.EPD,
|
display *epd.EPD,
|
||||||
transportsClient *transports.Client,
|
transportsClient *transports.Client,
|
||||||
feteClient *fete.Client,
|
feteClient *fete.Client,
|
||||||
|
weatherClient *weather.Client,
|
||||||
) error {
|
) error {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := display.Sleep(); err != nil {
|
if err := display.Sleep(); err != nil {
|
||||||
|
@ -59,7 +66,7 @@ func loop(
|
||||||
|
|
||||||
display.Clear()
|
display.Clear()
|
||||||
|
|
||||||
black, err := getBlack(ctx, time.Now, transportsClient, feteClient)
|
black, err := getBlack(ctx, time.Now, transportsClient, feteClient, weatherClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting black: %w", err)
|
return fmt.Errorf("getting black: %w", err)
|
||||||
}
|
}
|
||||||
|
|
122
weather/weather.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package weather
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/carlmjohnson/requests"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
APIKey string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
config Config
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(httpClient *http.Client, config Config) *Client {
|
||||||
|
return &Client{
|
||||||
|
config: config,
|
||||||
|
client: httpClient,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Prevision struct {
|
||||||
|
Lat float64 `json:"lat"`
|
||||||
|
Lon float64 `json:"lon"`
|
||||||
|
Timezone string `json:"timezone"`
|
||||||
|
TimezoneOffset int `json:"timezone_offset"`
|
||||||
|
Current struct {
|
||||||
|
Dt int `json:"dt"`
|
||||||
|
Sunrise int `json:"sunrise"`
|
||||||
|
Sunset int `json:"sunset"`
|
||||||
|
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 []struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Main string `json:"main"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
} `json:"weather"`
|
||||||
|
} `json:"current"`
|
||||||
|
Daily []Daily `json:"daily"`
|
||||||
|
Alerts []struct {
|
||||||
|
SenderName string `json:"sender_name"`
|
||||||
|
Event string `json:"event"`
|
||||||
|
Start int `json:"start"`
|
||||||
|
End int `json:"end"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
} `json:"alerts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Daily struct {
|
||||||
|
Dt int `json:"dt"`
|
||||||
|
Sunrise int `json:"sunrise"`
|
||||||
|
Sunset int `json:"sunset"`
|
||||||
|
Moonrise int `json:"moonrise"`
|
||||||
|
Moonset int `json:"moonset"`
|
||||||
|
MoonPhase float64 `json:"moon_phase"`
|
||||||
|
Summary string `json:"summary"`
|
||||||
|
Temp struct {
|
||||||
|
Day float64 `json:"day"`
|
||||||
|
Min float64 `json:"min"`
|
||||||
|
Max float64 `json:"max"`
|
||||||
|
Night float64 `json:"night"`
|
||||||
|
Eve float64 `json:"eve"`
|
||||||
|
Morn float64 `json:"morn"`
|
||||||
|
} `json:"temp"`
|
||||||
|
FeelsLike struct {
|
||||||
|
Day float64 `json:"day"`
|
||||||
|
Night float64 `json:"night"`
|
||||||
|
Eve float64 `json:"eve"`
|
||||||
|
Morn float64 `json:"morn"`
|
||||||
|
} `json:"feels_like"`
|
||||||
|
Pressure int `json:"pressure"`
|
||||||
|
Humidity int `json:"humidity"`
|
||||||
|
DewPoint float64 `json:"dew_point"`
|
||||||
|
WindSpeed float64 `json:"wind_speed"`
|
||||||
|
WindDeg int `json:"wind_deg"`
|
||||||
|
WindGust float64 `json:"wind_gust"`
|
||||||
|
Weather []Weather `json:"weather"`
|
||||||
|
Clouds int `json:"clouds"`
|
||||||
|
Pop float64 `json:"pop"`
|
||||||
|
Rain float64 `json:"rain"`
|
||||||
|
Uvi float64 `json:"uvi"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Weather struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Main string `json:"main"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetWeather(ctx context.Context) (res *Prevision, err error) {
|
||||||
|
err = requests.URL("https://api.openweathermap.org/data/3.0/onecall").
|
||||||
|
Client(c.client).
|
||||||
|
Param("lat", "45.78").
|
||||||
|
Param("lon", "4.89").
|
||||||
|
Param("appid", c.config.APIKey).
|
||||||
|
Param("units", "metric").
|
||||||
|
Param("lang", "fr").
|
||||||
|
Param("exclude", "minutely,hourly").
|
||||||
|
ToJSON(&res).
|
||||||
|
Fetch(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("calling openweathermap: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|