Mercurial > ~darius > hgwebdir.cgi > wh1080
diff xreport.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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xreport.c Tue Feb 09 13:44:25 2010 +1030 @@ -0,0 +1,371 @@ +/* + * 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 "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; +}