1 ;;; org-weather.el --- Supports displaying the weather forecast from
2 ;;; openweathermap.org in your org-mode agenda.
4 ;; This is an example snippet as retrieved from openweathermap.org
24 ;; "description": "broken clouds",
38 ;; Set this to your location
39 (defvar org-weather-location
"Graz,AT")
41 ;; Define the format string to display in the agenda, see below for available wildcards
42 (defvar org-weather-format
"Weather: %desc, %tmin-%tmax%tu, %p%pu, %h%hu, %s%su")
44 ;; Your openweather API key.
45 (defvar org-weather-api-key
"")
47 ;; The api url, no need to change ususally
48 (defvar org-weather-api-url
"http://api.openweathermap.org/data/2.5/forecast/daily?q=%s&mode=json&units=metric&cnt=7&APPID=%s")
50 (defvar org-weather-api-timeout
2)
52 ;; The units, just for displaying
53 (defvar org-weather-temperature-unit
"°C")
54 (defvar org-weather-pressure-unit
"hpa")
55 (defvar org-weather-humidity-unit
"%")
56 (defvar org-weather-speed-unit
"m/s")
58 ;; Variables for internal use only
59 (defvar org-weather-initialized nil
)
60 (defvar org-weather-data
)
61 (setq org-weather-data
(make-hash-table :test
'equal
))
63 (defun org-weather-load ()
64 "Loads the webserivce data and returns it as a JSON object."
65 (with-timeout (org-weather-api-timeout)
67 (url-insert-file-contents
68 (format org-weather-api-url org-weather-location org-weather-api-key
))
71 (defun org-weather-add-to-cache (item)
72 "Adds the one result 'list' item to the data cache"
73 (let* ((timestr (cdr (assoc 'dt item
)))
74 (cache-key (format-time-string "%F" (seconds-to-time timestr
)))
76 ;; extract fields from the 'weather' element
77 (weather (cdr (assoc 'weather item
)))
78 (main (org-weather-weather weather
'main
))
79 (desc (org-weather-weather weather
'description
))
80 (icon (org-weather-weather weather
'icon
))
82 ;; extract fields from the 'temp' element
83 (temperature (cdr (assoc 'temp item
)))
84 (tmin (number-to-string (round (org-weather-temp temperature
'min
))))
85 (tmax (number-to-string (round (org-weather-temp temperature
'max
))))
86 (tmorn (number-to-string (round (org-weather-temp temperature
'morn
))))
87 (tday (number-to-string (round (org-weather-temp temperature
'day
))))
88 (teve (number-to-string (round (org-weather-temp temperature
'eve
))))
89 (tnight (number-to-string (round (org-weather-temp temperature
'night
))))
92 (pressure (number-to-string (round (cdr (assoc 'pressure item
)))))
93 (humidity (number-to-string (round (cdr (assoc 'humidity item
)))))
94 (speed (number-to-string (round (cdr (assoc 'speed item
)))))
96 ;; replace in org-weather-format
97 (agenda-str org-weather-format
)
99 (agenda-str (org-weather-replace "%main" main agenda-str
))
100 (agenda-str (org-weather-replace "%desc" desc agenda-str
))
101 (agenda-str (org-weather-replace "%icon" icon agenda-str
))
103 (agenda-str (org-weather-replace "%tu" org-weather-temperature-unit agenda-str
))
104 (agenda-str (org-weather-replace "%tmin" tmin agenda-str
))
105 (agenda-str (org-weather-replace "%tmax" tmax agenda-str
))
106 (agenda-str (org-weather-replace "%tmorn" tmorn agenda-str
))
107 (agenda-str (org-weather-replace "%tday" tday agenda-str
))
108 (agenda-str (org-weather-replace "%teve" teve agenda-str
))
109 (agenda-str (org-weather-replace "%tnight" tnight agenda-str
))
111 (agenda-str (org-weather-replace "%pu" org-weather-pressure-unit agenda-str
))
112 (agenda-str (org-weather-replace "%p" pressure agenda-str
))
113 (agenda-str (org-weather-replace "%hu" org-weather-humidity-unit agenda-str
))
114 (agenda-str (org-weather-replace "%h" humidity agenda-str
))
115 (agenda-str (org-weather-replace "%su" org-weather-speed-unit agenda-str
))
116 (agenda-str (org-weather-replace "%s" speed agenda-str
))
119 (puthash cache-key agenda-str org-weather-data
)))
121 (defun org-weather-replace (what with in
)
122 (replace-regexp-in-string (regexp-quote what
) with in
))
124 (defun org-weather-weather (weather field
)
125 "Extracts a given field from the first element in the 'weather' list"
126 (cdr (assoc field
(elt weather
0))))
128 (defun org-weather-temp (temperature field
)
129 "Extracts a given field element from a 'temp' element"
130 (cdr (assoc field temperature
)))
132 (defun org-weather-refresh ()
133 "Refreshes the weather data"
135 (setq org-weather-data
(make-hash-table :test
'equal
))
136 (mapcar 'org-weather-add-to-cache
(cdr (assoc 'list
(org-weather-load))))
137 (setq org-weather-initialized t
))
139 (defun org-weather-string (&optional date
)
140 "String of day number of year of Gregorian DATE. Defaults to today's date if DATE is not given."
141 (let* ((d (or date
(calendar-current-date)))
142 (year (calendar-extract-year d
))
143 (month (calendar-extract-month d
))
144 (day (calendar-extract-day d
))
145 (current-time (encode-time 0 0 0 day month year
))
146 (cache-key (format-time-string "%F" current-time
)))
147 (when (not org-weather-initialized
)
148 (org-weather-refresh)
149 (setq org-weather-initialized t
))
150 (let ((org-weather-raw (gethash cache-key org-weather-data
)))
151 (when org-weather-raw org-weather-raw
))))
153 (defun org-weather ()
154 "Usable as sexp expression in the diary or an org file."
155 (org-weather-string date
))
157 ;; (org-weather-refresh)
158 ;; (eval-when-compile (require 'subr-x))
159 ;; (hash-table-keys org-weather-data)
160 ;; (setq org-weather-initialized nil)
161 ;; (puthash "2014-06-01" "foobarbaz" org-weather-data)
162 ;; (gethash "2014-06-01" org-weather-data)
164 (provide 'org-weather
)