summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2015-09-20 16:25:52 +0200
committerDimitri Sokolyuk <demon@dim13.org>2015-09-20 16:25:52 +0200
commit85ce26420f15b849c5687be5df5e79b9ec11af71 (patch)
tree6c63c7252e3079c53d11773a6416228acf92732b
Initial import
-rw-r--r--weather.go272
1 files changed, 272 insertions, 0 deletions
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`,
+}