Merge pull request #7 from jamesrichardsonjr/master
[org-weather.git] / org-weather.el
blobbc2d72ca562e6ec3ef444b7177df7a3c7377e069
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
5 ;;
6 ;; {
7 ;; "list": [
8 ;; {
9 ;; "dt": 1401616800,
10 ;; "temp": {
11 ;; "day": 17.04,
12 ;; "min": 11.19,
13 ;; "max": 17.04,
14 ;; "night": 11.19,
15 ;; "eve": 16.19,
16 ;; "morn": 17.04
17 ;; },
18 ;; "pressure": 934.7,
19 ;; "humidity": 56,
20 ;; "weather": [
21 ;; {
22 ;; "id": 803,
23 ;; "main": "Clouds",
24 ;; "description": "broken clouds",
25 ;; "icon": "04d"
26 ;; }
27 ;; ],
28 ;; "speed": 1.52,
29 ;; "deg": 356,
30 ;; "clouds": 68
31 ;; }
32 ;; ]
33 ;; }
35 (require 'json)
36 (require 'url)
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)
66 (with-temp-buffer
67 (url-insert-file-contents
68 (format org-weather-api-url org-weather-location org-weather-api-key))
69 (json-read))))
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))))
91 ;; other fields
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"
134 (interactive)
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)