From 85ce26420f15b849c5687be5df5e79b9ec11af71 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Sun, 20 Sep 2015 16:25:52 +0200 Subject: Initial import --- weather.go | 272 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 weather.go diff --git a/weather.go b/weather.go new file mode 100644 index 0000000..ab1f472 --- /dev/null +++ b/weather.go @@ -0,0 +1,272 @@ +// openweathermap API +package weather + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strconv" + "time" +) + +const baseURL = `http://api.openweathermap.org/data/2.5/weather` + +type Current struct { + Coord Coord + Weather []Weather + Base string // Internal Parameter + Main Main + Wind Wind + Clouds Clouds + Rain Rain + Snow Snow + Visibility int + DT Timestamp // time of data calculation, unix, UTC + Sys Sys + ID int // City ID + Name string // City Name + Cod int // Internal Parameter +} + +func (c Current) String() string { + return fmt.Sprintf("%v: %v, %v, %v", + c.Name, c.Weather[0], c.Main, c.Wind) +} + +type Coord struct { + Lon float64 // longitude + Lat float64 // latitude +} + +func (c Coord) String() string { + return fmt.Sprint(c.Lon, c.Lat) +} + +type Cond int + +type Weather struct { + Cond Cond `json:"id"` // Station ID + Main string // Group of weather parameters + Description string // Weather condition within the group + Icon string // Weather con id +} + +func (w Weather) String() string { + return fmt.Sprint(w.Cond) +} + +type Main struct { + Temp float64 // Temperature, Default Kelvin, Metric: Celsius + Pressure int // Atmospheric pressure, hPa + Humidity int // Humidity, % + TempMin float64 `json:"temp_min"` // min temp + TempMax float64 `json:"temp_max"` // max temp + SeaLevel int `json:"sea_level"` // pressure on the sea level, hPa + GrndLevel int `json:"grnd_level"` // pressure on the ground level, hPa +} + +func (m Main) String() string { + return fmt.Sprintf("%v°C, pressure: %v hPa, humidity: %v%%", + m.Temp, m.Pressure, m.Humidity) +} + +type Wind struct { + Speed float64 // Wind speed. Default meter/sec + Deg int // Wind direction, degrees (meteorogical) +} + +func (w Wind) String() string { + return fmt.Sprintf("wind: %v° %v m/s", w.Deg, w.Speed) +} + +type Clouds struct { + All int // Cloudness, % +} + +func (c Clouds) String() string { + return fmt.Sprintf("clouds: %v%%", c.All) +} + +type Rain struct { + Vol int `json:"3h"` // Rain volume for last 3 hours +} + +func (r Rain) String() string { + if r.Vol == 0 { + return "" + } + return fmt.Sprintf("rain: %v mm/3h", r.Vol) +} + +type Snow struct { + Vol int `json:"3h"` // Snow volume for last 3 hours +} + +func (s Snow) String() string { + if s.Vol == 0 { + return "" + } + return fmt.Sprintf("snow: %v mm/3h", s.Vol) +} + +type Sys struct { + Type int // Internal Parameter + ID int // Internal Parameter + Message float64 // Internal Parameter + Country string // Country code + Sunrise Timestamp // Sunrise time, unix, UTC + Sunset Timestamp // Sunset time, unix, UTC +} + +func (s Sys) String() string { + return fmt.Sprintf("country: %v sunrise: %v sunset: %v", + s.Country, s.Sunrise, s.Sunset) +} + +type Timestamp struct{ time.Time } + +func (t *Timestamp) MarshalJSON() ([]byte, error) { + ts := t.Unix() + stamp := fmt.Sprint(ts) + return []byte(stamp), nil +} + +func (t *Timestamp) UnmarshalJSON(b []byte) error { + ts, err := strconv.Atoi(string(b)) + if err != nil { + return err + } + *t = Timestamp{time.Unix(int64(ts), 0)} + return nil +} + +func get(param string) (Current, error) { + var c Current + resp, err := http.Get(baseURL + "?units=metric" + param) + if err != nil { + return c, err + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return c, err + } + err = json.Unmarshal(body, &c) + return c, err +} + +func ByCityName(name string) (Current, error) { + return get(fmt.Sprintf("&q=%v", url.QueryEscape(name))) +} + +func ByCityID(id int) (Current, error) { + return get(fmt.Sprintf("&id=%v", id)) +} + +func ByGeoCoord(lon, lat float64) (Current, error) { + return get(fmt.Sprintf("&lon=%v&lat=%v", lon, lat)) +} + +func ByZIPCode(zip int, country string) (Current, error) { + return get(fmt.Sprintf("&zip=%v,%v", zip, country)) +} + +func (c Cond) String() string { + if cc, ok := condCodes[c]; ok { + return cc + } + return "unknown" +} + +var condCodes = map[Cond]string{ + // Thunderstorm + 200: `thunderstorm with light rain`, + 201: `thunderstorm with rain`, + 202: `thunderstorm with heavy rain`, + 210: `light thunderstorm`, + 211: `thunderstorm`, + 212: `heavy thunderstorm`, + 221: `ragged thunderstorm`, + 230: `thunderstorm with light drizzle`, + 231: `thunderstorm with drizzle`, + 232: `thunderstorm with heavy drizzle`, + + // Drizzle + 300: `light intensity drizzle`, + 301: `drizzle`, + 302: `heavy intensity drizzle`, + 310: `light intensity drizzle rain`, + 311: `drizzle rain`, + 312: `heavy intensity drizzle rain`, + 313: `shower rain and drizzle`, + 314: `heavy shower rain and drizzle`, + 321: `shower drizzle`, + + // Rain + 500: `light rain`, + 501: `moderate rain`, + 502: `heavy intensity rain`, + 503: `very heavy rain`, + 504: `extreme rain`, + 511: `freezing rain`, + 520: `light intensity shower rain`, + 521: `shower rain`, + 522: `heavy intensity shower rain`, + 531: `ragged shower rain`, + + // Snow + 600: `light snow`, + 601: `snow`, + 602: `heavy snow`, + 611: `sleet`, + 612: `shower sleet`, + 615: `light rain and snow`, + 616: `rain and snow`, + 620: `light shower snow`, + 621: `shower snow`, + 622: `heavy shower snow`, + + // Atmosphere + 701: `mist`, + 711: `smoke`, + 721: `haze`, + 731: `sand, dust whirls`, + 741: `fog`, + 751: `sand`, + 761: `dust`, + 762: `volcanic ash`, + 771: `squalls`, + 781: `tornado`, + + // Clouds + 800: `clear sky`, + 801: `few clouds`, + 802: `scattered clouds`, + 803: `broken clouds`, + 804: `overcast clouds`, + + // Extreme + 900: `tornado`, + 901: `tropical storm`, + 902: `hurricane`, + 903: `cold`, + 904: `hot`, + 905: `windy`, + 906: `hail`, + + // Additional + 951: `calm`, + 952: `light breeze`, + 953: `gentle breeze`, + 954: `moderate breeze`, + 955: `fresh breeze`, + 956: `strong breeze`, + 957: `high wind, near gale`, + 958: `gale`, + 959: `severe gale`, + 960: `storm`, + 961: `violent storm`, + 962: `hurricane`, +} -- cgit v1.2.3