Mercurial > ~darius > hgwebdir.cgi > wh1080
view xreport.c @ 3:dc5ff2a1ed81
Be smarter about retries.
If the interrupt endpoint can't be read 100 times then retry the whole request.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Wed, 10 Feb 2010 11:33:27 +1030 |
parents | 9da35e705144 |
children |
line wrap: on
line source
/* * Report weather conditions to remote web sites. * * Greg Lehey, 14 December 2009 * * $Id: xreport.c,v 1.3 2010/02/07 03:41:35 grog Exp $ */ #include <stdlib.h> #include "wh1080.h" #define STAMPSIZE 32 /* size of time stamp to print out */ struct readings current_readings; /* current data readings, our version */ char reporturl [2048]; /* build up report here */ time_t last_report; /* time of last report */ /* * Data returned by database query, in the form we want. */ struct weather_query { float inside_humidity; float inside_temp; float inside_dewpoint; float outside_humidity; float outside_temp; float outside_dewpoint; float pressure_msl; float wind_speed; float wind_gust; float wind_direction; float rain; } weather_query; /* * Update the last report time. */ void update_lastreport (time_t time) { char report_time [STAMPSIZE]; strftime (report_time, /* format time and date */ STAMPSIZE, "%Y-%m-%d %T", localtime (&time)); sprintf (mysql_querytext, "REPLACE INTO lastreport (station_id, report_id, date)\n" "VALUES (\"%s\", \"Wunderground\", \"%s\")", config.wunderground_station_id, report_time ); doquery (mysql_querytext); } /* * Send information to Wunderground. * * See http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol for details * of communication protocol. * * Wunderground requires all values in archaic units, but pressures converted to * in Hg are converted back about 0.2 hPa too low. We use a different * definition, which may or may not get the in Hg right, but results in correct * conversion back to hPa. * * Return 0 on success, 1 on failure. Failure will be retried at the next * reporting interval. */ int really_inform_wunderground (time_t start, time_t end) { /* Care: we can't add start and end, because they'll overflow */ time_t midtime = start / 2 + end / 2; /* average time of the interval */ char dateutc [STAMPSIZE]; int something = 0; /* set when we find something to report */ int i; /* counter */ /* Values to report */ float inside_humidity; float inside_temp; #if 0 float inside_dewpoint; /* not currently used */ #endif float outside_humidity; float outside_temp; float outside_dewpoint; float pressure_msl; float wind_speed; float wind_gust; float wind_direction; float rain; sprintf (mysql_querytext, "SELECT AVG(inside_humidity),\n" " AVG(inside_temp),\n" " AVG(inside_dewpoint),\n" " AVG(outside_humidity),\n" " AVG(outside_temp),\n" " AVG(outside_dewpoint),\n" " AVG(pressure_msl),\n" " AVG(wind_speed),\n" " AVG(wind_gust),\n" " AVG(wind_direction)\n" "FROM observations\n" "WHERE unix_timestamp(timestamp(date,time)) >= %d\n" " AND unix_timestamp(timestamp(date, time)) <= %d\n" " AND station_id = \"%s\"\n", start, end, config.station_id ); if (doquery (mysql_querytext)) return 1; /* failed and reported */ if (verbose) { strftime (dateutc, /* format time and date */ STAMPSIZE, "%Y-%m-%d %T", localtime (&start)); printf ("Start date:\t\t%17s\n", dateutc); strftime (dateutc, /* format time and date */ STAMPSIZE, "%Y-%m-%d %T", localtime (&end)); printf ("End date:\t\t%17s\n", dateutc); } if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ { #if 0 /* * What a mess! The result of the query in in text form, and we need to convert it to float * both to reformat it and to convert units. */ printf ("%s %s %s %s %s %s %s %s %s %s %s\n", mysql_row [0], mysql_row [1], mysql_row [2], mysql_row [3], mysql_row [4], mysql_row [5], mysql_row [6], mysql_row [7], mysql_row [8], mysql_row [9], mysql_row [10] ); #endif /* * Any of these values may be NULL. If they all are, we don't have any data, so * wait for some to show up. */ for (i = 0; i < 11; i++) if (mysql_row [i]) something = 1; if (! something) /* nothing to report */ return 1; /* consider a "failure" */ strftime (dateutc, STAMPSIZE, "%F+%H%%3a%M%%3a%S", gmtime (&midtime)); /* format time and date */ /* Start building up the message */ sprintf (reporturl, "./wundersend " "'http://weatherstation.wunderground.com/weatherstation/updateweatherstation.php" "?ID=%s&PASSWORD=%s" "&dateutc=%s", config.wunderground_station_id, config.wunderground_passwd, dateutc ); /* Now find what we have to report */ if (mysql_row [0]) { inside_humidity = atof (mysql_row [0]); if (verbose) printf ("Inside humidity:\t%4.0f%%\n", inside_humidity); sprintf (&reporturl [strlen (reporturl)], "&indoorhumidity=%1.0f", inside_humidity ); } if (mysql_row [1]) { inside_temp = atof (mysql_row [1]); if (verbose) printf ("Inside temperature:\t%6.1f°\n", inside_temp); inside_temp = C_TO_F (inside_temp); sprintf (&reporturl [strlen (reporturl)], "&indoortempf=%2.1f", inside_temp ); } /* mysql_row [2] is inside dewpoint, which we don't seem to be able to report */ if (mysql_row [3]) { outside_humidity = atof (mysql_row [3]); if (verbose) printf ("Outside humidity:\t%4.0f%%\n", outside_humidity); sprintf (&reporturl [strlen (reporturl)], "&humidity=%1.0f", outside_humidity ); } if (mysql_row [4]) { outside_temp = atof (mysql_row [4]); if (verbose) printf ("Outside temperature:\t%6.1f°\n", outside_temp); outside_temp = C_TO_F (atof (mysql_row [4])); sprintf (&reporturl [strlen (reporturl)], "&tempf=%2.1f", outside_temp ); } if (mysql_row [5]) { outside_dewpoint = atof (mysql_row [5]); if (verbose) printf ("Outside dewpoint:\t%6.1f°\n", outside_dewpoint); outside_dewpoint = C_TO_F (outside_dewpoint); sprintf (&reporturl [strlen (reporturl)], "&dewptf=%2.1f", outside_dewpoint ); } if (mysql_row [6]) { pressure_msl = atof (mysql_row [6]); if (verbose) printf ("Sea level pressure:\t%6.1f hPa\n", pressure_msl); pressure_msl *= Wunder_hPa_TO_inHg; sprintf (&reporturl [strlen (reporturl)], "&baromin=%4.4f", pressure_msl ); } if (mysql_row [7]) { wind_speed = atof (mysql_row [7]); if (verbose) printf ("Wind speed:\t\t%6.1f km/h\n", wind_speed); wind_speed *= KM_TO_MILES; sprintf (&reporturl [strlen (reporturl)], "&windspeedmph=%2.1f", wind_speed ); } if (mysql_row [8]) { wind_gust = atof (mysql_row [8]); if (verbose) printf ("Wind gust:\t\t%6.1f km/h\n", wind_gust); wind_gust *= KM_TO_MILES; sprintf (&reporturl [strlen (reporturl)], "&windgustmph=%2.1f", wind_gust ); } if (mysql_row [9]) /* wind direction */ { wind_direction = atof (mysql_row [9]); if (verbose) printf ("Wind dir:\t\t%4.0f°\n", wind_direction); sprintf (&reporturl [strlen (reporturl)], "&winddir=%1.0f", wind_direction ); } mysql_free_result (mysql_result); /* * Now do the rain. This is special because it has to be per hour. */ start = end - SECSPERHOUR; sprintf (mysql_querytext, "SELECT SUM(rain)\n" "FROM observations\n" "WHERE unix_timestamp(timestamp(date,time)) >= %d\n" " AND unix_timestamp(timestamp(date, time)) <= %d\n" " AND station_id = \"%s\"\n", start, end, config.station_id ); if (doquery (mysql_querytext) == 0) /* succeeded */ { if ((mysql_row = mysql_fetch_row (mysql_result)) /* got something */ && mysql_row [0] ) /* and it's not NULL, */ { rain = atof (mysql_row [0]); if (verbose) printf ("Rain per hour:\t\t%6.1f mm\n", rain); rain *= MM_TO_IN; sprintf (&reporturl [strlen (reporturl)], "&rainin=%2.1f", rain ); } } sprintf (&reporturl [strlen (reporturl)], "&softwaretype=dereel-weather&action=updateraw'" ); if (verbose) printf ("\n"); /* end out output line */ if (debug) puts (reporturl); if (update) system (reporturl); } return 0; } void inform_wunderground () { time_t now; /* and time now */ sprintf (mysql_querytext, "SELECT unix_timestamp(date) FROM lastreport\n" " WHERE station_id =\"%s\"\n" " AND report_id = \"Wunderground\"", config.wunderground_station_id ); if (doquery (mysql_querytext)) /* silently ignore errors */ return; now = time (NULL); if (mysql_row = mysql_fetch_row (mysql_result)) /* got something */ last_report = atoi (mysql_row [0]); else last_report = now - config.wunderground_report_interval; mysql_free_result (mysql_result); /* * Report in strict intervals. */ while ((now - last_report) >= config.wunderground_report_interval) { if (really_inform_wunderground (last_report, last_report + config.wunderground_report_interval)) return; /* failure, we'll retry later */ last_report += config.wunderground_report_interval; update_lastreport (last_report); now = time (NULL); /* time moves on */ } } void usage (char *me) { fprintf (stderr, "Usage: %s [-d] [-n] [-v] [station ID] [db user] [password] [db host] [database]\n", me); exit (1); } int main (int argc, char *argv []) { time_t nextrun; time_t now; if (read_config (argc, argv) < 0) usage (argv [0]); if (! config.wunderground_station_id) { fprintf (stderr, "No wunderground station ID in config\n"); exit (1); } while (1) { inform_wunderground (); if (once) /* just run once */ exit (0); /* * Informing Wunderground takes finite time. Stay on schedule. * We may end up off by a second from time to time, but we shouldn't drift. * */ nextrun = last_report + config.wunderground_report_interval; /* next time to run */ now = time (NULL); sleep (nextrun - now); } return 0; }