summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsiddharth <s@ricketyspace.net>2022-05-15 23:39:38 -0400
committersiddharth <s@ricketyspace.net>2022-05-15 23:39:38 -0400
commitcbc777005e2d344151ea5c1984a33ff7b262b79a (patch)
treee188052a255aeffeb915b1f066211662794a0df6
parentceb8a50a802f3499a9e4a38940d7c001ce7d0004 (diff)
nws: add Forecast
-rw-r--r--nws/nws.go65
-rw-r--r--nws/nws_test.go52
2 files changed, 117 insertions, 0 deletions
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)
+ }
+ }
+}