New, updated version of web. Might contain customizations
This commit is contained in:
@@ -1,59 +1,65 @@
|
||||
#!/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 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
|
||||
# sys.path.append(_SCRIPT_PATH)
|
||||
def main_server_loop():
|
||||
''' 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
|
||||
are called and mounted to their respective paths
|
||||
|
||||
Args:
|
||||
*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': '0.0.0.0',
|
||||
'server.socket_port': 80
|
||||
'server.socket_host': config.Conf.val['_server_bind_ip'],
|
||||
'server.socket_port': config.Conf.val['_server_port']
|
||||
}
|
||||
# commit the config settings
|
||||
cherrypy.config.update(server_config)
|
||||
|
||||
# If launched directly, let's go
|
||||
if __name__ == '__main__':
|
||||
conf = {
|
||||
'/': {
|
||||
'tools.sessions.on': True,
|
||||
'tools.staticdir.root': os.path.abspath(_SCRIPT_PATH + '/')
|
||||
'tools.staticdir.root': os.path.abspath(config.SCRIPT_PATH + '/')
|
||||
},
|
||||
'/static': {
|
||||
'tools.staticdir.on': True,
|
||||
'tools.staticdir.dir': os.path.abspath(_SCRIPT_PATH + '/static')
|
||||
},
|
||||
'/data': {
|
||||
'tools.staticdir.on': False,
|
||||
'tools.staticdir.dir': os.path.abspath(_SCRIPT_PATH + '/dynamic')
|
||||
'tools.staticdir.dir': './static'
|
||||
}
|
||||
}
|
||||
|
||||
# Here are the different served mounts
|
||||
cherrypy.tree.mount(weather.WeatherInfo(), "/", conf)
|
||||
cherrypy.tree.mount(voltage.EnergyInfo(), "/", 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(dynamic.DynamicData(), "/data", conf)
|
||||
|
||||
# Run the server, lock it in place.
|
||||
cherrypy.tree.mount(dynamic.Expose(), "/data", conf)
|
||||
cherrypy.tree.mount(temphumi.PuerhInfo(), "/temphumi", conf)
|
||||
cherrypy.engine.start()
|
||||
cherrypy.engine.block()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
main_server_loop()
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
@@ -10,35 +10,83 @@ var process = module.exports = {};
|
||||
var cachedSetTimeout;
|
||||
var cachedClearTimeout;
|
||||
|
||||
function defaultSetTimout() {
|
||||
throw new Error('setTimeout has not been defined');
|
||||
}
|
||||
function defaultClearTimeout () {
|
||||
throw new Error('clearTimeout has not been defined');
|
||||
}
|
||||
(function () {
|
||||
try {
|
||||
if (typeof setTimeout === 'function') {
|
||||
cachedSetTimeout = setTimeout;
|
||||
} catch (e) {
|
||||
cachedSetTimeout = function () {
|
||||
throw new Error('setTimeout is not defined');
|
||||
} else {
|
||||
cachedSetTimeout = defaultSetTimout;
|
||||
}
|
||||
} catch (e) {
|
||||
cachedSetTimeout = defaultSetTimout;
|
||||
}
|
||||
try {
|
||||
if (typeof clearTimeout === 'function') {
|
||||
cachedClearTimeout = clearTimeout;
|
||||
} catch (e) {
|
||||
cachedClearTimeout = function () {
|
||||
throw new Error('clearTimeout is not defined');
|
||||
} else {
|
||||
cachedClearTimeout = defaultClearTimeout;
|
||||
}
|
||||
} catch (e) {
|
||||
cachedClearTimeout = defaultClearTimeout;
|
||||
}
|
||||
} ())
|
||||
function runTimeout(fun) {
|
||||
if (cachedSetTimeout === setTimeout) {
|
||||
//normal enviroments in sane situations
|
||||
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) {
|
||||
if (cachedClearTimeout === clearTimeout) {
|
||||
clearTimeout(marker);
|
||||
} else {
|
||||
cachedClearTimeout.call(null, marker);
|
||||
//normal enviroments in sane situations
|
||||
return clearTimeout(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 draining = false;
|
||||
@@ -121,6 +169,10 @@ process.off = noop;
|
||||
process.removeListener = noop;
|
||||
process.removeAllListeners = noop;
|
||||
process.emit = noop;
|
||||
process.prependListener = noop;
|
||||
process.prependOnceListener = noop;
|
||||
|
||||
process.listeners = function (name) { return [] }
|
||||
|
||||
process.binding = function (name) {
|
||||
throw new Error('process.binding is not supported');
|
||||
@@ -2789,7 +2841,8 @@ DygraphInteraction.defaultModel = {
|
||||
// Give plugins a chance to grab this event.
|
||||
var e = {
|
||||
canvasx: context.dragEndX,
|
||||
canvasy: context.dragEndY
|
||||
canvasy: context.dragEndY,
|
||||
cancelable: true
|
||||
};
|
||||
if (g.cascadeEvents_('dblclick', e)) {
|
||||
return;
|
||||
@@ -3447,6 +3500,12 @@ if (typeof process !== 'undefined') {
|
||||
"type": "integer",
|
||||
"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": {
|
||||
"default": "...",
|
||||
"labels": ["Interactive Elements"],
|
||||
@@ -3716,7 +3775,7 @@ if (typeof process !== 'undefined') {
|
||||
"default": "null",
|
||||
"labels": ["Axis display", "Interactive Elements"],
|
||||
"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": {
|
||||
"labels": ["Chart labels"],
|
||||
@@ -4646,29 +4705,36 @@ var dateTicker = function dateTicker(a, b, pixels, opts, dygraph, vals) {
|
||||
exports.dateTicker = dateTicker;
|
||||
// Time granularity enumeration
|
||||
var Granularity = {
|
||||
SECONDLY: 0,
|
||||
TWO_SECONDLY: 1,
|
||||
FIVE_SECONDLY: 2,
|
||||
TEN_SECONDLY: 3,
|
||||
THIRTY_SECONDLY: 4,
|
||||
MINUTELY: 5,
|
||||
TWO_MINUTELY: 6,
|
||||
FIVE_MINUTELY: 7,
|
||||
TEN_MINUTELY: 8,
|
||||
THIRTY_MINUTELY: 9,
|
||||
HOURLY: 10,
|
||||
TWO_HOURLY: 11,
|
||||
SIX_HOURLY: 12,
|
||||
DAILY: 13,
|
||||
TWO_DAILY: 14,
|
||||
WEEKLY: 15,
|
||||
MONTHLY: 16,
|
||||
QUARTERLY: 17,
|
||||
BIANNUAL: 18,
|
||||
ANNUAL: 19,
|
||||
DECADAL: 20,
|
||||
CENTENNIAL: 21,
|
||||
NUM_GRANULARITIES: 22
|
||||
MILLISECONDLY: 0,
|
||||
TWO_MILLISECONDLY: 1,
|
||||
FIVE_MILLISECONDLY: 2,
|
||||
TEN_MILLISECONDLY: 3,
|
||||
FIFTY_MILLISECONDLY: 4,
|
||||
HUNDRED_MILLISECONDLY: 5,
|
||||
FIVE_HUNDRED_MILLISECONDLY: 6,
|
||||
SECONDLY: 7,
|
||||
TWO_SECONDLY: 8,
|
||||
FIVE_SECONDLY: 9,
|
||||
TEN_SECONDLY: 10,
|
||||
THIRTY_SECONDLY: 11,
|
||||
MINUTELY: 12,
|
||||
TWO_MINUTELY: 13,
|
||||
FIVE_MINUTELY: 14,
|
||||
TEN_MINUTELY: 15,
|
||||
THIRTY_MINUTELY: 16,
|
||||
HOURLY: 17,
|
||||
TWO_HOURLY: 18,
|
||||
SIX_HOURLY: 19,
|
||||
DAILY: 20,
|
||||
TWO_DAILY: 21,
|
||||
WEEKLY: 22,
|
||||
MONTHLY: 23,
|
||||
QUARTERLY: 24,
|
||||
BIANNUAL: 25,
|
||||
ANNUAL: 26,
|
||||
DECADAL: 27,
|
||||
CENTENNIAL: 28,
|
||||
NUM_GRANULARITIES: 29
|
||||
};
|
||||
|
||||
exports.Granularity = Granularity;
|
||||
@@ -4699,6 +4765,13 @@ var DateField = {
|
||||
* @type {Array.<{datefield:number, step:number, spacing:number}>}
|
||||
*/
|
||||
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.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 };
|
||||
@@ -4963,7 +5036,7 @@ var logRangeFraction = function logRangeFraction(r0, r1, pct) {
|
||||
// Original calcuation:
|
||||
// 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])
|
||||
//
|
||||
// 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
|
||||
* the length of the generated string. The advantage of this format is that
|
||||
* 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.
|
||||
* @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:
|
||||
* "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS"
|
||||
* @private
|
||||
@@ -6293,6 +6366,12 @@ function dateAxisLabelFormatter(date, granularity, opts) {
|
||||
if (frac === 0 || granularity >= DygraphTickers.Granularity.DAILY) {
|
||||
// e.g. '21 Jan' (%d%b)
|
||||
return zeropad(day) + ' ' + 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 {
|
||||
return hmsString_(hours, mins, secs, millis);
|
||||
}
|
||||
@@ -6372,7 +6451,7 @@ function dateValueFormatter(d, opts) {
|
||||
* @param {Object} attrs Various other attributes, e.g. errorBars determines
|
||||
* whether the input data contains error ranges. For a complete list of
|
||||
* 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.ANIMATION_STEPS = 12;Dygraph.ANIMATION_DURATION = 200; /**
|
||||
* 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.
|
||||
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.
|
||||
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
|
||||
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
|
||||
if(hiddenScale !== 1){this.hidden_ctx_.scale(hiddenScale,hiddenScale);}}; /**
|
||||
* 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.
|
||||
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.
|
||||
// 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());}});}; /**
|
||||
* Combined animation logic for all zoom functions.
|
||||
* 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
|
||||
// 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.
|
||||
// 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);}}}}; /**
|
||||
* Make a copy of input attributes, removing file as a convenience.
|
||||
* @private
|
||||
@@ -8748,8 +8828,8 @@ rangeSelector.prototype.updateVisibility_ = function () {
|
||||
* Resizes the range selector.
|
||||
*/
|
||||
rangeSelector.prototype.resize_ = function () {
|
||||
function setElementRect(canvas, context, rect) {
|
||||
var canvasScale = utils.getContextPixelRatio(context);
|
||||
function setElementRect(canvas, context, rect, pixelRatioOption) {
|
||||
var canvasScale = pixelRatioOption || utils.getContextPixelRatio(context);
|
||||
|
||||
canvas.style.top = rect.y + 'px';
|
||||
canvas.style.left = rect.x + 'px';
|
||||
@@ -8776,8 +8856,9 @@ rangeSelector.prototype.resize_ = function () {
|
||||
h: this.getOption_('rangeSelectorHeight')
|
||||
};
|
||||
|
||||
setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_);
|
||||
setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_);
|
||||
var pixelRatioOption = this.dygraph_.getNumericOption('pixelRatio');
|
||||
setElementRect(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_, pixelRatioOption);
|
||||
setElementRect(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_, pixelRatioOption);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
var hours = 24;
|
||||
var granularity = '2m';
|
||||
var granularity = '5m';
|
||||
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(
|
||||
// containing div
|
||||
document.getElementById("solar"),
|
||||
// CSV or path to a CSV file.
|
||||
graphdata
|
||||
,{
|
||||
//labels: ['time','V_solar','Isolar', P_solar, P_cons],
|
||||
axes : {
|
||||
x : {
|
||||
drawGrid: true,
|
||||
@@ -16,80 +14,82 @@ graphdata
|
||||
},
|
||||
y : {
|
||||
drawGrid: false,
|
||||
drawAxis : true
|
||||
drawAxis: true,
|
||||
valueRange: [44.5,55]
|
||||
},
|
||||
y2 : {
|
||||
drawGrid: false,
|
||||
drawAxis: true,
|
||||
independentTicks: true
|
||||
independentTicks: true,
|
||||
customBars: true,
|
||||
valueRange: [0,1300]
|
||||
}
|
||||
},
|
||||
rollPeriod: 5,
|
||||
visibility: [true, false, true, true],
|
||||
rollPeriod: 3,
|
||||
interactionModel: {},
|
||||
connectSeparatedPoints: true,
|
||||
series:{
|
||||
'V_solar': {
|
||||
axis: 'y',
|
||||
color: '#ffd020',
|
||||
fillGraph: true,
|
||||
fillAlpha: 0.4
|
||||
},
|
||||
'I_solar': {
|
||||
axis: 'y',
|
||||
color: '#ff1100'
|
||||
},
|
||||
'P_solar': {
|
||||
axis: 'y2',
|
||||
color: '#1111ff',
|
||||
fillGraph: true,
|
||||
fillAlpha: 0.4
|
||||
color: '#ff5500'
|
||||
},
|
||||
'P_cons': {
|
||||
axis: 'y2',
|
||||
color: '#ff1111',
|
||||
fillGraph: true,
|
||||
fillAlpha: 0.4
|
||||
'V_array': {
|
||||
axis: 'y',
|
||||
color: '#666'
|
||||
}
|
||||
|
||||
},
|
||||
ylabel: '<span style="color:#ffd020;">[V]</span>/<span style="color:#ff1100;">[A]</span>',
|
||||
y2label: '<span style="color:#111177;">Solar / Consumption [W]</span>',
|
||||
ylabel: '<span style="color:#666;">Battery [V]</span>',
|
||||
y2label: '<span style="color:#ff2200;">Power [W]</span>',
|
||||
labelsDiv: 'solar_labels',
|
||||
legend: 'always'
|
||||
legend: 'always',
|
||||
customBars: true
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
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});
|
||||
//power.updateOptions({'file': graphdata});
|
||||
}
|
||||
|
||||
function setHours(hours_to_set){
|
||||
hours = hours_to_set;
|
||||
switch(hours){
|
||||
case '1':
|
||||
granularity = '30s';
|
||||
granularity = '10s';
|
||||
retention = 'monthly';
|
||||
break;
|
||||
case '6':
|
||||
granularity = '1m';
|
||||
granularity = '10s';
|
||||
retention = 'monthly';
|
||||
break;
|
||||
case '12':
|
||||
granularity = '1m';
|
||||
granularity = '2m';
|
||||
retention = 'monthly';
|
||||
break;
|
||||
case '24':
|
||||
granularity = '2m';
|
||||
granularity = '5m';
|
||||
retention = 'monthly';
|
||||
break;
|
||||
case '168':
|
||||
granularity = '20m';
|
||||
granularity = '15m';
|
||||
retention = 'monthly';
|
||||
break;
|
||||
case '720':
|
||||
granularity = '1h';
|
||||
granularity = '3h';
|
||||
retention = 'yearly';
|
||||
break;
|
||||
case '8760':
|
||||
granularity = '6h';
|
||||
retention = 'yearly';
|
||||
break;
|
||||
case '87600':
|
||||
granularity = '24h';
|
||||
retention = 'yearly';
|
||||
break;
|
||||
default:
|
||||
granularity = '10m';
|
||||
granularity = '5m';
|
||||
retention = 'monthly';
|
||||
}
|
||||
end = 0;
|
||||
//document.getElementById('xxx').innerHTML = graphdata;
|
||||
@@ -118,3 +118,49 @@ function setForth(){
|
||||
//document.getElementById('xxx').innerHTML = graphdata;
|
||||
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);
|
||||
|
||||
@@ -1,16 +1,53 @@
|
||||
var hours = 24;
|
||||
var granularity = '1m';
|
||||
var end = 0;
|
||||
var winddata = "https://bastart.spoton.cz/data/wind_monitor?range=24h&granularity=1m&end=0h";
|
||||
var temphumidata = "https://bastart.spoton.cz/data/temphumi_monitor?range=24h&granularity=2m&end=0h";
|
||||
var pressuredata = "https://bastart.spoton.cz/data/pressure_monitor?range=168h&granularity=2m&end=0h";
|
||||
//defaults
|
||||
var default_granularity = '5m'; // needs to be specified as string, changes
|
||||
var default_hours = 24; // int is OK, (h) hardcoded
|
||||
var default_end = 0; // detto
|
||||
var base_url = "https://bastart.spoton.cz/data/";
|
||||
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(
|
||||
// containing div
|
||||
document.getElementById("wind"),
|
||||
// CSV or path to a CSV file.
|
||||
winddata
|
||||
,{
|
||||
//labels: ['time','Speed','Gust', 'Direction'],
|
||||
data['wind_monitor'],
|
||||
{
|
||||
axes : {
|
||||
x : {
|
||||
drawGrid: true,
|
||||
@@ -27,7 +64,7 @@ winddata
|
||||
independentTicks: true
|
||||
}
|
||||
},
|
||||
rollPeriod: 20,
|
||||
rollPeriod: 5,
|
||||
interactionModel: {},
|
||||
connectSeparatedPoints: true,
|
||||
series:{
|
||||
@@ -45,7 +82,6 @@ winddata
|
||||
axis: 'y2',
|
||||
color: '#999999'
|
||||
}
|
||||
|
||||
},
|
||||
ylabel: '<span style="color:#444444;">Speed<span style="color:#444444;"> / <span style="color:#ff5555;">Gusts</span> [km/h]',
|
||||
y2label: '<span style="color:#999999;">Direction [°]</span>',
|
||||
@@ -55,12 +91,9 @@ winddata
|
||||
);
|
||||
|
||||
temphumi_out = new Dygraph(
|
||||
// containing div
|
||||
document.getElementById("temphumi"),
|
||||
// CSV or path to a CSV file.
|
||||
temphumidata
|
||||
,{
|
||||
//labels: [time,T(ins),T(out),Humi(ins),Humi(out)],
|
||||
data['temphumi_monitor'],
|
||||
{
|
||||
axes : {
|
||||
x : {
|
||||
drawGrid: true,
|
||||
@@ -76,7 +109,7 @@ temphumidata
|
||||
independentTicks: true
|
||||
}
|
||||
},
|
||||
rollPeriod: 10,
|
||||
rollPeriod: 5,
|
||||
visibility: [false, true, false, true],
|
||||
interactionModel: {},
|
||||
connectSeparatedPoints: true,
|
||||
@@ -101,7 +134,6 @@ temphumidata
|
||||
axis: 'y2',
|
||||
color: '#222288'
|
||||
}
|
||||
|
||||
},
|
||||
ylabel: '<span style="color:#555555;">Outside [°C]</span>',
|
||||
y2label: '<span style="color:#222288;">Humidity [%]</span>',
|
||||
@@ -111,12 +143,9 @@ temphumidata
|
||||
);
|
||||
|
||||
temphumi_in = new Dygraph(
|
||||
// containing div
|
||||
document.getElementById("temphumi_in"),
|
||||
// CSV or path to a CSV file.
|
||||
temphumidata
|
||||
,{
|
||||
//labels: [time,T(ins),T(out),Humi(ins),Humi(out)],
|
||||
data['temphumi_monitor'],
|
||||
{
|
||||
axes : {
|
||||
x : {
|
||||
drawGrid: true,
|
||||
@@ -134,7 +163,7 @@ temphumidata
|
||||
valueRange: [0,100]
|
||||
}
|
||||
},
|
||||
rollPeriod: 10,
|
||||
rollPeriod: 5,
|
||||
visibility: [true, false, true, false],
|
||||
interactionModel: {},
|
||||
connectSeparatedPoints: true,
|
||||
@@ -159,7 +188,6 @@ temphumidata
|
||||
axis: 'y2',
|
||||
color: '#222288'
|
||||
}
|
||||
|
||||
},
|
||||
ylabel: '<span style="color:#555555;">Inside [°C]</span>',
|
||||
y2label: '<span style="color:#222288;">Humidity [%]</span>',
|
||||
@@ -169,12 +197,9 @@ temphumidata
|
||||
);
|
||||
|
||||
pressure = new Dygraph(
|
||||
// containing div
|
||||
document.getElementById("pressure"),
|
||||
// CSV or path to a CSV file.
|
||||
pressuredata
|
||||
,{
|
||||
//labels: [time,Pressure],
|
||||
data['pressure_monitor'],
|
||||
{
|
||||
axes : {
|
||||
x : {
|
||||
drawGrid: true,
|
||||
@@ -191,7 +216,7 @@ pressuredata
|
||||
valueRange: [970,1055]
|
||||
}
|
||||
},
|
||||
rollPeriod: 10,
|
||||
rollPeriod: 20,
|
||||
interactionModel: {},
|
||||
connectSeparatedPoints: true,
|
||||
visibility: [true, false],
|
||||
@@ -208,7 +233,6 @@ pressuredata
|
||||
fillGraph: true,
|
||||
fillAlpha: 0.5
|
||||
}
|
||||
|
||||
},
|
||||
ylabel: '<span style="color:#555555;">Pressure [hPa]</span>',
|
||||
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){
|
||||
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'){
|
||||
wind.updateOptions({'file': graphdata});
|
||||
wind.updateOptions({'file': graphdata[source]});
|
||||
}
|
||||
if(source == 'temphumi_monitor'){
|
||||
temphumi_out.updateOptions({'file': graphdata});
|
||||
temphumi_in.updateOptions({'file': graphdata});
|
||||
temphumi_out.updateOptions({'file': graphdata[source]});
|
||||
temphumi_in.updateOptions({'file': graphdata[source]});
|
||||
}
|
||||
if(source == 'pressure_monitor'){
|
||||
pressure.updateOptions({'file': graphdata});
|
||||
pressure.updateOptions({'file': graphdata[source]});
|
||||
}
|
||||
//document.getElementById('xxx').innerHTML = source;
|
||||
//power.updateOptions({'file': graphdata});
|
||||
if(source == 'rrate_monitor'){
|
||||
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){
|
||||
hours = hours_to_set;
|
||||
switch(hours){
|
||||
hours[target] = hours_to_set;
|
||||
switch(hours[target]){
|
||||
case '1':
|
||||
granularity = '1m';
|
||||
if(target == 'temphumi_monitor'){ granularity = '2m';}
|
||||
granularity[target] = '30s';
|
||||
if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
|
||||
break;
|
||||
case '6':
|
||||
granularity = '1m';
|
||||
if(target == 'temphumi_monitor'){ granularity = '2m';}
|
||||
granularity[target] = '1m';
|
||||
if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
|
||||
break;
|
||||
case '12':
|
||||
granularity = '1m';
|
||||
if(target == 'temphumi_monitor'){ granularity = '2m';}
|
||||
granularity[target] = '2m';
|
||||
if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
|
||||
break;
|
||||
case '24':
|
||||
granularity = '1m';
|
||||
if(target == 'temphumi_monitor'){ granularity = '2m';}
|
||||
granularity[target] = '5m';
|
||||
if(target == 'temphumi_monitor'){ granularity[target] = '2m';}
|
||||
break;
|
||||
case '168':
|
||||
granularity = '10m';
|
||||
granularity[target] = '10m';
|
||||
break;
|
||||
case '720':
|
||||
granularity = '1h';
|
||||
granularity[target] = '1h';
|
||||
break;
|
||||
case '4320':
|
||||
granularity = '6h';
|
||||
granularity[target] = '12h';
|
||||
break;
|
||||
case '8640':
|
||||
granularity = '1d';
|
||||
granularity[target] = '24h';
|
||||
break;
|
||||
default:
|
||||
granularity = '10m';
|
||||
granularity[target] = default_granularity;
|
||||
}
|
||||
end = 0;
|
||||
//document.getElementById('xxx').innerHTML = target;
|
||||
end[target] = 0;
|
||||
refreshGraph(target);
|
||||
}
|
||||
|
||||
// Functions for buttons to scale / move graphs
|
||||
function setBack(target){
|
||||
// range=1h -> range=2h&end=1h
|
||||
disp_range = hours*1 - end*1;
|
||||
hours = hours*1 + disp_range;
|
||||
end = end*1 + disp_range;
|
||||
//document.getElementById('xxx').innerHTML = graphdata;
|
||||
disp_range = hours[target]*1 - end[target]*1;
|
||||
hours[target] = hours[target]*1 + disp_range;
|
||||
end[target] = end[target]*1 + disp_range;
|
||||
refreshGraph(target);
|
||||
}
|
||||
|
||||
function setForth(target){
|
||||
disp_range = hours*1 - end*1;
|
||||
hours = hours*1 - disp_range;
|
||||
if(hours < disp_range){
|
||||
hours = disp_range;
|
||||
disp_range = hours[target]*1 - end[target]*1;
|
||||
hours[target] = hours[target]*1 - disp_range;
|
||||
if(hours[target] < disp_range){
|
||||
hours[target] = disp_range;
|
||||
}
|
||||
end = end*1 - disp_range;
|
||||
if(end < 0){
|
||||
end = 0;
|
||||
end[target] = end[target]*1 - disp_range;
|
||||
if(end[target] < 0){
|
||||
end[target] = 0;
|
||||
}
|
||||
//document.getElementById('xxx').innerHTML = graphdata;
|
||||
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);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div id="footer">
|
||||
Created in 101 minutes, in VI, while sitting in a train Wien -> Bratislava.
|
||||
Uploeaded over EDGE with a lot of signal-less territory on roaming. Cheers.
|
||||
Measurements utilise Arduino, ESP8266, lot of python, another lot
|
||||
of Micropython, tons of "heart", no cocaine, but shitloads of Tea. Cheers.
|
||||
Done by Ventil.
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -10,14 +10,37 @@
|
||||
<meta name="Keywords" content="automation, python, development, arduino, measurement">
|
||||
<meta name="description" content="RasPi automation hardcore">
|
||||
<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 -->
|
||||
<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 -->
|
||||
<link href="../static/css/dashboard.css" rel="stylesheet">
|
||||
<link href="https://bastart.spoton.cz/static/css/dashboard.css" rel="stylesheet">
|
||||
<!-- Dygraph css and js -->
|
||||
<link href="../static/css/dygraph.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="../static/js/dygraph.js"></script>
|
||||
<link href="https://bastart.spoton.cz/static/css/dygraph.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="https://bastart.spoton.cz/static/js/dygraph.js"></script>
|
||||
<link rel="icon" href="../../favicon.ico">
|
||||
</head>
|
||||
<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
56
web/templates/status_admin.html
Normal file → Executable file
@@ -4,19 +4,35 @@
|
||||
<div class="col"></div>
|
||||
<main class="pt-4 col-10">
|
||||
<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">
|
||||
<div class="col placeholder">
|
||||
<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>
|
||||
<div class="col placeholder">
|
||||
<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>
|
||||
<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 class="row text-center placeholders">
|
||||
<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('8640','solcap_monitor')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('solcap_monitor')">>></button>
|
||||
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
|
||||
</div>
|
||||
</section>
|
||||
<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('8640','cpumem_monitor')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('cpumem_monitor')">>></button>
|
||||
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
|
||||
</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')"><<</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')">>></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')"><<</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')">>></button>
|
||||
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
|
||||
</div>
|
||||
<script type="text/javascript" src="../static/js/status_graph.js"></script>
|
||||
</section>
|
||||
</main>
|
||||
<div class="col"></div>
|
||||
|
||||
@@ -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">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</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">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
@@ -15,6 +15,9 @@
|
||||
<li class="nav-item {status}">
|
||||
<a class="nav-link" href="https://bastart.spoton.cz/status">Status</a>
|
||||
</li>
|
||||
<li class="nav-item {temphumi}">
|
||||
<a class="nav-link" href="https://bastart.spoton.cz/temphumi">Temp / Humidity</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@@ -4,31 +4,26 @@
|
||||
<div class="col"></div>
|
||||
<main class="pt-4 col-10">
|
||||
<h1>Energy Dashboard</h1>
|
||||
|
||||
<h5><span id="timestamp">{timestamp}</span> UTC</h5>
|
||||
<section class="row text-center placeholders">
|
||||
<div class="col placeholder">
|
||||
<img src="{array_voltage_icon}" width="20" class="img-fluid" alt="Battery voltage">
|
||||
<h3>{array_voltage} [V]</h3>
|
||||
<div class="text-muted">{array_percent} [%]</div>
|
||||
<h3><span id="array_voltage">{array_voltage}</span> [V]</h3>
|
||||
<div class="text-muted"><span id="array_percent">{array_percent}</span> [%]</div>
|
||||
</div>
|
||||
<div class="col placeholder">
|
||||
<img src="../static/img/battery_current.png" width="20" class="img-fluid" alt="Battery current">
|
||||
<h3>{charge_current}</h3>
|
||||
<img src="{charge_current_icon}" width="20" class="img-fluid" alt="Battery current">
|
||||
<h3><span id="charge_current">{charge_current}</span></h3>
|
||||
<div class="text-muted">Charging [A]</div>
|
||||
</div>
|
||||
<div class="col placeholder">
|
||||
<img src="../static/img/solar_power.png" width="20" class="img-fluid" alt="Solar array power">
|
||||
<h3>{solar_power}</h3>
|
||||
<img src="{solar_power_icon}" width="40" class="img-fluid" alt="Solar array power">
|
||||
<h3><span id=solar_power>{solar_power}</span></h3>
|
||||
<span class="text-muted"> Solar PV [W]</span>
|
||||
</div>
|
||||
<div class="col placeholder">
|
||||
<img src="../static/img/solar_voltage.png" width="20" class="img-fluid" alt="Solar array voltage">
|
||||
<h3>{voltage_solar}</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>
|
||||
<img src="{solar_power_icon}" width="40" class="img-fluid" alt="Max power / day">
|
||||
<h3><span id=pmax_day>{pmax_day}</span></h3>
|
||||
<div class="text-muted">Pmax / day [W]</div>
|
||||
</div>
|
||||
</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('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('8760')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth()">>></button>
|
||||
<h6><span id="graph_timestamp">{timestamp}</span> UTC</h6>
|
||||
</div>
|
||||
<div id="xxx"></div>
|
||||
</section>
|
||||
|
||||
<div class="table-responisve">
|
||||
<h2>Historical values by day</h2>
|
||||
{history_table}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
{stats_table}
|
||||
{fresh_table}
|
||||
|
||||
</div>
|
||||
</main>
|
||||
<div class="col"></div>
|
||||
|
||||
@@ -4,40 +4,50 @@
|
||||
<div class="col"></div>
|
||||
<main class="pt-4 col-10">
|
||||
<h1>Weather Dashboard</h1>
|
||||
<h5>{timestamp} UTC</h5>
|
||||
<h5><span id="timestamp">{_timestamp}</span> UTC</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>
|
||||
<img src="{_w_speed_icon}" width="50" class="img-fluid" alt="Wind Speed">
|
||||
<h4><span id="w_speed_km">{_w_speed_km}</span> [km/h]</h4>
|
||||
<div class="text-muted">
|
||||
<span id="w_speed_ms">{_w_speed_ms}</span> [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>
|
||||
<img src="{_w_gust_icon}" width="50" class="img-fluid" alt="Wind Gusts">
|
||||
<h4><span id="w_gust_km">{_w_gust_km} [km/h]</h4>
|
||||
<div class="text-muted">
|
||||
<span id="w_gust_ms">{_w_gust_ms}</span> [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} °</div>
|
||||
<img src="{_w_dir_icon}" width="50" class="img-fluid" alt="Wind Direction">
|
||||
<h4><span id="w_dir_name">{_w_dir_name}</h4>
|
||||
<div class="text-muted"><span id="w_dir">{_w_dir_deg}</span> °</div>
|
||||
</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} °C</h4>
|
||||
<div class="col-md-3 placeholder col-sm-6">
|
||||
<img src="{_out_temp_icon}" width="30" class="img-fluid" alt="Outside Temperature">
|
||||
<h4><span id="out_temp">{_out_temp}</span> °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} °C</h4>
|
||||
<div class="col-md-3 placeholder col-sm-6">
|
||||
<img src="{_in_temp_icon}" width="30" class="img-fluid" alt="Inside Temperature">
|
||||
<h4><span id="in_temp">{_in_temp}</span> °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]</h4>
|
||||
<div class="text-muted">{raw_pressure} [hPa] raw</div>
|
||||
<div class="col-md-3 placeholder col-sm-6">
|
||||
<img src="{_pressure_icon}" width="30" class="img-fluid" alt="Atmospheric pressure">
|
||||
<h4><span id="current_pressure">{_pressure}</span> [hPa]</h4>
|
||||
<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>
|
||||
</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('8640','wind_monitor')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('wind_monitor')">>></button>
|
||||
<h6><span id="g_tstamp_wind_monitor">{_timestamp}</span> UTC</h6>
|
||||
</div></div>
|
||||
</div>
|
||||
</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('8640','temphumi_monitor')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor')">>></button>
|
||||
<h6><span id="g_tstamp_temphumi_monitor">{_timestamp}</span> UTC</h6>
|
||||
</div>
|
||||
</section>
|
||||
<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('8640','pressure_monitor')">Year</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('pressure_monitor')">>></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')"><<</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')">>></button>
|
||||
<h6><span id="g_tstamp_rrate_monitor">{_timestamp}</span> UTC</h6>
|
||||
</div>
|
||||
<script type="text/javascript" src="../static/js/weather_graph.js"></script>
|
||||
</section>
|
||||
|
||||
@@ -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} °</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} °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} °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')"><<</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')">>></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')"><<</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');">>></button>
|
||||
=======
|
||||
<button type="button" class="btn btn-secondary" onclick="setForth('temphumi_monitor')">>></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>
|
||||
Reference in New Issue
Block a user