Mercurial > ~darius > hgwebdir.cgi > wh1080
comparison yreport.c @ 0:9dab44dcb331
Initial commit of Greg's code from http://www.lemis.com/grog/tmp/wh1080.tar.gz
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Tue, 09 Feb 2010 13:44:25 +1030 |
parents | |
children | 9da35e705144 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:9dab44dcb331 |
---|---|
1 /* | |
2 * Report weather conditions to remote web sites. | |
3 * | |
4 * Greg Lehey, 14 December 2009 | |
5 * | |
6 * $Id: yreport.c,v 1.2 2010/02/07 03:39:12 grog Exp $ | |
7 */ | |
8 | |
9 #include "wh1080.h" | |
10 | |
11 #define STAMPSIZE 32 /* size of time stamp to print out */ | |
12 | |
13 /* | |
14 * Data returned by database query, in the form we want. | |
15 */ | |
16 struct weather_query | |
17 { | |
18 float inside_humidity; | |
19 float inside_temp; | |
20 float inside_dewpoint; | |
21 float outside_humidity; | |
22 float outside_temp; | |
23 float outside_dewpoint; | |
24 float pressure_msl; | |
25 float wind_speed; | |
26 float wind_gust; | |
27 float wind_direction; | |
28 float rain; | |
29 } weather_query; | |
30 | |
31 /* Format strings for printing out variables */ | |
32 char *rowformat1 [] = {"\t$inside_humidity = %4.0f;\n", | |
33 "\t$inside_temperature = %2.1f;\n", | |
34 "\t$inside_dewpoint = %2.1f;\n", | |
35 "\t$outside_humidity = %4.0f;\n", | |
36 "\t$outside_temperature = %2.1f;\n", | |
37 "\t$outside_dewpoint = %2.1f;\n", | |
38 "\t$pressure_msl = %2.1f;\n", | |
39 "\t$wind_speed = %2.1f;\n", | |
40 "\t$wind_gust = %2.1f;\n", | |
41 "\t$wind_direction = %4.0f;\n", | |
42 "\t$rain = %2.1f;\n"}; | |
43 | |
44 char *rowformat2 [] = {"\t$max_inside_humidity = %2.3f;\n", | |
45 "\t$min_inside_humidity = %2.3f;\n", | |
46 "\t$max_inside_temp = %2.3f;\n", | |
47 "\t$min_inside_temp = %2.3f;\n", | |
48 "\t$max_inside_dewpoint = %2.3f;\n", | |
49 "\t$min_inside_dewpoint = %2.3f;\n", | |
50 "\t$max_outside_humidity = %2.3f;\n", | |
51 "\t$min_outside_humidity = %2.3f;\n", | |
52 "\t$max_outside_temp = %2.3f;\n", | |
53 "\t$min_outside_temp = %2.3f;\n", | |
54 "\t$max_outside_dewpoint = %2.3f;\n", | |
55 "\t$min_outside_dewpoint = %2.3f;\n", | |
56 "\t$max_pressure_msl = %2.3f;\n", | |
57 "\t$min_pressure_msl = %2.3f;\n", | |
58 "\t$max_wind_speed = %2.3f;\n", | |
59 "\t$min_wind_speed = %2.3f;\n", | |
60 "\t$max_wind_gust = %2.3f;\n", | |
61 "\t$min_wind_gust = %2.3f;\n", | |
62 "\t$sum_rain = %2.3f;\n" }; | |
63 | |
64 char *maxmintimes [] = {"inside_humidity", | |
65 "inside_temp", | |
66 "inside_dewpoint", | |
67 "outside_humidity", | |
68 "outside_temp", | |
69 "outside_dewpoint", | |
70 "pressure_msl", | |
71 "wind_speed", | |
72 "wind_gust" }; | |
73 | |
74 int rowformats1 = sizeof (rowformat1) / sizeof (char *); | |
75 int rowformats2 = sizeof (rowformat2) / sizeof (char *); | |
76 int maxmincount = sizeof (maxmintimes) / sizeof (char *); | |
77 | |
78 /* | |
79 * Create a header file for PHP pages. The "current readings" are an average | |
80 * over the last config.website_generation_interval seconds. | |
81 */ | |
82 | |
83 /* | |
84 * An alternative query method could be prepared statements. See | |
85 * http://dev.mysql.com/doc/refman/5.1/en/c-api-prepared-statements.html for | |
86 * details. Peter Jeremy says: "Search for MYSQL_BIND, mysql_stmt_bind_param() | |
87 * and mysql_stmt_bind_result()." | |
88 */ | |
89 void make_php_header_file () | |
90 { | |
91 time_t start; | |
92 time_t now; | |
93 FILE *header_file; | |
94 char date_time [DATETEXTLENGTH]; /* Wednesday, 25 November 2009 16:47:46 */ | |
95 time_t yesterday; | |
96 char yesterday_text [DATETEXTLENGTH]; /* YYYY-MM-DD */ | |
97 int row; | |
98 int rough_direction; /* out of range */ | |
99 | |
100 header_file = fopen (config.php_header, "w"); | |
101 if (! header_file) | |
102 fprintf (stderr, | |
103 "Can't open %s: %s (%d)\n", | |
104 config.php_header, | |
105 strerror (errno), | |
106 errno ); | |
107 else | |
108 { | |
109 now = time (NULL); | |
110 start = now - config.website_generation_interval; /* determine the time we're doing this for */ | |
111 strftime (date_time, DATETEXTLENGTH, "%A, %e %B %Y %T", localtime (&now)); | |
112 yesterday = now - SECSPERDAY; /* this time yesterday */ | |
113 strftime (yesterday_text, DATETEXTLENGTH, "%F", localtime (&yesterday)); | |
114 | |
115 fprintf (header_file, | |
116 "<?php\n" | |
117 "/* Automatically generated file. Do not edit */\n" | |
118 "\t$timetext = \"%s\";\n" | |
119 "\t$yesterday = \"%s\";\n" | |
120 "\t$timestamp = %d;\n", | |
121 date_time, /* time in text form */ | |
122 yesterday_text, /* yesterday's date YYYY-MM-DD */ | |
123 (int) now ); /* time of reading */ | |
124 | |
125 sprintf (mysql_querytext, | |
126 "SELECT AVG(inside_humidity),\n" | |
127 " AVG(inside_temp),\n" | |
128 " AVG(inside_dewpoint),\n" | |
129 " AVG(outside_humidity),\n" | |
130 " AVG(outside_temp),\n" | |
131 " AVG(outside_dewpoint),\n" | |
132 " AVG(pressure_msl),\n" | |
133 " AVG(wind_speed),\n" | |
134 " AVG(wind_gust),\n" | |
135 " AVG(wind_direction),\n" | |
136 " SUM(rain)\n" | |
137 "FROM %s\n" | |
138 "WHERE unix_timestamp(timestamp(date,time)) >= %d\n" | |
139 " AND unix_timestamp(timestamp(date, time)) <= %d\n" | |
140 " AND station_id = \"%s\"\n", | |
141 config.db_table, | |
142 start, | |
143 now, | |
144 config.station_id ); | |
145 | |
146 if (doquery (mysql_querytext)) | |
147 return; /* failed and reported */ | |
148 | |
149 if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ | |
150 { | |
151 for (row = 0; row < rowformats1; row++) | |
152 { | |
153 /* | |
154 * We have a problem here: if a value is missing, we can't just print | |
155 * it. Fake a number for the time being. | |
156 */ | |
157 if (mysql_row [row] && *mysql_row [row]) /* something there */ | |
158 fprintf (header_file, rowformat1 [row], atof (mysql_row [row])); | |
159 else | |
160 fprintf (header_file, rowformat1 [row], -999.0); | |
161 } | |
162 | |
163 /* Isn't this ugly? */ | |
164 rough_direction = 1000; /* out of range */ | |
165 if ((mysql_row [9]) && (*mysql_row [9])) /* something there */ | |
166 rough_direction = (int) ((atof (mysql_row [9]) + 11.25) / 22.5); | |
167 | |
168 if ((rough_direction < 16) && (rough_direction >= 0)) | |
169 fprintf (header_file, | |
170 "\t$wind_direction_text = \"%s\";\n", | |
171 wind_directions [rough_direction] ) ; | |
172 else | |
173 fprintf (header_file, "\t$wind_direction_text = \"(none)\";\n"); | |
174 mysql_free_result (mysql_result); | |
175 } | |
176 | |
177 /* Now stats for the day */ | |
178 strftime (date_time, DATETEXTLENGTH, "%Y-%m-%d", localtime (&now)); | |
179 sprintf (mysql_querytext, | |
180 "SELECT @max_inside_humidity := MAX(inside_humidity),\n" | |
181 " @min_inside_humidity := MIN(inside_humidity),\n" | |
182 " @max_inside_temp := MAX(inside_temp),\n" | |
183 " @min_inside_temp := MIN(inside_temp),\n" | |
184 " @max_inside_dewpoint := MAX(inside_dewpoint),\n" | |
185 " @min_inside_dewpoint := MIN(inside_dewpoint),\n" | |
186 " @max_outside_humidity := MAX(outside_humidity),\n" | |
187 " @min_outside_humidity := MIN(outside_humidity),\n" | |
188 " @max_outside_temp := MAX(outside_temp),\n" | |
189 " @min_outside_temp := MIN(outside_temp),\n" | |
190 " @max_outside_dewpoint := MAX(outside_dewpoint),\n" | |
191 " @min_outside_dewpoint := MIN(outside_dewpoint),\n" | |
192 " @max_pressure_msl := MAX(pressure_msl),\n" | |
193 " @min_pressure_msl := MIN(pressure_msl),\n" | |
194 " @max_wind_speed := MAX(wind_speed),\n" | |
195 " @min_wind_speed := MIN(wind_speed),\n" | |
196 " @max_wind_gust := MAX(wind_gust),\n" | |
197 " @min_wind_gust := MIN(wind_gust),\n" | |
198 " SUM(rain)\n" | |
199 "FROM %s\n" | |
200 "WHERE date = \"%s\"\n" | |
201 " AND station_id = \"%s\"\n", | |
202 config.db_table, | |
203 date_time, | |
204 config.station_id ); | |
205 | |
206 if (doquery (mysql_querytext)) | |
207 return; /* failed and reported */ | |
208 | |
209 if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ | |
210 { | |
211 for (row = 0; row < rowformats2; row++) | |
212 fprintf (header_file, rowformat2 [row], atof (mysql_row [row])); | |
213 mysql_free_result (mysql_result); | |
214 } | |
215 | |
216 /* Now get the times that go with the maxima and minima */ | |
217 for (row = 0; row < maxmincount; row++) | |
218 { | |
219 /* Time of maximum */ | |
220 sprintf (mysql_querytext, | |
221 "SELECT time from %s\n" | |
222 "WHERE date = \"%s\"\n" | |
223 " AND station_id = \"%s\"\n" | |
224 " AND %s = @max_%s\n" | |
225 "LIMIT 1", | |
226 config.db_table, | |
227 date_time, | |
228 config.station_id, | |
229 maxmintimes [row], | |
230 maxmintimes [row] ); | |
231 if (doquery (mysql_querytext)) /* failure */ | |
232 return; /* XXX be cleverer */ | |
233 if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ | |
234 { | |
235 fprintf (header_file, "\t$max_%s_time = \"%s\";\n", maxmintimes [row], mysql_row [0]); | |
236 mysql_free_result (mysql_result); | |
237 } | |
238 else /* dummy */ | |
239 fprintf (header_file, "\t$max_%s_time = \"unknown\"\n", maxmintimes [row]); | |
240 /* Now time of minimum */ | |
241 sprintf (mysql_querytext, | |
242 "SELECT time from %s\n" | |
243 "WHERE date = \"%s\"\n" | |
244 " AND station_id = \"%s\"\n" | |
245 " AND %s = @min_%s\n" | |
246 "LIMIT 1", | |
247 config.db_table, | |
248 date_time, | |
249 config.station_id, | |
250 maxmintimes [row], | |
251 maxmintimes [row] ); | |
252 if (doquery (mysql_querytext)) /* failure */ | |
253 return; /* XXX be cleverer */ | |
254 if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ | |
255 { | |
256 fprintf (header_file, "\t$min_%s_time = \"%s\";\n", maxmintimes [row], mysql_row [0]); | |
257 mysql_free_result (mysql_result); | |
258 } | |
259 else /* dummy */ | |
260 fprintf (header_file, "\t$min_%s_time = \"unknown\"\n", maxmintimes [row]); | |
261 } | |
262 | |
263 fprintf (header_file, "\t?>\n"); /* end */ | |
264 fclose (header_file); | |
265 } | |
266 } | |
267 | |
268 void usage (char *me) | |
269 { | |
270 fprintf (stderr, | |
271 "Usage: %s [-d] [-n] [-v] [-1] [station ID] [db user] [password] [db host] [database]\n", | |
272 me); | |
273 exit (1); | |
274 } | |
275 | |
276 int main (int argc, char *argv []) | |
277 { | |
278 time_t lastrun; | |
279 time_t nextrun; | |
280 time_t now; | |
281 | |
282 if (read_config (argc, argv) < 0) | |
283 usage (argv [0]); | |
284 | |
285 while (1) | |
286 { | |
287 lastrun = time (NULL); /* time we ran the loop */ | |
288 make_php_header_file (); | |
289 if (once) /* just run once */ | |
290 exit (0); | |
291 /* | |
292 * Informing Wunderground takes finite time. Stay on schedule. | |
293 * We may end up off by a second from time to time, but we shouldn't drift. | |
294 * | |
295 */ | |
296 nextrun = lastrun + config.website_generation_interval; /* next time to run */ | |
297 now = time (NULL); | |
298 sleep (nextrun - now); | |
299 } | |
300 return 0; | |
301 } |