summaryrefslogtreecommitdiff
path: root/weather.go
blob: 4eb5c13c66158a15bfb04f51479139c24d60f299 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package main

// TODO: allow free-text lookups of place names, rather than ids
// TODO: decode weather type number
// TODO: split out met office specific stuff to separate module
// TODO: add other weather providers

import (
	"encoding/json"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

const defid = "310118"

type Response struct {
	BestFcst struct {
		Forecast struct {
			Location struct {
				Days []Day `json:"Day"`
			}
		}
	}
}

type Day struct {
	Date      string `json:"@date"`
	DayValues struct {
		WeatherParameters WeatherParams
	}
	NightValues struct {
		WeatherParameters WeatherParams
	}
	TimeSteps struct {
		TimeStep []struct {
			Time              string `json:"@time"`
			WeatherParameters WeatherParams
		}
	}
}

type WeatherParams struct {
	AQIndex int     // Air Quality
	F       float64 // Feels Like Temperature
	H       int     // Humidity
	P       int     // Pressure
	PP      int     // Precipitation Probability
	T       float64 // Temperature
	UV      int     // Max UV Index
	V       int     // Visibility
	WD      string  // Wind Direction
	WG      float64 // Wind Gust
	WS      float64 // Wind Speed
	WT      int     // Weather Type
}

var (
	numdays = flag.Int("n", 2, "number of days to show")
	verbose = flag.Bool("v", false, "verbose: show all weather details")
)

func main() {
	var r Response
	var id string

	flag.Parse()
	if flag.NArg() > 0 {
		id = flag.Arg(0)
	} else {
		id = defid
	}

	resp, err := http.Get("https://www.metoffice.gov.uk/public/data/PWSCache/BestForecast/Forecast/" + id + ".json?concise=true")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		log.Fatalf("HTTP status code: %d\n", resp.StatusCode)
	}
	b, err := ioutil.ReadAll(resp.Body)
	err = json.Unmarshal(b, &r)
	if err != nil {
		log.Fatal(err)
	}

	for i, d := range r.BestFcst.Forecast.Location.Days {
		if *numdays > 0 && i >= *numdays {
			break
		}
		if i > 0 {
			fmt.Printf("---------------------------------------------------------\n")
		}
		fmt.Printf("%s\n", d.Date)
		prettyWeather("     Day", d.DayValues.WeatherParameters)
		prettyWeather("   Night", d.NightValues.WeatherParameters)

		for _, t := range d.TimeSteps.TimeStep {
			prettyWeather(t.Time, t.WeatherParameters)
		}
	}
}

func prettyWeather(t string, w WeatherParams) {
	fmt.Printf("%s  Type: %2d, Temp: %4.1f°C, Rain: %2d%%, Wind: %2.1fm/s\n", t, w.WT, w.T, w.PP, w.WS)
	if *verbose {
		fmt.Printf("          %+v\n", w)
	}
}