New, updated version of web. Might contain customizations

This commit is contained in:
2019-08-21 15:44:49 +02:00
parent c3850b6e19
commit 47326ed774
11 changed files with 600 additions and 536 deletions

View File

@@ -1,59 +1,65 @@
#!/usr/bin/python3 #!/usr/bin/python3
"""Our cherrypy server, it all starts here
Let's look at the statically linked stuff as well (i.e. the files that will
serve us data). These imports are static files in the same directory. Each
a spearate application with it's own face and behavior
"""
import os import os
import cherrypy import cherrypy
import sys
# UI for weather ./weather.py
import weather
# CSV "API" for graphs, or individual pulling ./dynamic.py
import dynamic
# UI for RasPi / davis status ./status.py
import status
PATH = os.path.abspath(os.path.dirname(__file__)) import index
from modules import voltage
from modules import weather
from modules import dynamic
from modules import status
from modules import temphumi
import config
# Where are we?
_SCRIPT_PATH = os.path.dirname(sys.argv[0])
# Certificates fro SSL reside here
_CERT_PATH = _SCRIPT_PATH + '/.cert'
# So we can load static libraries def main_server_loop():
# sys.path.append(_SCRIPT_PATH) ''' Master http server - the main executable / daemon
# basic config for the server, the SSL part is questionable... Contains basic server settings and how the sub-modules
server_config = { are called and mounted to their respective paths
'server.socket_host': '0.0.0.0',
'server.socket_port': 80
}
# commit the config settings
cherrypy.config.update(server_config)
# If launched directly, let's go Args:
if __name__ == '__main__': *None*
Sets:
*server_config:* dict(), updates cherrypy.config
*conf:* dict(), see Cherrypy docs for more
*cherrypy.config:* dict(), see Cherrypy docs for more
Returns:
*N/A*
Raises:
*Exception* If server is unable to start
'''
server_config={
'server.socket_host': config.Conf.val['_server_bind_ip'],
'server.socket_port': config.Conf.val['_server_port']
}
cherrypy.config.update(server_config)
conf = { conf = {
'/': { '/': {
'tools.sessions.on': True, 'tools.sessions.on': True,
'tools.staticdir.root': os.path.abspath(_SCRIPT_PATH + '/') 'tools.staticdir.root': os.path.abspath(config.SCRIPT_PATH + '/')
}, },
'/static': { '/static': {
'tools.staticdir.on': True, 'tools.staticdir.on': True,
'tools.staticdir.dir': os.path.abspath(_SCRIPT_PATH + '/static') 'tools.staticdir.dir': './static'
},
'/data': {
'tools.staticdir.on': False,
'tools.staticdir.dir': os.path.abspath(_SCRIPT_PATH + '/dynamic')
} }
} }
# Here are the different served mounts cherrypy.tree.mount(voltage.EnergyInfo(), "/", conf)
cherrypy.tree.mount(weather.WeatherInfo(), "/", conf) cherrypy.tree.mount(voltage.EnergyInfo(), "/energy", conf)
cherrypy.tree.mount(weather.WeatherInfo(), "/weather", conf)
cherrypy.tree.mount(status.StatusInfo(), "/status", conf) cherrypy.tree.mount(status.StatusInfo(), "/status", conf)
cherrypy.tree.mount(dynamic.DynamicData(), "/data", conf) cherrypy.tree.mount(dynamic.Expose(), "/data", conf)
cherrypy.tree.mount(temphumi.PuerhInfo(), "/temphumi", conf)
# Run the server, lock it in place.
cherrypy.engine.start() cherrypy.engine.start()
cherrypy.engine.block() cherrypy.engine.block()
if __name__ == '__main__':
try:
main_server_loop()
except Exception as e:
raise e

View File

@@ -10,35 +10,83 @@ var process = module.exports = {};
var cachedSetTimeout; var cachedSetTimeout;
var cachedClearTimeout; var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () { (function () {
try { try {
cachedSetTimeout = setTimeout; if (typeof setTimeout === 'function') {
} catch (e) { cachedSetTimeout = setTimeout;
cachedSetTimeout = function () { } else {
throw new Error('setTimeout is not defined'); cachedSetTimeout = defaultSetTimout;
} }
} catch (e) {
cachedSetTimeout = defaultSetTimout;
} }
try { try {
cachedClearTimeout = clearTimeout; if (typeof clearTimeout === 'function') {
} catch (e) { cachedClearTimeout = clearTimeout;
cachedClearTimeout = function () { } else {
throw new Error('clearTimeout is not defined'); cachedClearTimeout = defaultClearTimeout;
} }
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
} }
} ()) } ())
function runTimeout(fun) { function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) { if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0); return setTimeout(fun, 0);
} else {
return cachedSetTimeout.call(null, fun, 0);
} }
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
} }
function runClearTimeout(marker) { function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) { if (cachedClearTimeout === clearTimeout) {
clearTimeout(marker); //normal enviroments in sane situations
} else { return clearTimeout(marker);
cachedClearTimeout.call(null, marker);
} }
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
} }
var queue = []; var queue = [];
var draining = false; var draining = false;
@@ -121,6 +169,10 @@ process.off = noop;
process.removeListener = noop; process.removeListener = noop;
process.removeAllListeners = noop; process.removeAllListeners = noop;
process.emit = noop; process.emit = noop;
process.prependListener = noop;
process.prependOnceListener = noop;
process.listeners = function (name) { return [] }
process.binding = function (name) { process.binding = function (name) {
throw new Error('process.binding is not supported'); throw new Error('process.binding is not supported');
@@ -2789,7 +2841,8 @@ DygraphInteraction.defaultModel = {
// Give plugins a chance to grab this event. // Give plugins a chance to grab this event.
var e = { var e = {
canvasx: context.dragEndX, canvasx: context.dragEndX,
canvasy: context.dragEndY canvasy: context.dragEndY,
cancelable: true
}; };
if (g.cascadeEvents_('dblclick', e)) { if (g.cascadeEvents_('dblclick', e)) {
return; return;
@@ -3447,6 +3500,12 @@ if (typeof process !== 'undefined') {
"type": "integer", "type": "integer",
"description": "Width, in pixels, of the chart. If the container div has been explicitly sized, this will be ignored." "description": "Width, in pixels, of the chart. If the container div has been explicitly sized, this will be ignored."
}, },
"pixelRatio": {
"default": "(devicePixelRatio / context.backingStoreRatio)",
"labels": ["Overall display"],
"type": "float",
"description": "Overrides the pixel ratio scaling factor for the canvas's 2d context. Ordinarily, this is set to the devicePixelRatio / (context.backingStoreRatio || 1), so on mobile devices, where the devicePixelRatio can be somewhere around 3, performance can be improved by overriding this value to something less precise, like 1, at the expense of resolution."
},
"interactionModel": { "interactionModel": {
"default": "...", "default": "...",
"labels": ["Interactive Elements"], "labels": ["Interactive Elements"],
@@ -3716,7 +3775,7 @@ if (typeof process !== 'undefined') {
"default": "null", "default": "null",
"labels": ["Axis display", "Interactive Elements"], "labels": ["Axis display", "Interactive Elements"],
"type": "float", "type": "float",
"description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% pased the edges of the displayed values. null means no bounds." "description": "A value representing the farthest a graph may be panned, in percent of the display. For example, a value of 0.1 means that the graph can only be panned 10% passed the edges of the displayed values. null means no bounds."
}, },
"title": { "title": {
"labels": ["Chart labels"], "labels": ["Chart labels"],
@@ -4646,29 +4705,36 @@ var dateTicker = function dateTicker(a, b, pixels, opts, dygraph, vals) {
exports.dateTicker = dateTicker; exports.dateTicker = dateTicker;
// Time granularity enumeration // Time granularity enumeration
var Granularity = { var Granularity = {
SECONDLY: 0, MILLISECONDLY: 0,
TWO_SECONDLY: 1, TWO_MILLISECONDLY: 1,
FIVE_SECONDLY: 2, FIVE_MILLISECONDLY: 2,
TEN_SECONDLY: 3, TEN_MILLISECONDLY: 3,
THIRTY_SECONDLY: 4, FIFTY_MILLISECONDLY: 4,
MINUTELY: 5, HUNDRED_MILLISECONDLY: 5,
TWO_MINUTELY: 6, FIVE_HUNDRED_MILLISECONDLY: 6,
FIVE_MINUTELY: 7, SECONDLY: 7,
TEN_MINUTELY: 8, TWO_SECONDLY: 8,
THIRTY_MINUTELY: 9, FIVE_SECONDLY: 9,
HOURLY: 10, TEN_SECONDLY: 10,
TWO_HOURLY: 11, THIRTY_SECONDLY: 11,
SIX_HOURLY: 12, MINUTELY: 12,
DAILY: 13, TWO_MINUTELY: 13,
TWO_DAILY: 14, FIVE_MINUTELY: 14,
WEEKLY: 15, TEN_MINUTELY: 15,
MONTHLY: 16, THIRTY_MINUTELY: 16,
QUARTERLY: 17, HOURLY: 17,
BIANNUAL: 18, TWO_HOURLY: 18,
ANNUAL: 19, SIX_HOURLY: 19,
DECADAL: 20, DAILY: 20,
CENTENNIAL: 21, TWO_DAILY: 21,
NUM_GRANULARITIES: 22 WEEKLY: 22,
MONTHLY: 23,
QUARTERLY: 24,
BIANNUAL: 25,
ANNUAL: 26,
DECADAL: 27,
CENTENNIAL: 28,
NUM_GRANULARITIES: 29
}; };
exports.Granularity = Granularity; exports.Granularity = Granularity;
@@ -4699,6 +4765,13 @@ var DateField = {
* @type {Array.<{datefield:number, step:number, spacing:number}>} * @type {Array.<{datefield:number, step:number, spacing:number}>}
*/ */
var TICK_PLACEMENT = []; var TICK_PLACEMENT = [];
TICK_PLACEMENT[Granularity.MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 1, spacing: 1 };
TICK_PLACEMENT[Granularity.TWO_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 2, spacing: 2 };
TICK_PLACEMENT[Granularity.FIVE_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 5, spacing: 5 };
TICK_PLACEMENT[Granularity.TEN_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 10, spacing: 10 };
TICK_PLACEMENT[Granularity.FIFTY_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 50, spacing: 50 };
TICK_PLACEMENT[Granularity.HUNDRED_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 100, spacing: 100 };
TICK_PLACEMENT[Granularity.FIVE_HUNDRED_MILLISECONDLY] = { datefield: DateField.DATEFIELD_MS, step: 500, spacing: 500 };
TICK_PLACEMENT[Granularity.SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 1, spacing: 1000 * 1 }; TICK_PLACEMENT[Granularity.SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 1, spacing: 1000 * 1 };
TICK_PLACEMENT[Granularity.TWO_SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 2, spacing: 1000 * 2 }; TICK_PLACEMENT[Granularity.TWO_SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 2, spacing: 1000 * 2 };
TICK_PLACEMENT[Granularity.FIVE_SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 5, spacing: 1000 * 5 }; TICK_PLACEMENT[Granularity.FIVE_SECONDLY] = { datefield: DateField.DATEFIELD_SS, step: 5, spacing: 1000 * 5 };
@@ -4963,7 +5036,7 @@ var logRangeFraction = function logRangeFraction(r0, r1, pct) {
// Original calcuation: // Original calcuation:
// pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0]))); // pct = (log(x) - log(xRange[0])) / (log(xRange[1]) - log(xRange[0])));
// //
// Multiply both sides by the right-side demoninator. // Multiply both sides by the right-side denominator.
// pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0]) // pct * (log(xRange[1] - log(xRange[0]))) = log(x) - log(xRange[0])
// //
// add log(xRange[0]) to both sides // add log(xRange[0]) to both sides
@@ -5231,7 +5304,7 @@ function isValidPoint(p, opt_allowNaNY) {
; ;
/** /**
* Number formatting function which mimicks the behavior of %g in printf, i.e. * Number formatting function which mimics the behavior of %g in printf, i.e.
* either exponential or fixed format (without trailing 0s) is used depending on * either exponential or fixed format (without trailing 0s) is used depending on
* the length of the generated string. The advantage of this format is that * the length of the generated string. The advantage of this format is that
* there is a predictable upper bound on the resulting string length, * there is a predictable upper bound on the resulting string length,
@@ -5385,7 +5458,7 @@ function hmsString_(hh, mm, ss, ms) {
/** /**
* Convert a JS date (millis since epoch) to a formatted string. * Convert a JS date (millis since epoch) to a formatted string.
* @param {number} time The JavaScript time value (ms since epoch) * @param {number} time The JavaScript time value (ms since epoch)
* @param {boolean} utc Wether output UTC or local time * @param {boolean} utc Whether output UTC or local time
* @return {string} A date of one of these forms: * @return {string} A date of one of these forms:
* "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS" * "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS"
* @private * @private
@@ -6293,6 +6366,12 @@ function dateAxisLabelFormatter(date, granularity, opts) {
if (frac === 0 || granularity >= DygraphTickers.Granularity.DAILY) { if (frac === 0 || granularity >= DygraphTickers.Granularity.DAILY) {
// e.g. '21 Jan' (%d%b) // e.g. '21 Jan' (%d%b)
return zeropad(day) + '&#160;' + SHORT_MONTH_NAMES_[month]; return zeropad(day) + '&#160;' + SHORT_MONTH_NAMES_[month];
} else if (granularity < DygraphTickers.Granularity.SECONDLY) {
// e.g. 40.310 (meaning 40 seconds and 310 milliseconds)
var str = "" + millis;
return zeropad(secs) + "." + ('000' + str).substring(str.length);
} else if (granularity > DygraphTickers.Granularity.MINUTELY) {
return hmsString_(hours, mins, secs, 0);
} else { } else {
return hmsString_(hours, mins, secs, millis); return hmsString_(hours, mins, secs, millis);
} }
@@ -6372,7 +6451,7 @@ function dateValueFormatter(d, opts) {
* @param {Object} attrs Various other attributes, e.g. errorBars determines * @param {Object} attrs Various other attributes, e.g. errorBars determines
* whether the input data contains error ranges. For a complete list of * whether the input data contains error ranges. For a complete list of
* options, see http://dygraphs.com/options.html. * options, see http://dygraphs.com/options.html.
*/var Dygraph=function Dygraph(div,data,opts){this.__init__(div,data,opts);};Dygraph.NAME = "Dygraph";Dygraph.VERSION = "2.0.0"; // Various default values */var Dygraph=function Dygraph(div,data,opts){this.__init__(div,data,opts);};Dygraph.NAME = "Dygraph";Dygraph.VERSION = "2.1.0"; // Various default values
Dygraph.DEFAULT_ROLL_PERIOD = 1;Dygraph.DEFAULT_WIDTH = 480;Dygraph.DEFAULT_HEIGHT = 320; // For max 60 Hz. animation: Dygraph.DEFAULT_ROLL_PERIOD = 1;Dygraph.DEFAULT_WIDTH = 480;Dygraph.DEFAULT_HEIGHT = 320; // For max 60 Hz. animation:
Dygraph.ANIMATION_STEPS = 12;Dygraph.ANIMATION_DURATION = 200; /** Dygraph.ANIMATION_STEPS = 12;Dygraph.ANIMATION_DURATION = 200; /**
* Standard plotters. These may be used by clients. * Standard plotters. These may be used by clients.
@@ -6643,9 +6722,9 @@ var target=e.target || e.fromElement;var relatedTarget=e.relatedTarget || e.toEl
// This happens when the graph is resized. // This happens when the graph is resized.
if(!this.resizeHandler_){this.resizeHandler_ = function(e){dygraph.resize();}; // Update when the window is resized. if(!this.resizeHandler_){this.resizeHandler_ = function(e){dygraph.resize();}; // Update when the window is resized.
// TODO(danvk): drop frames depending on complexity of the chart. // TODO(danvk): drop frames depending on complexity of the chart.
this.addAndTrackEvent(window,'resize',this.resizeHandler_);}};Dygraph.prototype.resizeElements_ = function(){this.graphDiv.style.width = this.width_ + "px";this.graphDiv.style.height = this.height_ + "px";var canvasScale=utils.getContextPixelRatio(this.canvas_ctx_);this.canvas_.width = this.width_ * canvasScale;this.canvas_.height = this.height_ * canvasScale;this.canvas_.style.width = this.width_ + "px"; // for IE this.addAndTrackEvent(window,'resize',this.resizeHandler_);}};Dygraph.prototype.resizeElements_ = function(){this.graphDiv.style.width = this.width_ + "px";this.graphDiv.style.height = this.height_ + "px";var pixelRatioOption=this.getNumericOption('pixelRatio');var canvasScale=pixelRatioOption || utils.getContextPixelRatio(this.canvas_ctx_);this.canvas_.width = this.width_ * canvasScale;this.canvas_.height = this.height_ * canvasScale;this.canvas_.style.width = this.width_ + "px"; // for IE
this.canvas_.style.height = this.height_ + "px"; // for IE this.canvas_.style.height = this.height_ + "px"; // for IE
if(canvasScale !== 1){this.canvas_ctx_.scale(canvasScale,canvasScale);}var hiddenScale=utils.getContextPixelRatio(this.hidden_ctx_);this.hidden_.width = this.width_ * hiddenScale;this.hidden_.height = this.height_ * hiddenScale;this.hidden_.style.width = this.width_ + "px"; // for IE if(canvasScale !== 1){this.canvas_ctx_.scale(canvasScale,canvasScale);}var hiddenScale=pixelRatioOption || utils.getContextPixelRatio(this.hidden_ctx_);this.hidden_.width = this.width_ * hiddenScale;this.hidden_.height = this.height_ * hiddenScale;this.hidden_.style.width = this.width_ + "px"; // for IE
this.hidden_.style.height = this.height_ + "px"; // for IE this.hidden_.style.height = this.height_ + "px"; // for IE
if(hiddenScale !== 1){this.hidden_ctx_.scale(hiddenScale,hiddenScale);}}; /** if(hiddenScale !== 1){this.hidden_ctx_.scale(hiddenScale,hiddenScale);}}; /**
* Detach DOM elements in the dygraph and null out all data references. * Detach DOM elements in the dygraph and null out all data references.
@@ -6801,6 +6880,7 @@ var oldValueRanges=this.yAxisRanges();var newValueRanges=[];for(var i=0;i < this
*/Dygraph.prototype.resetZoom = function(){var _this4=this;var dirtyX=this.isZoomed('x');var dirtyY=this.isZoomed('y');var dirty=dirtyX || dirtyY; // Clear any selection, since it's likely to be drawn in the wrong place. */Dygraph.prototype.resetZoom = function(){var _this4=this;var dirtyX=this.isZoomed('x');var dirtyY=this.isZoomed('y');var dirty=dirtyX || dirtyY; // Clear any selection, since it's likely to be drawn in the wrong place.
this.clearSelection();if(!dirty)return; // Calculate extremes to avoid lack of padding on reset. this.clearSelection();if(!dirty)return; // Calculate extremes to avoid lack of padding on reset.
var _xAxisExtremes=this.xAxisExtremes();var _xAxisExtremes2=_slicedToArray(_xAxisExtremes,2);var minDate=_xAxisExtremes2[0];var maxDate=_xAxisExtremes2[1];var animatedZooms=this.getBooleanOption('animatedZooms');var zoomCallback=this.getFunctionOption('zoomCallback'); // TODO(danvk): merge this block w/ the code below. var _xAxisExtremes=this.xAxisExtremes();var _xAxisExtremes2=_slicedToArray(_xAxisExtremes,2);var minDate=_xAxisExtremes2[0];var maxDate=_xAxisExtremes2[1];var animatedZooms=this.getBooleanOption('animatedZooms');var zoomCallback=this.getFunctionOption('zoomCallback'); // TODO(danvk): merge this block w/ the code below.
// TODO(danvk): factor out a generic, public zoomTo method.
if(!animatedZooms){this.dateWindow_ = null;this.axes_.forEach(function(axis){if(axis.valueRange)delete axis.valueRange;});this.drawGraph_();if(zoomCallback){zoomCallback.call(this,minDate,maxDate,this.yAxisRanges());}return;}var oldWindow=null,newWindow=null,oldValueRanges=null,newValueRanges=null;if(dirtyX){oldWindow = this.xAxisRange();newWindow = [minDate,maxDate];}if(dirtyY){oldValueRanges = this.yAxisRanges();newValueRanges = this.yAxisExtremes();}this.doAnimatedZoom(oldWindow,newWindow,oldValueRanges,newValueRanges,function(){_this4.dateWindow_ = null;_this4.axes_.forEach(function(axis){if(axis.valueRange)delete axis.valueRange;});if(zoomCallback){zoomCallback.call(_this4,minDate,maxDate,_this4.yAxisRanges());}});}; /** if(!animatedZooms){this.dateWindow_ = null;this.axes_.forEach(function(axis){if(axis.valueRange)delete axis.valueRange;});this.drawGraph_();if(zoomCallback){zoomCallback.call(this,minDate,maxDate,this.yAxisRanges());}return;}var oldWindow=null,newWindow=null,oldValueRanges=null,newValueRanges=null;if(dirtyX){oldWindow = this.xAxisRange();newWindow = [minDate,maxDate];}if(dirtyY){oldValueRanges = this.yAxisRanges();newValueRanges = this.yAxisExtremes();}this.doAnimatedZoom(oldWindow,newWindow,oldValueRanges,newValueRanges,function(){_this4.dateWindow_ = null;_this4.axes_.forEach(function(axis){if(axis.valueRange)delete axis.valueRange;});if(zoomCallback){zoomCallback.call(_this4,minDate,maxDate,_this4.yAxisRanges());}});}; /**
* Combined animation logic for all zoom functions. * Combined animation logic for all zoom functions.
* either the x parameters or y parameters may be null. * either the x parameters or y parameters may be null.
@@ -7217,7 +7297,7 @@ if('rollPeriod' in attrs){this.rollPeriod_ = attrs.rollPeriod;}if('dateWindow' i
// highlightCircleSize // highlightCircleSize
// Check if this set options will require new points. // Check if this set options will require new points.
var requiresNewPoints=utils.isPixelChangingOptionList(this.attr_("labels"),attrs);utils.updateDeep(this.user_attrs_,attrs);this.attributes_.reparseSeries();if(file){ // This event indicates that the data is about to change, but hasn't yet. var requiresNewPoints=utils.isPixelChangingOptionList(this.attr_("labels"),attrs);utils.updateDeep(this.user_attrs_,attrs);this.attributes_.reparseSeries();if(file){ // This event indicates that the data is about to change, but hasn't yet.
// TODO(danvk): support cancelation of the update via this event. // TODO(danvk): support cancellation of the update via this event.
this.cascadeEvents_('dataWillUpdate',{});this.file_ = file;if(!block_redraw)this.start_();}else {if(!block_redraw){if(requiresNewPoints){this.predraw_();}else {this.renderGraph_(false);}}}}; /** this.cascadeEvents_('dataWillUpdate',{});this.file_ = file;if(!block_redraw)this.start_();}else {if(!block_redraw){if(requiresNewPoints){this.predraw_();}else {this.renderGraph_(false);}}}}; /**
* Make a copy of input attributes, removing file as a convenience. * Make a copy of input attributes, removing file as a convenience.
* @private * @private
@@ -8748,8 +8828,8 @@ rangeSelector.prototype.updateVisibility_ = function () {
* Resizes the range selector. * Resizes the range selector.
*/ */
rangeSelector.prototype.resize_ = function () { rangeSelector.prototype.resize_ = function () {
function setElementRect(canvas, context, rect) { function setElementRect(canvas, context, rect, pixelRatioOption) {
var canvasScale = utils.getContextPixelRatio(context); var canvasScale = pixelRatioOption || utils.getContextPixelRatio(context);
canvas.style.top = rect.y + 'px'; canvas.style.top = rect.y + 'px';
canvas.style.left = rect.x + 'px'; canvas.style.left = rect.x + 'px';
@@ -8776,8 +8856,9 @@ rangeSelector.prototype.resize_ = function () {
h: this.getOption_('rangeSelectorHeight') h: this.getOption_('rangeSelectorHeight')
}; };
setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_); var pixelRatioOption = this.dygraph_.getNumericOption('pixelRatio');
setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_); setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_, pixelRatioOption);
setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_, pixelRatioOption);
}; };
/** /**

View File

@@ -1,14 +1,12 @@
var hours = 24; var hours = 24;
var granularity = '2m'; var granularity = '5m';
var end = 0; var end = 0;
var graphdata = "https://bastart.spoton.cz/data/solar_monitor?range=24h&granularity=2m&end=0h"; var retention = 'monthly';
var graphdata = "https://bastart.spoton.cz/data/solar_monitor?range=24h&granularity=5m&end=0h&retention=monthly";
sol = new Dygraph( sol = new Dygraph(
// containing div
document.getElementById("solar"), document.getElementById("solar"),
// CSV or path to a CSV file.
graphdata graphdata
,{ ,{
//labels: ['time','V_solar','Isolar', P_solar, P_cons],
axes : { axes : {
x : { x : {
drawGrid: true, drawGrid: true,
@@ -16,80 +14,82 @@ graphdata
}, },
y : { y : {
drawGrid: false, drawGrid: false,
drawAxis : true drawAxis: true,
valueRange: [44.5,55]
}, },
y2 : { y2 : {
drawGrid: false, drawGrid: false,
drawAxis: true, drawAxis: true,
independentTicks: true independentTicks: true,
customBars: true,
valueRange: [0,1300]
} }
}, },
rollPeriod: 5, rollPeriod: 3,
visibility: [true, false, true, true],
interactionModel: {}, interactionModel: {},
connectSeparatedPoints: true, connectSeparatedPoints: true,
series:{ series:{
'V_solar': {
axis: 'y',
color: '#ffd020',
fillGraph: true,
fillAlpha: 0.4
},
'I_solar': {
axis: 'y',
color: '#ff1100'
},
'P_solar': { 'P_solar': {
axis: 'y2', axis: 'y2',
color: '#1111ff', color: '#ff5500'
fillGraph: true,
fillAlpha: 0.4
}, },
'P_cons': { 'V_array': {
axis: 'y2', axis: 'y',
color: '#ff1111', color: '#666'
fillGraph: true,
fillAlpha: 0.4
} }
}, },
ylabel: '<span style="color:#ffd020;">[V]</span>/<span style="color:#ff1100;">[A]</span>', ylabel: '<span style="color:#666;">Battery [V]</span>',
y2label: '<span style="color:#111177;">Solar / Consumption [W]</span>', y2label: '<span style="color:#ff2200;">Power [W]</span>',
labelsDiv: 'solar_labels', labelsDiv: 'solar_labels',
legend: 'always' legend: 'always',
customBars: true
} }
); );
function refreshGraph(){ function refreshGraph(){
graphdata = "https://bastart.spoton.cz/data/solar_monitor?range=" + hours + "h&granularity=" + granularity + "&end=" + end + "h"; graphdata = "https://bastart.spoton.cz/data/solar_monitor?range=" + hours + "h&granularity=" + granularity + "&end=" + end + "h&retention=" + retention;
sol.updateOptions({'file': graphdata}); sol.updateOptions({'file': graphdata});
//power.updateOptions({'file': graphdata});
} }
function setHours(hours_to_set){ function setHours(hours_to_set){
hours = hours_to_set; hours = hours_to_set;
switch(hours){ switch(hours){
case '1': case '1':
granularity = '30s'; granularity = '10s';
retention = 'monthly';
break; break;
case '6': case '6':
granularity = '1m'; granularity = '10s';
retention = 'monthly';
break; break;
case '12': case '12':
granularity = '1m'; granularity = '2m';
retention = 'monthly';
break; break;
case '24': case '24':
granularity = '2m'; granularity = '5m';
retention = 'monthly';
break; break;
case '168': case '168':
granularity = '20m'; granularity = '15m';
retention = 'monthly';
break; break;
case '720': case '720':
granularity = '1h'; granularity = '3h';
retention = 'yearly';
break;
case '8760':
granularity = '6h';
retention = 'yearly';
break;
case '87600':
granularity = '24h';
retention = 'yearly';
break; break;
default: default:
granularity = '10m'; granularity = '5m';
retention = 'monthly';
} }
end = 0; end = 0;
//document.getElementById('xxx').innerHTML = graphdata; //document.getElementById('xxx').innerHTML = graphdata;
@@ -118,3 +118,49 @@ function setForth(){
//document.getElementById('xxx').innerHTML = graphdata; //document.getElementById('xxx').innerHTML = graphdata;
refreshGraph(); refreshGraph();
} }
function getPageContents(callback,url,params) {
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari, SeaMonkey
xmlhttp=new XMLHttpRequest();
}
else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if(params!=null) {
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
} else {
xmlhttp.open("GET", url, true);
}
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback(xmlhttp.responseText);
}
}
xmlhttp.send(params);
}
counter = 0;
function refreshValues(){
fresh_vals_url = '/data/solar_realtime_data?type=json'
getPageContents(function(result){freshVals=JSON.parse(result);},
fresh_vals_url)
document.getElementById('timestamp').innerHTML = freshVals.time;
document.getElementById('array_voltage').innerHTML = freshVals.V_array;
document.getElementById('array_percent').innerHTML = freshVals.perc_array;
document.getElementById('charge_current').innerHTML = freshVals.ChCurr;
document.getElementById('solar_power').innerHTML = freshVals.Psol;
document.getElementById('pmax_day').innerHTML = freshVals.Pmax_day;
counter = counter + 5000;
if(counter >= 360000){
refreshGraph();
document.getElementById('graph_timestamp').innerHTML = freshVals.time;
counter = 0;
}
}
var intervalVal = setInterval(refreshValues, 5000);

View File

@@ -1,16 +1,53 @@
var hours = 24; //defaults
var granularity = '1m'; var default_granularity = '5m'; // needs to be specified as string, changes
var end = 0; var default_hours = 24; // int is OK, (h) hardcoded
var winddata = "https://bastart.spoton.cz/data/wind_monitor?range=24h&granularity=1m&end=0h"; var default_end = 0; // detto
var temphumidata = "https://bastart.spoton.cz/data/temphumi_monitor?range=24h&granularity=2m&end=0h"; var base_url = "https://bastart.spoton.cz/data/";
var pressuredata = "https://bastart.spoton.cz/data/pressure_monitor?range=168h&granularity=2m&end=0h"; var counter = 0;
var tout = 5000; // fresh date refresh rate, in ms
var g_tout = 30000; // graph update rate, in ms
//initialize the uninitialized
var hours = new Object();
var granularity = new Object();
var end = new Object();
var graphdata = new Object();
var data = new Object();
// types match function names in python's Dynamic.py class
var types = Array('wind_monitor',
'temphumi_monitor',
'pressure_monitor',
'rrate_monitor');
// Now let's set up the defaults and primary data sources, leter changed dynamically
var types_size = types.length;
for(var i=0; i<types_size; i++){
var type = types[i];
hours[type] = default_hours;
granularity[type] = default_granularity;
end[type] = default_end;
if(type == 'wind_monitor'){
hours[type] = 12;
granularity[type] = '1m';
}
data[type] = base_url + type + "?range=" + hours[type] + "h&granularity=" + granularity[type] + "&end=" + default_end + "h";
if(type == 'pressure_monitor'){
hours[type] = 168;
granularity[type] = '1h';
data[type] = base_url + type + "?range=" + hours[type] + "h&granularity=" + granularity[type] + "&end=" + default_end + "h";
}
if(type == 'rrate_monitor'){
hours[type] = 168;
granularity[type] = '1h';
data[type] = base_url + type + "?range=" + hours[type] + "h&granularity=" + granularity[type] + "&end=" + default_end + "h";
}
}
wind = new Dygraph( wind = new Dygraph(
// containing div
document.getElementById("wind"), document.getElementById("wind"),
// CSV or path to a CSV file. data['wind_monitor'],
winddata {
,{
//labels: ['time','Speed','Gust', 'Direction'],
axes : { axes : {
x : { x : {
drawGrid: true, drawGrid: true,
@@ -27,7 +64,7 @@ winddata
independentTicks: true independentTicks: true
} }
}, },
rollPeriod: 20, rollPeriod: 5,
interactionModel: {}, interactionModel: {},
connectSeparatedPoints: true, connectSeparatedPoints: true,
series:{ series:{
@@ -45,7 +82,6 @@ winddata
axis: 'y2', axis: 'y2',
color: '#999999' color: '#999999'
} }
}, },
ylabel: '<span style="color:#444444;">Speed<span style="color:#444444;"> / <span style="color:#ff5555;">Gusts</span> [km/h]', ylabel: '<span style="color:#444444;">Speed<span style="color:#444444;"> / <span style="color:#ff5555;">Gusts</span> [km/h]',
y2label: '<span style="color:#999999;">Direction [&deg;]</span>', y2label: '<span style="color:#999999;">Direction [&deg;]</span>',
@@ -55,12 +91,9 @@ winddata
); );
temphumi_out = new Dygraph( temphumi_out = new Dygraph(
// containing div
document.getElementById("temphumi"), document.getElementById("temphumi"),
// CSV or path to a CSV file. data['temphumi_monitor'],
temphumidata {
,{
//labels: [time,T(ins),T(out),Humi(ins),Humi(out)],
axes : { axes : {
x : { x : {
drawGrid: true, drawGrid: true,
@@ -76,7 +109,7 @@ temphumidata
independentTicks: true independentTicks: true
} }
}, },
rollPeriod: 10, rollPeriod: 5,
visibility: [false, true, false, true], visibility: [false, true, false, true],
interactionModel: {}, interactionModel: {},
connectSeparatedPoints: true, connectSeparatedPoints: true,
@@ -101,7 +134,6 @@ temphumidata
axis: 'y2', axis: 'y2',
color: '#222288' color: '#222288'
} }
}, },
ylabel: '<span style="color:#555555;">Outside [&deg;C]</span>', ylabel: '<span style="color:#555555;">Outside [&deg;C]</span>',
y2label: '<span style="color:#222288;">Humidity [%]</span>', y2label: '<span style="color:#222288;">Humidity [%]</span>',
@@ -111,12 +143,9 @@ temphumidata
); );
temphumi_in = new Dygraph( temphumi_in = new Dygraph(
// containing div
document.getElementById("temphumi_in"), document.getElementById("temphumi_in"),
// CSV or path to a CSV file. data['temphumi_monitor'],
temphumidata {
,{
//labels: [time,T(ins),T(out),Humi(ins),Humi(out)],
axes : { axes : {
x : { x : {
drawGrid: true, drawGrid: true,
@@ -134,7 +163,7 @@ temphumidata
valueRange: [0,100] valueRange: [0,100]
} }
}, },
rollPeriod: 10, rollPeriod: 5,
visibility: [true, false, true, false], visibility: [true, false, true, false],
interactionModel: {}, interactionModel: {},
connectSeparatedPoints: true, connectSeparatedPoints: true,
@@ -159,7 +188,6 @@ temphumidata
axis: 'y2', axis: 'y2',
color: '#222288' color: '#222288'
} }
}, },
ylabel: '<span style="color:#555555;">Inside [&deg;C]</span>', ylabel: '<span style="color:#555555;">Inside [&deg;C]</span>',
y2label: '<span style="color:#222288;">Humidity [%]</span>', y2label: '<span style="color:#222288;">Humidity [%]</span>',
@@ -169,12 +197,9 @@ temphumidata
); );
pressure = new Dygraph( pressure = new Dygraph(
// containing div
document.getElementById("pressure"), document.getElementById("pressure"),
// CSV or path to a CSV file. data['pressure_monitor'],
pressuredata {
,{
//labels: [time,Pressure],
axes : { axes : {
x : { x : {
drawGrid: true, drawGrid: true,
@@ -191,7 +216,7 @@ pressuredata
valueRange: [970,1055] valueRange: [970,1055]
} }
}, },
rollPeriod: 10, rollPeriod: 20,
interactionModel: {}, interactionModel: {},
connectSeparatedPoints: true, connectSeparatedPoints: true,
visibility: [true, false], visibility: [true, false],
@@ -208,7 +233,6 @@ pressuredata
fillGraph: true, fillGraph: true,
fillAlpha: 0.5 fillAlpha: 0.5
} }
}, },
ylabel: '<span style="color:#555555;">Pressure [hPa]</span>', ylabel: '<span style="color:#555555;">Pressure [hPa]</span>',
labelsDiv: 'pressure_labels', labelsDiv: 'pressure_labels',
@@ -216,81 +240,175 @@ pressuredata
} }
); );
rrate = new Dygraph(
document.getElementById("rrate"),
data['rrate_monitor'],
{
axes : {
x : {
drawGrid: true,
drawAxis : true
},
y : {
drawGrid: false,
drawAxis : true,
valueRange: [0,3]
},
y2 : {
drawGrid: false,
drawAxis: true,
valueRange: [0,3]
}
},
rollPeriod: 0,
interactionModel: {},
connectSeparatedPoints: true,
visibility: [true, true],
series:{
'Rrate': {
axis: 'y',
color: '#0055ff',
fillGraph: true,
fillAlpha: 0.5
},
'Rrate_max': {
axis: 'y2',
color: '#0000aa',
fillGraph: false
}
},
ylabel: '<span style="color:#555555;">Rain rate [mm/h]</span>',
labelsDiv: 'rrate_labels',
legend: 'always'
}
);
// Functions for buttons to scale / move graphs
function refreshGraph(source){ function refreshGraph(source){
graphdata = "https://bastart.spoton.cz/data/" + source + "?range=" + hours + "h&granularity=" + granularity + "&end=" + end + "h"; graphdata[source] = "https://bastart.spoton.cz/data/" + source + "?range=" + hours[source] + "h&granularity=" + granularity[source] + "&end=" + end[source] + "h";
if(source == 'wind_monitor'){ if(source == 'wind_monitor'){
wind.updateOptions({'file': graphdata}); wind.updateOptions({'file': graphdata[source]});
} }
if(source == 'temphumi_monitor'){ if(source == 'temphumi_monitor'){
temphumi_out.updateOptions({'file': graphdata}); temphumi_out.updateOptions({'file': graphdata[source]});
temphumi_in.updateOptions({'file': graphdata}); temphumi_in.updateOptions({'file': graphdata[source]});
} }
if(source == 'pressure_monitor'){ if(source == 'pressure_monitor'){
pressure.updateOptions({'file': graphdata}); pressure.updateOptions({'file': graphdata[source]});
} }
//document.getElementById('xxx').innerHTML = source; if(source == 'rrate_monitor'){
//power.updateOptions({'file': graphdata}); rrate.updateOptions({'file': graphdata[source]});
}
// TODO: adjust to update graph timestamps per click on ranges
// document.getElementById('g_tstamp_' + source).innerHTML = freshVals.time;
} }
// here, target needs to match the python's dynamic class again
function setHours(hours_to_set, target){ function setHours(hours_to_set, target){
hours = hours_to_set; hours[target] = hours_to_set;
switch(hours){ switch(hours[target]){
case '1': case '1':
granularity = '1m'; granularity[target] = '30s';
if(target == 'temphumi_monitor'){ granularity = '2m';} if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
break; break;
case '6': case '6':
granularity = '1m'; granularity[target] = '1m';
if(target == 'temphumi_monitor'){ granularity = '2m';} if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
break; break;
case '12': case '12':
granularity = '1m'; granularity[target] = '2m';
if(target == 'temphumi_monitor'){ granularity = '2m';} if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
break; break;
case '24': case '24':
granularity = '1m'; granularity[target] = '5m';
if(target == 'temphumi_monitor'){ granularity = '2m';} if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
break; break;
case '168': case '168':
granularity = '10m'; granularity[target] = '10m';
break; break;
case '720': case '720':
granularity = '1h'; granularity[target] = '1h';
break; break;
case '4320': case '4320':
granularity = '6h'; granularity[target] = '12h';
break; break;
case '8640': case '8640':
granularity = '1d'; granularity[target] = '24h';
break; break;
default: default:
granularity = '10m'; granularity[target] = default_granularity;
} }
end = 0; end[target] = 0;
//document.getElementById('xxx').innerHTML = target;
refreshGraph(target); refreshGraph(target);
} }
// Functions for buttons to scale / move graphs
function setBack(target){ function setBack(target){
// range=1h -> range=2h&end=1h disp_range = hours[target]*1 - end[target]*1;
disp_range = hours*1 - end*1; hours[target] = hours[target]*1 + disp_range;
hours = hours*1 + disp_range; end[target] = end[target]*1 + disp_range;
end = end*1 + disp_range;
//document.getElementById('xxx').innerHTML = graphdata;
refreshGraph(target); refreshGraph(target);
} }
function setForth(target){ function setForth(target){
disp_range = hours*1 - end*1; disp_range = hours[target]*1 - end[target]*1;
hours = hours*1 - disp_range; hours[target] = hours[target]*1 - disp_range;
if(hours < disp_range){ if(hours[target] < disp_range){
hours = disp_range; hours[target] = disp_range;
} }
end = end*1 - disp_range; end[target] = end[target]*1 - disp_range;
if(end < 0){ if(end[target] < 0){
end = 0; end[target] = 0;
} }
//document.getElementById('xxx').innerHTML = graphdata;
refreshGraph(target); refreshGraph(target);
} }
function getPageContents(callback,url,params) {
if (window.XMLHttpRequest){
// code for IE7+, Firefox, Chrome, Opera, Safari, SeaMonkey
xmlhttp=new XMLHttpRequest();
}
else{
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
if(params!=null) {
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
} else {
xmlhttp.open("GET", url, true);
}
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
callback(xmlhttp.responseText);
}
}
xmlhttp.send(params);
}
function refreshValues(){
fresh_vals_url = '/data/weather_realtime_data?type=json'
getPageContents(function(result){freshVals=JSON.parse(result);},
fresh_vals_url)
document.getElementById('timestamp').innerHTML = freshVals.time;
document.getElementById('w_speed_km').innerHTML = freshVals.wind.speed;
document.getElementById('w_speed_ms').innerHTML = freshVals.wind.speed_ms;
document.getElementById('w_dir').innerHTML = freshVals.wind.dir;
document.getElementById('w_gust_km').innerHTML = freshVals.wind.gust;
document.getElementById('w_gust_ms').innerHTML = freshVals.wind.gust_ms;
document.getElementById('w_dir_name').innerHTML = freshVals.wind.dir_name;
document.getElementById('out_temp').innerHTML = freshVals.temperature.out;
document.getElementById('in_temp').innerHTML = freshVals.temperature.in;
document.getElementById('current_pressure').innerHTML = freshVals.pressure;
document.getElementById('current_rrate').innerHTML = freshVals.rainrate;
counter = counter + tout;
if(counter >= g_tout){
for(var i=0; i<types_size; i++){
var type = types[i];
refreshGraph(type);
document.getElementById('g_tstamp_' + type).innerHTML = freshVals.time;
}
counter = 0;
}
}
var intervalVal = setInterval(refreshValues, tout);

View File

@@ -1,6 +1,6 @@
<div id="footer"> <div id="footer">
Created in 101 minutes, in VI, while sitting in a train Wien -> Bratislava. Measurements utilise Arduino, ESP8266, lot of python, another lot
Uploeaded over EDGE with a lot of signal-less territory on roaming. Cheers. of Micropython, tons of "heart", no cocaine, but shitloads of Tea. Cheers.
Done by Ventil. Done by Ventil.
</div> </div>
</body> </body>

View File

@@ -10,14 +10,37 @@
<meta name="Keywords" content="automation, python, development, arduino, measurement"> <meta name="Keywords" content="automation, python, development, arduino, measurement">
<meta name="description" content="RasPi automation hardcore"> <meta name="description" content="RasPi automation hardcore">
<meta name="Author" content="Spoton s.r.o. | Milan Toman"> <meta name="Author" content="Spoton s.r.o. | Milan Toman">
<link rel="stylesheet" type="text/css" href="./static/css/def_style.css"> <link rel="stylesheet" type="text/css" href="https://bastart.spoton.cz/static/css/def_style.css">
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link href="../static/css/bootstrap.min.css" rel="stylesheet"> <link href="https://bastart.spoton.cz/static/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this template --> <!-- Custom styles for this template -->
<link href="../static/css/dashboard.css" rel="stylesheet"> <link href="https://bastart.spoton.cz/static/css/dashboard.css" rel="stylesheet">
<!-- Dygraph css and js --> <!-- Dygraph css and js -->
<link href="../static/css/dygraph.css" rel="stylesheet"> <link href="https://bastart.spoton.cz/static/css/dygraph.css" rel="stylesheet">
<script type="text/javascript" src="../static/js/dygraph.js"></script> <script type="text/javascript" src="https://bastart.spoton.cz/static/js/dygraph.js"></script>
<link rel="icon" href="../../favicon.ico"> <link rel="icon" href="../../favicon.ico">
</head> </head>
<body> <body>
<!--
<script>
//window.fbAsyncInit = function() {
// FB.init({
// appId : '315766815677378',
// cookie : true,
// xfbml : true,
// version : 'v3.2'
// });
//
// FB.AppEvents.logPageView();
//
//};
//
//(function(d, s, id){
// var js, fjs = d.getElementsByTagName(s)[0];
// if (d.getElementById(id)) {return;}
// js = d.createElement(s); js.id = id;
// js.src = "https://connect.facebook.net/en_US/sdk.js";
// fjs.parentNode.insertBefore(js, fjs);
// }(document, 'script', 'facebook-jssdk'));
</script>-->

56
web/templates/status_admin.html Normal file → Executable file
View File

@@ -4,19 +4,35 @@
<div class="col"></div> <div class="col"></div>
<main class="pt-4 col-10"> <main class="pt-4 col-10">
<h1>Status Dashboard</h1> <h1>Status Dashboard</h1>
<h5>{timestamp} UTC</h5> <h5 id="timestamp">{timestamp} UTC</h5>
<p>Up since: {_uptime}</p>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
<div class="col placeholder"> <div class="col placeholder">
<img src="{sol_icon}" width="20" class="img-fluid" alt="ISS solar irradiation"> <img src="{sol_icon}" width="20" class="img-fluid" alt="ISS solar irradiation">
<h3>{sol_value}</h3> <h3 id="sol_val">{_sol_value}</h3>
<div class="text-muted">[V]</div> <div class="text-muted">[V]</div>
</div> </div>
<div class="col placeholder"> <div class="col placeholder">
<img src="{cap_icon}" width="20" class="img-fluid" alt="ISS Capacitor state"> <img src="{cap_icon}" width="20" class="img-fluid" alt="ISS Capacitor state">
<h3>{cap_value}</h3> <h3 id="cap_val">{_cap_value}</h3>
<div class="text-muted">[V]</div> <div class="text-muted">[V]</div>
</div> </div>
<div class="col placeholder">
<img src="{cpu_icon}" width="20" class="img-fluid" alt="CPU %">
<h3 id="cpu_val">{_cpu}</h3>
<div class="text-muted">[%]</div>
</div>
<div class="col placeholder">
<img src="{mem_icon}" width="20" class="img-fluid" alt="Mem / Disk %">
<h3><span id="mem">{_mem}</span> / <span id="disk">{_disk}</span></h3>
<div class="text-muted">[%]</div>
</div>
<div class="col placeholder">
<img src="{network_icon}" width="20" class="img-fluid" alt="RasPI network">
<h3><span id="net_in">{_net_in}</span> / <span id="net_out">{_net_out}</span></h3>
<div class="text-muted">IN [kB/s] / OUT [kB/s]</div>
</div>
</section> </section>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
<div class="col"> <div class="col">
@@ -31,6 +47,7 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','solcap_monitor')">6Mo</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','solcap_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','solcap_monitor')">Year</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','solcap_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('solcap_monitor')">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth('solcap_monitor')">&gt;&gt;</button>
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
</div> </div>
</section> </section>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
@@ -47,8 +64,39 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','cpumem_monitor')">6Mo</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','cpumem_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','cpumem_monitor')">Year</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','cpumem_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('cpumem_monitor')">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth('cpumem_monitor')">&gt;&gt;</button>
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
</div> </div>
<script type="text/javascript" src="../static/js/solcap_graph.js"></script> </section>
<section class="row text-center placeholders">
<div class="col">
<div id="network_labels"></div>
<div id="network" class="container-fluid" style="width:100%;height:200px;"></div>
<button type="button" class="btn btn-secondary" onclick="setBack('network_monitor')">&lt;&lt;</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('1','network_monitor')">1h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('6','network_monitor')">6h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('12','network_monitor')">12h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24','network_monitor')">24h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168','network_monitor')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('720','network_monitor')">Month</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','network_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','network_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('network_monitor')">&gt;&gt;</button>
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
</div>
</section>
<section class="row text-center placeholders">
<div class="col">
<div id="esp_battery_labels"></div>
<div id="esp_battery" class="container-fluid" style="width:100%;height:200px;"></div>
<button type="button" class="btn btn-secondary" onclick="setBack('esp_battery_monitor')">&lt;&lt;</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168','esp_battery_monitor')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('720','esp_battery_monitor')">Month</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','esp_battery_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','esp_battery_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('esp_battery_monitor')">&gt;&gt;</button>
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
</div>
<script type="text/javascript" src="../static/js/status_graph.js"></script>
</section> </section>
</main> </main>
<div class="col"></div> <div class="col"></div>

View File

@@ -2,7 +2,7 @@
<button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler navbar-toggler-right hidden-lg-up" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span> <span class="navbar-toggler-icon"></span>
</button> </button>
<a class="navbar-brand" href="#">Monitoring</a> <a class="navbar-brand" href="https://bastart.spoton.cz">Monitoring</a>
<div class="collapse navbar-collapse" id="navbarsExampleDefault"> <div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto"> <ul class="navbar-nav mr-auto">
@@ -15,6 +15,9 @@
<li class="nav-item {status}"> <li class="nav-item {status}">
<a class="nav-link" href="https://bastart.spoton.cz/status">Status</a> <a class="nav-link" href="https://bastart.spoton.cz/status">Status</a>
</li> </li>
<li class="nav-item {temphumi}">
<a class="nav-link" href="https://bastart.spoton.cz/temphumi">Temp / Humidity</a>
</li>
</ul> </ul>
</div> </div>
</nav> </nav>

View File

@@ -4,31 +4,26 @@
<div class="col"></div> <div class="col"></div>
<main class="pt-4 col-10"> <main class="pt-4 col-10">
<h1>Energy Dashboard</h1> <h1>Energy Dashboard</h1>
<h5><span id="timestamp">{timestamp}</span> UTC</h5>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
<div class="col placeholder"> <div class="col placeholder">
<img src="{array_voltage_icon}" width="20" class="img-fluid" alt="Battery voltage"> <img src="{array_voltage_icon}" width="20" class="img-fluid" alt="Battery voltage">
<h3>{array_voltage} [V]</h3> <h3><span id="array_voltage">{array_voltage}</span> [V]</h3>
<div class="text-muted">{array_percent} [%]</div> <div class="text-muted"><span id="array_percent">{array_percent}</span> [%]</div>
</div> </div>
<div class="col placeholder"> <div class="col placeholder">
<img src="../static/img/battery_current.png" width="20" class="img-fluid" alt="Battery current"> <img src="{charge_current_icon}" width="20" class="img-fluid" alt="Battery current">
<h3>{charge_current}</h3> <h3><span id="charge_current">{charge_current}</span></h3>
<div class="text-muted">Charging [A]</div> <div class="text-muted">Charging [A]</div>
</div> </div>
<div class="col placeholder"> <div class="col placeholder">
<img src="../static/img/solar_power.png" width="20" class="img-fluid" alt="Solar array power"> <img src="{solar_power_icon}" width="40" class="img-fluid" alt="Solar array power">
<h3>{solar_power}</h3> <h3><span id=solar_power>{solar_power}</span></h3>
<span class="text-muted"> Solar PV [W]</span> <span class="text-muted"> Solar PV [W]</span>
</div> </div>
<div class="col placeholder"> <div class="col placeholder">
<img src="../static/img/solar_voltage.png" width="20" class="img-fluid" alt="Solar array voltage"> <img src="{solar_power_icon}" width="40" class="img-fluid" alt="Max power / day">
<h3>{voltage_solar}</h3> <h3><span id=pmax_day>{pmax_day}</span></h3>
<div class="text-muted">Solar [V]</div>
</div>
<div class="col placeholder">
<img src="../static/img/pmax_day.png" width="20" class="img-fluid" alt="Max power / day">
<h3>{pmax_day}</h3>
<div class="text-muted">Pmax / day [W]</div> <div class="text-muted">Pmax / day [W]</div>
</div> </div>
</section> </section>
@@ -45,19 +40,15 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24')">24h</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24')">24h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168')">Week</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('720')">Month</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('720')">Month</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8760')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth()">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth()">&gt;&gt;</button>
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
</div> </div>
<div id="xxx"></div>
</section> </section>
<div class="table-responisve"> <div class="table-responisve">
<h2>Historical values by day</h2> <h2>Historical values by day</h2>
{history_table}
</div>
<div class="table-responsive">
{stats_table} {stats_table}
{fresh_table}
</div> </div>
</main> </main>
<div class="col"></div> <div class="col"></div>

View File

@@ -4,40 +4,50 @@
<div class="col"></div> <div class="col"></div>
<main class="pt-4 col-10"> <main class="pt-4 col-10">
<h1>Weather Dashboard</h1> <h1>Weather Dashboard</h1>
<h5>{timestamp} UTC</h5> <h5><span id="timestamp">{_timestamp}</span> UTC</h5>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-4 placeholder col-sm-6">
<img src="{w_speed_icon}" width="50" class="img-fluid" alt="Wind Speed"> <img src="{_w_speed_icon}" width="50" class="img-fluid" alt="Wind Speed">
<h4>{w_speed_km} [km/h]</h4> <h4><span id="w_speed_km">{_w_speed_km}</span> [km/h]</h4>
<div class="text-muted">{w_speed_ms} [m/s]</div> <div class="text-muted">
<span id="w_speed_ms">{_w_speed_ms}</span> [m/s]
</div>
</div> </div>
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-4 placeholder col-sm-6">
<img src="{w_gust_icon}" width="50" class="img-fluid" alt="Wind Gusts"> <img src="{_w_gust_icon}" width="50" class="img-fluid" alt="Wind Gusts">
<h4>{w_gust_km} [km/h]</h4> <h4><span id="w_gust_km">{_w_gust_km} [km/h]</h4>
<div class="text-muted">{w_gust_ms} [m/s]</div> <div class="text-muted">
<span id="w_gust_ms">{_w_gust_ms}</span> [m/s]
</div>
</div> </div>
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-4 placeholder col-sm-6">
<img src="{w_dir_icon}" width="50" class="img-fluid" alt="Wind Direction"> <img src="{_w_dir_icon}" width="50" class="img-fluid" alt="Wind Direction">
<h4>{w_dir_name}</h4> <h4><span id="w_dir_name">{_w_dir_name}</h4>
<div class="text-muted">{w_dir_deg} &deg;</div> <div class="text-muted"><span id="w_dir">{_w_dir_deg}</span> &deg;</div>
</div> </div>
</section> </section>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-3 placeholder col-sm-6">
<img src="{out_temp_icon}" width="50" class="img-fluid" alt="Outside Temperature"> <img src="{_out_temp_icon}" width="30" class="img-fluid" alt="Outside Temperature">
<h4>{out_temp} &deg;C</h4> <h4><span id="out_temp">{_out_temp}</span> &deg;C</h4>
<div class="text-muted">[Outside]</div> <div class="text-muted">[Outside]</div>
</div> </div>
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-3 placeholder col-sm-6">
<img src="{in_temp_icon}" width="50" class="img-fluid" alt="Inside Temperature"> <img src="{_in_temp_icon}" width="30" class="img-fluid" alt="Inside Temperature">
<h4>{in_temp} &deg;C</h4> <h4><span id="in_temp">{_in_temp}</span> &deg;C</h4>
<div class="text-muted">[Inside]</div> <div class="text-muted">[Inside]</div>
</div> </div>
<div class="col-md-4 placeholder col-sm-6"> <div class="col-md-3 placeholder col-sm-6">
<img src="{pressure_icon}" width="50" class="img-fluid" alt="Atmospheric pressure"> <img src="{_pressure_icon}" width="30" class="img-fluid" alt="Atmospheric pressure">
<h4>{pressure} [hPa]</h4> <h4><span id="current_pressure">{_pressure}</span> [hPa]</h4>
<div class="text-muted">{raw_pressure} [hPa] raw</div> <div class="text-muted">{_raw_pressure} [hPa] raw</div>
</div>
<div class="col-md-3 placeholder col-sm-6">
<img src="{_rrate_icon}" width="30" class="img-fluid" alt="Rain rate">
<h4><span id="current_rrate">{_rrate}</span></h4>
<div class="text-muted">[mm/h]</div>
</div> </div>
</section> </section>
@@ -56,6 +66,7 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','wind_monitor')">6Mo</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','wind_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','wind_monitor')">Year</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','wind_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('wind_monitor')">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth('wind_monitor')">&gt;&gt;</button>
<h6><span id="g_tstamp_wind_monitor">{_timestamp}</span> UTC</h6>
</div></div> </div></div>
</div> </div>
</section> </section>
@@ -74,6 +85,7 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','temphumi_monitor')">6Mo</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','temphumi_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','temphumi_monitor')">Year</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','temphumi_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor')">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor')">&gt;&gt;</button>
<h6><span id="g_tstamp_temphumi_monitor">{_timestamp}</span> UTC</h6>
</div> </div>
</section> </section>
<section class="row text-center placeholders"> <section class="row text-center placeholders">
@@ -88,6 +100,22 @@
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','pressure_monitor')">6Mo</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','pressure_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','pressure_monitor')">Year</button> <button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','pressure_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('pressure_monitor')">&gt;&gt;</button> <button type="button" class="btn btn-secondary" onclick="setForth('pressure_monitor')">&gt;&gt;</button>
<h6><span id="g_tstamp_pressure_monitor">{_timestamp}</span> UTC</h6>
</div>
</section>
<section class="row text-center placeholders">
<div class="col">
<div id="rrate_labels"></div>
<div id="rrate" class="container-fluid" style="width:100%;height:200px;"></div>
<button type="button" class="btn btn-secondary" onclick="setBack('rrate_monitor')">&lt;&lt;</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('12','rrate_monitor')">12h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24','rrate_monitor')">24h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168','rrate_monitor')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('720','rrate_monitor')">Month</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('4320','rrate_monitor')">6Mo</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('8640','rrate_monitor')">Year</button>
<button type="button" class="btn btn-secondary" onclick="setForth('rrate_monitor')">&gt;&gt;</button>
<h6><span id="g_tstamp_rrate_monitor">{_timestamp}</span> UTC</h6>
</div> </div>
<script type="text/javascript" src="../static/js/weather_graph.js"></script> <script type="text/javascript" src="../static/js/weather_graph.js"></script>
</section> </section>

View File

@@ -1,280 +0,0 @@
<div class="container-fluid">
<div class="row">
<!--
--------------------------- Nahodou menu na levo -----------------------
--
<nav class="col-sm-3 col-md-2 hidden-xs-down bg-faded sidebar">
<ul class="nav nav-pills flex-column">
<li class="nav-item">
<a class="nav-link active" href="#">Overview <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Reports</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Analytics</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Export</a>
</li>
</ul>
<ul class="nav nav-pills flex-column">
<li class="nav-item">
<a class="nav-link" href="#">Nav item</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Nav item again</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">One more nav</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Another nav item</a>
</li>
</ul>
<ul class="nav nav-pills flex-column">
<li class="nav-item">
<a class="nav-link" href="#">Nav item again</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">One more nav</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Another nav item</a>
</li>
</ul>
</nav>
-->
<div class="col"></div>
<main class="pt-4 col-10">
<h1>Weather Dashboard</h1>
<h5>{timestamp}</h5>
<section class="row text-center placeholders">
<div class="col-md-4 placeholder col-sm-6">
<img src="{w_speed_icon}" width="50" class="img-fluid" alt="Wind Speed">
<h4>{w_speed_km} [km/h]</h4>
<div class="text-muted">{w_speed_ms} [m/s]</div>
</div>
<div class="col-md-4 placeholder col-sm-6">
<img src="{w_gust_icon}" width="50" class="img-fluid" alt="Wind Gusts">
<h4>{w_gust_km} [km/h]</h4>
<div class="text-muted">{w_gust_ms} [m/s]</div>
</div>
<div class="col-md-4 placeholder col-sm-6">
<img src="{w_dir_icon}" width="50" class="img-fluid" alt="Wind Direction">
<h4>{w_dir_name}</h4>
<div class="text-muted">{w_dir_deg} &deg;</div>
</section>
<section class="row text-center placeholders">
<div class="col-md-4 placeholder col-sm-6">
<img src="{out_temp_icon}" width="50" class="img-fluid" alt="Outside Temperature">
<h4>{out_temp} &deg;C</h4>
<div class="text-muted">[Outside]</div>
</div>
<div class="col-md-4 placeholder col-sm-6">
<img src="{in_temp_icon}" width="50" class="img-fluid" alt="Inside Temperature">
<h4>{in_temp} &deg;C</h4>
<div class="text-muted">[Inside]</div>
</div>
<div class="col-md-4 placeholder col-sm-6">
<img src="{pressure_icon}" width="50" class="img-fluid" alt="Atmospheric pressure">
<h4>{pressure} [hPa] Adjusted</h4>
<div class="text-muted">{raw_pressure} [hPa] Actual</div>
</section>
<section class="row text-center placeholders">
<div class="col">
<h2>Wind speed and direction</h2>
<div id="wind_labels"></div>
<div id="wind" class="container-fluid" style="width:100%;height:200px;"></div>
<div class="row"><div class="col py-5">
<button type="button" class="btn btn-secondary" onclick="setBack('wind_monitor')">&lt;&lt;</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('1','wind_monitor')">1h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('6','wind_monitor')">6h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('12','wind_monitor')">12h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24','wind_monitor')">24h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168','wind_monitor')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('5040','wind_monitor')">Month</button>
<button type="button" class="btn btn-secondary" onclick="setForth('wind_monitor')">&gt;&gt;</button>
</div></div>
</div>
</section>
<section class="row text-center placeholders">
<div class="col">
<h2>Temperature and Humidity</h2>
<div id="temphumi_labels"></div><div id="temphumi_labels_in"></div>
<div id="temphumi" class="container-fluid" style="width:100%;height:200px;"></div>
<div id="temphumi_in" class="container-fluid" style="width:100%;height:200px;"></div>
<button type="button" class="btn btn-secondary" onclick="setBack('temphumi_monitor')">&lt;&lt;</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('1','temphumi_monitor')">1h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('6','temphumi_monitor')">6h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('12','temphumi_monitor')">12h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('24','temphumi_monitor')">24h</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('168','temphumi_monitor')">Week</button>
<button type="button" class="btn btn-secondary btn-sm" onclick="setHours('5040','temphumi_monitor')">Month</button>
<<<<<<< HEAD
<button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor');">&gt;&gt;</button>
=======
<button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor')">&gt;&gt;</button>
>>>>>>> ca62f04757f1010262e5559bbd8753bfa49bf34e
</div>
</section>
<section class="row text-center placeholders">
<div class="col">
<div id="pressure_labels"></div>
<div id="pressure" class="container-fluid" style="width:100%;"></div>
</div>
<script type="text/javascript" src="../static/js/weather_graph.js"></script>
</section>
</main>
<div class="col" id="xxx"></div>
<!--
<h2>Section title</h2>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
<th>Header</th>
</tr>
</thead>
<tbody>
<tr>
<td>1,001</td>
<td>Lorem</td>
<td>ipsum</td>
<td>dolor</td>
<td>sit</td>
</tr>
<tr>
<td>1,002</td>
<td>amet</td>
<td>consectetur</td>
<td>adipiscing</td>
<td>elit</td>
</tr>
<tr>
<td>1,003</td>
<td>Integer</td>
<td>nec</td>
<td>odio</td>
<td>Praesent</td>
</tr>
<tr>
<td>1,003</td>
<td>libero</td>
<td>Sed</td>
<td>cursus</td>
<td>ante</td>
</tr>
<tr>
<td>1,004</td>
<td>dapibus</td>
<td>diam</td>
<td>Sed</td>
<td>nisi</td>
</tr>
<tr>
<td>1,005</td>
<td>Nulla</td>
<td>quis</td>
<td>sem</td>
<td>at</td>
</tr>
<tr>
<td>1,006</td>
<td>nibh</td>
<td>elementum</td>
<td>imperdiet</td>
<td>Duis</td>
</tr>
<tr>
<td>1,007</td>
<td>sagittis</td>
<td>ipsum</td>
<td>Praesent</td>
<td>mauris</td>
</tr>
<tr>
<td>1,008</td>
<td>Fusce</td>
<td>nec</td>
<td>tellus</td>
<td>sed</td>
</tr>
<tr>
<td>1,009</td>
<td>augue</td>
<td>semper</td>
<td>porta</td>
<td>Mauris</td>
</tr>
<tr>
<td>1,010</td>
<td>massa</td>
<td>Vestibulum</td>
<td>lacinia</td>
<td>arcu</td>
</tr>
<tr>
<td>1,011</td>
<td>eget</td>
<td>nulla</td>
<td>Class</td>
<td>aptent</td>
</tr>
<tr>
<td>1,012</td>
<td>taciti</td>
<td>sociosqu</td>
<td>ad</td>
<td>litora</td>
</tr>
<tr>
<td>1,013</td>
<td>torquent</td>
<td>per</td>
<td>conubia</td>
<td>nostra</td>
</tr>
<tr>
<td>1,014</td>
<td>per</td>
<td>inceptos</td>
<td>himenaeos</td>
<td>Curabitur</td>
</tr>
<tr>
<td>1,015</td>
<td>sodales</td>
<td>ligula</td>
<td>in</td>
<td>libero</td>
</tr>
</tbody>
</table>
</div>
-->
</div>
</div>
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="../static/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="../static/js/ie10bugfix.js"></script>