From cbc777005e2d344151ea5c1984a33ff7b262b79a Mon Sep 17 00:00:00 2001 From: siddharth Date: Sun, 15 May 2022 23:39:38 -0400 Subject: nws: add Forecast --- nws/nws.go | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ nws/nws_test.go | 52 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) (limited to 'nws') diff --git a/nws/nws.go b/nws/nws.go index a3155ab..b939d2a 100644 --- a/nws/nws.go +++ b/nws/nws.go @@ -24,6 +24,29 @@ type NWSPoint struct { Properties NWSPointProperties } +type NWSForecastPeriod struct { + Number int + Name string + StartTime string + EndTime string + IsDayTime bool + Temperature int + TemperatureUnit string + TemperatureTrend string + WindSpeed string + WindDirection string + ShortForecast string + DetailedForecast string +} + +type NWSForecastProperties struct { + Periods []NWSForecastPeriod +} + +type NWSForecast struct { + Properties NWSForecastProperties +} + type NWSError struct { Title string Type string @@ -74,3 +97,45 @@ func Points(lat, lng float32) (*NWSPoint, error) { return point, nil } +// NWS forecast endpoint. +func Forecast(point *NWSPoint) (*NWSForecast, error) { + if point == nil { + return nil, fmt.Errorf("forecast: point nil") + } + if len(point.Properties.Forecast) == 0 { + return nil, fmt.Errorf("forecast: link empty") + } + + // Get the forecast + resp, err := client.Get(point.Properties.Forecast) + if err != nil { + return nil, fmt.Errorf("forecast: get: %v", err) + } + + // Parse response body. + body, err := io.ReadAll(resp.Body) + if err != nil { + return nil, fmt.Errorf("forecast: body: %v", err) + } + + // Check if the request failed. + if resp.StatusCode != 200 { + perr := new(NWSError) + err := json.Unmarshal(body, perr) + if err != nil { + return nil, fmt.Errorf("forecast: json: %v", err) + } + return nil, fmt.Errorf("forecast: %v", perr) + } + + // Unmarshal. + forecast := new(NWSForecast) + err = json.Unmarshal(body, forecast) + if err != nil { + return nil, fmt.Errorf("forecast: decode: %v", err) + } + if len(forecast.Properties.Periods) == 0 { + return nil, fmt.Errorf("forecast: periods empty") + } + return forecast, nil +} diff --git a/nws/nws_test.go b/nws/nws_test.go index 97dd184..ea47188 100644 --- a/nws/nws_test.go +++ b/nws/nws_test.go @@ -33,3 +33,55 @@ func TestPoints(t *testing.T) { t.Errorf("points: %v", np) } } + +func TestForecast(t *testing.T) { + // Get point. + np, err := Points(41.115, -83.177) + if err != nil { + t.Errorf("error: %v", err) + } + + // Get forecast. + fc, err := Forecast(np) + if err != nil { + t.Errorf("error: %v", err) + } + + // Verify periods. + for i, period := range fc.Properties.Periods { + if period.Number < 1 { + t.Errorf("period: %d: number invalid: %v", i, period.Number) + } + if len(period.Name) < 1 { + t.Errorf("period: %d: name invalid: %v", i, period.Name) + } + if len(period.StartTime) < 1 { + t.Errorf("period: %d: start time invalid: %v", i, + period.StartTime) + } + if len(period.EndTime) < 1 { + t.Errorf("period: %d: end time invalid: %v", i, + period.EndTime) + } + if len(period.TemperatureUnit) < 1 { + t.Errorf("period: %d: temperature unit invalid: %v", + i, period.TemperatureUnit) + } + if len(period.WindSpeed) < 1 { + t.Errorf("period: %d: wind speed invalid: %v", + i, period.WindSpeed) + } + if len(period.WindDirection) < 1 { + t.Errorf("period: %d: wind direction invalid: %v", + i, period.WindDirection) + } + if len(period.ShortForecast) < 1 { + t.Errorf("period: %d: short forecast invalid: %v", + i, period.ShortForecast) + } + if len(period.DetailedForecast) < 1 { + t.Errorf("period: %d: detailed forecast invalid: %v", + i, period.DetailedForecast) + } + } +} -- cgit v1.2.3