# HG changeset patch # User Daniel O'Connor # Date 1357798116 -37800 # Node ID a0213f0e707b26e38e076c9dde68737cf042cd27 # Parent bfe6ed563ffc3f2bbc7053d7b133abf7343573c3 - Update for v12.10 - Plot raw data to show more up to date data - Average/peak winds so they don't spam the display. - Display the time of the most recent data. diff -r bfe6ed563ffc -r a0213f0e707b iwws.py --- a/iwws.py Wed Jun 20 12:57:30 2012 +0930 +++ b/iwws.py Thu Jan 10 16:38:36 2013 +1030 @@ -34,7 +34,7 @@ import calendar import datetime -import DataStore +import pywws.DataStore import flask import logging @@ -58,22 +58,39 @@ @app.route('/getdata.json') def getdata(): app.logger.debug("Getting data") - store = DataStore.hourly_store(DATA_DIR) + if 'duration' in flask.request.args: + duration = float(flask.request.args['duration']) + else: + duration = 24 * 60 * 60 + duration = datetime.timedelta(seconds = duration) + store = pywws.DataStore.data_store(DATA_DIR) now = datetime.datetime.now() - then = now - datetime.timedelta(1) + then = now - duration data = store[then:now] app.logger.debug("done") r = {} for k in store.key_list: r[k] = [] + # Raw data has absolute rain counts + baserain = None for d in data: + if baserain == None: + baserain = d['rain'] + delta = d['rain'] - baserain + # Sanity check + if d['rain'] < baserain or delta > 100: + delta = 0 + d['rain'] = delta + + lastdata = d['idx'] for k in d.keys(): if k == 'idx': t = int(dt2epoch(d[k])) r[k].append(t) else: r[k].append(d[k]) + r['lastdata'] = dt2epoch(lastdata) return flask.jsonify(r) def dt2epoch(dt): diff -r bfe6ed563ffc -r a0213f0e707b static/iwws.css --- a/static/iwws.css Wed Jun 20 12:57:30 2012 +0930 +++ b/static/iwws.css Thu Jan 10 16:38:36 2013 +1030 @@ -11,16 +11,23 @@ font-size: x-small; } + +div#stamp { + font-size: small; + margin-left : auto; + margin-right : auto; + height: 4%; +} div#graph1 { margin-left : auto; margin-right : auto; width: 97%; - height: 45%; + height: 43%; } div#graph2 { margin-left : auto; margin-right : auto; width: 97%; - height: 45%; + height: 43%; } diff -r bfe6ed563ffc -r a0213f0e707b static/iwws.js --- a/static/iwws.js Wed Jun 20 12:57:30 2012 +0930 +++ b/static/iwws.js Thu Jan 10 16:38:36 2013 +1030 @@ -45,28 +45,71 @@ var l = datacache['idx'].length - 1; var d = new Date(); var tzofs = d.getTimezoneOffset() * 60; + var wavgtmp = 0; + var wgusttmp = 0; + var winddir = 0; + var windavgs = 0; + var windnavg = 4; for (i = 0; i < l; i++) { - // Convert time from UTC to browser LT - t = datacache['idx'][i] - tzofs; + // Apply offset so Flot times look right (it always shows UTC) + t = (datacache['idx'][i] - tzofs) * 1000.0; + + // Keep track of min/max temperature if (datacache['temp_out'][i] < mint) mint = datacache['temp_out'] if (datacache['temp_out'][i] > maxt) maxt = datacache['temp_out'][i] - temp_out.push([t * 1000.0, datacache['temp_out'][i]]); - if (datacache['hum_out'][i] != null && datacache['temp_out'][i] != null) { - dewpt.push([t * 1000.0, hum2dp(datacache['hum_out'][i], datacache['temp_out'][i])]); + + // Store outside temperature if valid + if (datacache['temp_out'][i] != null) { + temp_out.push([t, datacache['temp_out'][i]]); + + // Calculate dewpoint if outside humidity is valid + if (datacache['hum_out'][i] != null) { + dewpt.push([t, hum2dp(datacache['hum_out'][i], datacache['temp_out'][i])]); + } } - wavg.push([t * 1000.0, datacache['wind_ave'][i] * 60.0 * 60.0 / 1000.0, wind2angle(datacache['wind_dir'][i])]); - wgust.push([t * 1000.0, datacache['wind_gust'][i] * 60.0 * 60.0 / 1000.0, wind2angle(datacache['wind_dir'][i])]); - pressure.push([t * 1000.0, datacache['abs_pressure'][i]]); + + // Store baro + pressure.push([t, datacache['abs_pressure'][i]]); + + // Store rain if there was any if (datacache['rain'][i] > 0) - rain.push([t * 1000.0, datacache['rain'][i]]); + rain.push([t, datacache['rain'][i]]); + + // Store wind (convert to km/r) + // Average the average wind speed + wavgtmp += datacache['wind_ave'][i] * 60.0 * 60.0 / 1000.0 + // Pick highest speed gusts + var g = datacache['wind_gust'][i] * 60.0 * 60.0 / 1000.0; + if (g > wgusttmp) { + wgusttmp = g; + } + // Accumulate speed/gust direction + winddir += wind2angle(datacache['wind_dir'][i]); + windavgs++; + // Normalise + if (windavgs == windnavg) { + windavgs = 0; + wavgtmp /= windnavg; + // Note: gust is peak, so nothing to do + winddir /= windnavg; + + // Store + wavg.push([t, wavgtmp, winddir]); + wgust.push([t, wgusttmp, winddir]); + + // Reset accumulators + wavgtmp = 0; + wgusttmp = 0; + winddir = 0; + } } $.plot($("#graph1"), [ - { data : pressure, label: "Baro", yaxis : 1, points : { show : true }, lines : { show : true } }, - { data : temp_out, label: "Temp.", yaxis : 2, points : { show : true }, lines : { show : true } }, - { data : dewpt, label: "Dew point", yaxis : 2, points : { show : true }, lines : { show : true } }, + { data : pressure, label: "Baro", yaxis : 1, points : { show : true, radius : 0 }, lines : { show : true } }, + { data : temp_out, label: "Temp.", yaxis : 2, points : { show : true, radius : 0 }, lines : { show : true } }, + { data : dewpt, label: "Dew point", yaxis : 2, points : { show : true, radius : 0 }, lines : { show : true } }, ], { xaxis : { mode : 'time' }, legend : { backgroundOpacity : 0, position : 'nw' }, @@ -75,7 +118,7 @@ }); $.plot($("#graph2"), [ { data : wavg, label: "Wind (Avg)", yaxis : 1, points : { show : true }, lines : { show : true }, direction : true }, - { data : wgust, label: "Wind (Gust)", yaxis : 1, points : { show : true }, lines : { show : true }, direction : true }, + { data : wgust, label: "Wind (Gust)", yaxis : 1, points : { show : true }, lines : { show : true }, direction : true }, { data : rain, label: "Rain", yaxis : 2, bars : { show : true, barWidth : 0.5 * 60 * 60 * 1000, align : "centre" } }, ], { xaxis : { mode : 'time' }, @@ -83,6 +126,10 @@ yaxis : { tickFormatter : spdFormatter }, y2axis : { min : 0, tickFormatter : mmFormatter } }); + // Reverse tzofs calculation as Date does local time + var dobj = new Date(datacache['lastdata'] * 1000.0); + $('#stamp').html(sprintf("Last data: %02d/%02d/%02d %02d:%02d:%02d", dobj.getFullYear(), dobj.getMonth() + 1, dobj.getDate(), + dobj.getHours(), dobj.getMinutes(), dobj.getSeconds())); } function wind2angle(dir) { diff -r bfe6ed563ffc -r a0213f0e707b static/sprintf.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/static/sprintf.js Thu Jan 10 16:38:36 2013 +1030 @@ -0,0 +1,130 @@ +/** + * + * Javascript sprintf + * http://www.webtoolkit.info/ + * + * + **/ + +sprintfWrapper = { + init : function () { + if (typeof arguments == "undefined") { return null; } + if (arguments.length < 1) { return null; } + if (typeof arguments[0] != "string") { return null; } + if (typeof RegExp == "undefined") { return null; } + + var string = arguments[0]; + var exp = new RegExp(/(%([%]|(\-)?(\+|\x20)?(0)?(\d+)?(\.(\d)?)?([bcdfosxX])))/g); + var matches = new Array(); + var strings = new Array(); + var convCount = 0; + var stringPosStart = 0; + var stringPosEnd = 0; + var matchPosEnd = 0; + var newString = ''; + var match = null; + + while (match = exp.exec(string)) { + if (match[9]) { convCount += 1; } + + stringPosStart = matchPosEnd; + stringPosEnd = exp.lastIndex - match[0].length; + strings[strings.length] = string.substring(stringPosStart, stringPosEnd); + + matchPosEnd = exp.lastIndex; + matches[matches.length] = { + match: match[0], + left: match[3] ? true : false, + sign: match[4] || '', + pad: match[5] || ' ', + min: match[6] || 0, + precision: match[8], + code: match[9] || '%', + negative: parseInt(arguments[convCount]) < 0 ? true : false, + argument: String(arguments[convCount]) + }; + } + strings[strings.length] = string.substring(matchPosEnd); + + if (matches.length == 0) { return string; } + if ((arguments.length - 1) < convCount) { return null; } + + var code = null; + var match = null; + var i = null; + + for (i=0; i + @@ -22,6 +23,7 @@ Update
+