Dashboard: Doppelungen zusammengelegt, Lade- und Renderlast gesenkt
Zusammenlegung
- Die sechs Endpunkte getConsData_/getProdData_{month,year,decade}.php sind
ajax/energyHistory.php?series=&range= gewichen, der gemeinsame Aufbau der
Chart-Daten steht in ajax/chartData.php. Die erzeugte SQL wurde gegen alle
sechs Originale abgeglichen.
- Die 13 Raeume der Home-Ansicht stehen nur noch in restricted/rooms.php.
home.php rendert die SVG-Kacheln daraus, homeMQTT.js bekommt dieselbe
Tabelle als JSON (346 -> 222 bzw. 428 -> 197 Zeilen).
- Gemeinsame JS-Helfer in js/solar/common.js; geteilte Bausteine fuer
Wetterkacheln, Chart-Skripte und das Formular der Ladesteuerung.
- Seitenvorlagen sind jetzt .php und werden eingebunden, statt per
file_get_contents zusammengesetzt zu werden.
Fehlerbehebungen
- ?action=weather fuehrte auf eine leere Seite, es gibt jetzt weather.php.
- homeMQTT.js griff auf ein #meteogram zu, das home.php nie hatte, und brach
damit den readystatechange-Handler ab.
- Die Heizungsseite abonnierte weatherStation/#, zeigte die Werte aber nie an.
Ladelast
- Chart.js, MQTT und Meteogramm werden nur noch auf den Seiten geladen, die
sie brauchen; die Seitentabelle dafuer steht in index.php.
- mqtt.js durch die minifizierte Fassung ersetzt (859 -> 359 KB). MQTT.js
5.14.1, byte-identisch mit dem signierten npm-Tarball.
- Rund 3,1 MB ungenutzte Vendor-Reste und AdminLTE-Demobilder entfernt.
- Solar 1796 -> 1240 KB, Home 1796 -> 873 KB, Historie 1796 -> 843 KB.
Speicher im Browser
- Chart.defaults.devicePixelRatio auf 1.5 gedeckelt. Die Zeichenpuffer der
Diagramme waren mit 20-45 MB der groesste Posten der Seite.
- Das Meteogramm-iframe laedt erst beim Hinscrollen.
Realtime-SVG
- Filterbereiche auf das noetige Mass verkleinert und den wirkungslosen
feOffset-Durchgang entfernt: 60 % weniger gerasterte Filterflaeche bei
pixelgleichem Ergebnis.
- Die Fluss-Animation laeuft ueber transform statt stroke-dashoffset, mit
Punkten statt Strichmuster; sie ruht, wo kein Fluss anliegt.
- Der Wertupdate schreibt nur noch bei echter Aenderung und benutzt
textContent statt innerHTML: 9 statt 86 Elemente pro Update, davon keines
mit Filter. describeArc rundet auf volle Grad.
- waterInfo auf scale(0.90) wie die uebrigen Info-Gruppen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<!-- Chart.js samt Zubehör - nur auf Seiten mit Diagrammen. -->
|
||||
<script src="js/chart.min.js"></script>
|
||||
<script src="js/chartjs-plugin-annotation.min.js"></script>
|
||||
<script src="js/luxon.min.js"></script>
|
||||
<script src="js/hammer.js"></script>
|
||||
<script src="js/chartjs-scale-timestack.min.js"></script>
|
||||
<script src="js/siprefix.min.js"></script>
|
||||
<script>
|
||||
Chart.register('chartjs-plugin-annotation');
|
||||
|
||||
const arraySum = (arr) => {
|
||||
return arr.reduce((total, current) => {
|
||||
return total + parseFloat(current);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function tooltipLabel(context) {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.dataset.yAxisID == "y1") {
|
||||
label += Math.round(context.parsed.y * 10) / 10 + " " + "%";
|
||||
} else {
|
||||
if (context.parsed.y !== null) {
|
||||
ret = scale(Math.round(context.parsed.y), false);
|
||||
label += ret[0] + " " + ret[1] + "W";
|
||||
}
|
||||
}
|
||||
return label;
|
||||
};
|
||||
|
||||
function tooltipFooter(tooltipItems) {
|
||||
let sum = 0;
|
||||
tooltipItems.forEach(function (tooltipItem) {
|
||||
if (tooltipItem.dataset.yAxisID != "y1") {
|
||||
sum += tooltipItem.parsed.y;
|
||||
}
|
||||
});
|
||||
ret = scale(Math.round(sum), false);
|
||||
sum = ret[0] + " " + ret[1] + "W";
|
||||
return 'Sum: ' + sum;
|
||||
}
|
||||
|
||||
// Zeichenpuffer eines Canvas belegt Breite x Hoehe x DPR^2 x 4 Byte - auf
|
||||
// hochaufloesenden Schirmen ist das der groesste Speicherposten der Seite.
|
||||
// Deckel bei 1.5 kostet kaum Schaerfe und spart bei DPR 2 rund 44 %,
|
||||
// bei DPR 3 rund 75 %.
|
||||
Chart.defaults.devicePixelRatio = Math.min(1.5, window.devicePixelRatio || 1);
|
||||
|
||||
Chart.defaults.font.size = 10;
|
||||
Chart.defaults.animations = false;
|
||||
Chart.defaults.animation = false;
|
||||
Chart.defaults.plugins.legend.position = "bottom";
|
||||
Chart.defaults.plugins.legend.labels.pointStyleWidth = 10;
|
||||
Chart.defaults.plugins.legend.labels.usePointStyle = true;
|
||||
Chart.defaults.plugins.legend.labels.pointStyle = "line";
|
||||
Chart.defaults.plugins.tooltip.position = "nearest";
|
||||
Chart.defaults.plugins.tooltip.pointStyle = "circle";
|
||||
Chart.defaults.plugins.tooltip.usePointStyle = true;
|
||||
Chart.defaults.plugins.tooltip.boxWidth = 4;
|
||||
Chart.defaults.plugins.tooltip.callbacks.footer = tooltipFooter;
|
||||
Chart.defaults.plugins.tooltip.callbacks.label = tooltipLabel;
|
||||
</script>
|
||||
@@ -1,174 +0,0 @@
|
||||
<!--begin::Footer-->
|
||||
<footer class="app-footer">
|
||||
<!--begin::To the end-->
|
||||
<div class="float-end d-none d-sm-inline">Free simple code</div>
|
||||
<!--end::To the end-->
|
||||
<!--begin::Copyright-->
|
||||
<strong>
|
||||
No © 2025 by
|
||||
<a href="https://el-wa.org" class="text-decoration-none">m0</a>
|
||||
</strong>
|
||||
All rights don't care.
|
||||
<!--end::Copyright-->
|
||||
</footer>
|
||||
<!--end::Footer-->
|
||||
<div class="modal fade" id="modalEV" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-title">Charger settings:</h4>
|
||||
<div class="card-tools" style="position: absolute; right: 10px;">
|
||||
<button type="button" class="btn btn-tool" data-bs-dismiss="modal">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body p-0 m-0 shadow" id="modal-body">
|
||||
Loading...
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-default" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" id="modalSaveBtn" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvas" data-bs-backdrop="static">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvas-title">Offcanvas with backdrop</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body" id="offcanvas-body">
|
||||
<p>.....</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end::App Wrapper-->
|
||||
<!--begin::Script-->
|
||||
<!--begin::Third Party Plugin(OverlayScrollbars)
|
||||
<script src="js/overlayscrollbars.browser.es6.min.js" crossorigin="anonymous"></script>-->
|
||||
<!--end::Third Party Plugin(OverlayScrollbars)--><!--begin::Required Plugin(popperjs for Bootstrap 5)-->
|
||||
<script src="js/meteogram.js"></script>
|
||||
<script src='js/mqtt.js'></script>
|
||||
<script src="js/popper.min.js" crossorigin="anonymous"></script>
|
||||
<!--end::Required Plugin(popperjs for Bootstrap 5)--><!--begin::Required Plugin(Bootstrap 5)-->
|
||||
<script src="js/bootstrap.min.js" crossorigin="anonymous"></script>
|
||||
<!--end::Required Plugin(Bootstrap 5)--><!--begin::Required Plugin(AdminLTE)-->
|
||||
<script src="js/adminlte.js"></script>
|
||||
<!--end::Required Plugin(AdminLTE)--><!--begin::OverlayScrollbars Configure-->
|
||||
<script src="js/modal-dynamic.min.js"></script>
|
||||
|
||||
|
||||
<!-- OPTIONAL SCRIPTS -->
|
||||
|
||||
<!-- sortablejs
|
||||
<script src="js/Sortable.min.js"></script>
|
||||
-->
|
||||
<!-- sortablejs
|
||||
<script>
|
||||
if (document.querySelector('.connectedSortable')) {
|
||||
new Sortable(document.querySelector('.connectedSortable'), {
|
||||
group: 'shared',
|
||||
handle: '.card-header',
|
||||
});
|
||||
}
|
||||
const cardHeaders = document.querySelectorAll('.connectedSortable .card-header');
|
||||
cardHeaders.forEach((cardHeader) => {
|
||||
cardHeader.style.cursor = 'move';
|
||||
});
|
||||
</script>
|
||||
-->
|
||||
|
||||
<!-- ChartJS -->
|
||||
<script src="js/chart.min.js"></script>
|
||||
<script src="js/chartjs-plugin-annotation.min.js"></script>
|
||||
<script src="js/luxon.min.js"></script>
|
||||
<script src="js/hammer.js"></script>
|
||||
<script src="js/chartjs-scale-timestack.min.js"></script>
|
||||
<script src="js/siprefix.min.js"></script>
|
||||
<script>
|
||||
Chart.register('chartjs-plugin-annotation');
|
||||
const arraySum = (arr) => {
|
||||
return arr.reduce((total, current) => {
|
||||
return total + parseFloat(current);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function tooltipLabel (context) {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.dataset.yAxisID == "y1") {
|
||||
label += Math.round(context.parsed.y * 10) / 10 + " " + "%";
|
||||
} else {
|
||||
if (context.parsed.y !== null) {
|
||||
ret = scale(Math.round(context.parsed.y), false);
|
||||
label += ret[0] + " " + ret[1] + "W";
|
||||
}
|
||||
}
|
||||
return label;
|
||||
};
|
||||
|
||||
function tooltipFooter (tooltipItems){
|
||||
let sum = 0;
|
||||
|
||||
tooltipItems.forEach(function(tooltipItem) {
|
||||
if (tooltipItem.dataset.yAxisID == "y1") {
|
||||
//sum2 += tooltipItem.parsed.y;
|
||||
}else{
|
||||
sum += tooltipItem.parsed.y;
|
||||
}
|
||||
});
|
||||
//sum2 = Math.round(sum * 10) / 10 + " " + "%";
|
||||
ret = scale(Math.round(sum), false);
|
||||
sum = ret[0] + " " + ret[1] + "W";
|
||||
return 'Sum: ' + sum;
|
||||
}
|
||||
|
||||
Chart.defaults.font.size = 10;
|
||||
Chart.defaults.animations = false;
|
||||
Chart.defaults.animation = false;
|
||||
Chart.defaults.plugins.legend.position = "bottom";
|
||||
Chart.defaults.plugins.legend.labels.pointStyleWidth = 10;
|
||||
Chart.defaults.plugins.legend.labels.usePointStyle = true;
|
||||
Chart.defaults.plugins.legend.labels.pointStyle = "line";
|
||||
Chart.defaults.plugins.tooltip.position = "nearest";
|
||||
Chart.defaults.plugins.tooltip.pointStyle = "circle";
|
||||
Chart.defaults.plugins.tooltip.usePointStyle= true;
|
||||
Chart.defaults.plugins.tooltip.boxWidth= 4;
|
||||
Chart.defaults.plugins.tooltip.callbacks.footer = tooltipFooter;
|
||||
Chart.defaults.plugins.tooltip.callbacks.label = tooltipLabel;
|
||||
|
||||
/*
|
||||
tooltip: {
|
||||
position: 'nearest',
|
||||
pointStyle: "circle",
|
||||
boxWidth: 4,
|
||||
usePointStyle: true,
|
||||
callbacks: {
|
||||
label: function (context) {
|
||||
let label = context.dataset.label || '';
|
||||
if (label) {
|
||||
label += ': ';
|
||||
}
|
||||
if (context.dataset.yAxisID == "y1") {
|
||||
label += Math.round(context.parsed.y * 10) / 10 + " " + "%";
|
||||
} else {
|
||||
if (context.parsed.y !== null) {
|
||||
ret = scale(Math.round(context.parsed.y), false);
|
||||
label += ret[0] + " " + ret[1] + "W";
|
||||
}
|
||||
}
|
||||
return label;
|
||||
},
|
||||
},
|
||||
},*/
|
||||
</script>
|
||||
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,74 @@
|
||||
<!--begin::Footer-->
|
||||
<footer class="app-footer">
|
||||
<!--begin::To the end-->
|
||||
<div class="float-end d-none d-sm-inline">Free simple code</div>
|
||||
<!--end::To the end-->
|
||||
<!--begin::Copyright-->
|
||||
<strong>
|
||||
No © 2025 by
|
||||
<a href="https://el-wa.org" class="text-decoration-none">m0</a>
|
||||
</strong>
|
||||
All rights don't care.
|
||||
<!--end::Copyright-->
|
||||
</footer>
|
||||
<!--end::Footer-->
|
||||
<div class="modal fade" id="modalEV" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="modal-title">Charger settings:</h4>
|
||||
<div class="card-tools" style="position: absolute; right: 10px;">
|
||||
<button type="button" class="btn btn-tool" data-bs-dismiss="modal">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body p-0 m-0 shadow" id="modal-body">
|
||||
Loading...
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between">
|
||||
<button type="button" class="btn btn-default" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" id="modalSaveBtn" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas offcanvas-top" tabindex="-1" id="offcanvas" data-bs-backdrop="static">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvas-title">Offcanvas with backdrop</h5>
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body" id="offcanvas-body">
|
||||
<p>.....</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!--end::App Wrapper-->
|
||||
|
||||
<!--begin::Script-->
|
||||
<script src="js/popper.min.js" crossorigin="anonymous"></script>
|
||||
<script src="js/bootstrap.min.js" crossorigin="anonymous"></script>
|
||||
<script src="js/adminlte.min.js"></script>
|
||||
<script src="js/modal-dynamic.min.js"></script>
|
||||
<?php if ($page["mqtt"]): ?>
|
||||
<!-- MQTT.js 5.14.1, dist/mqtt.min.js aus dem npm-Paket (368 KB statt 859 KB unminifiziert) -->
|
||||
<script src="js/mqtt.min.js"></script>
|
||||
<?php endif; ?>
|
||||
<?php if ($page["meteogram"]): ?>
|
||||
<script src="js/meteogram.js"></script>
|
||||
<?php endif; ?>
|
||||
<?php if ($page["charts"]): ?>
|
||||
<?php include __DIR__ . "/charts.html"; ?>
|
||||
<?php endif; ?>
|
||||
<script src="js/solar/common.js?v=<?= filemtime("js/solar/common.js") ?>"></script>
|
||||
<?php foreach ($page["scripts"] as $script): ?>
|
||||
<script src="<?= $script ?>?v=<?= filemtime($script) ?>"></script>
|
||||
<?php endforeach; ?>
|
||||
<!--end::Script-->
|
||||
|
||||
</body>
|
||||
<!--end::Body-->
|
||||
|
||||
</html>
|
||||
+7
-12
@@ -2,10 +2,9 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<!--begin::Head-->
|
||||
<?php
|
||||
if(!isset($_GET["action"]))
|
||||
$_GET["action"] = "solar";
|
||||
if(!isset($_GET["floor"]))
|
||||
<?php
|
||||
// $_GET["action"] ist von index.php bereits auf eine gueltige Seite gesetzt.
|
||||
if (!isset($_GET["floor"]))
|
||||
$_GET["floor"] = "OG";
|
||||
?>
|
||||
<head>
|
||||
@@ -29,24 +28,20 @@ if(!isset($_GET["floor"]))
|
||||
<!--begin::Accessibility Features-->
|
||||
<!-- Skip links will be dynamically added by accessibility.js -->
|
||||
<meta name="supported-color-schemes" content="light dark" />
|
||||
<link rel="preload" href="./css/adminlte.css?v=2" as="style" />
|
||||
<link rel="stylesheet" href="./css/solar.css" as="style" />
|
||||
<link rel="preload" href="./css/adminlte.min.css?v=2" as="style" />
|
||||
<link rel="stylesheet" href="./css/solar.css" />
|
||||
<!--end::Accessibility Features-->
|
||||
|
||||
<!--begin::Fonts-->
|
||||
<link rel="stylesheet" href="assets/fonts/font_poppins.css" media="print" onload="this.media='all'" />
|
||||
<!--end::Fonts-->
|
||||
|
||||
<!--begin::Third Party Plugin(OverlayScrollbars)
|
||||
<link rel="stylesheet" href="css/overlayscrollbars.min.css" />-->
|
||||
<!--end::Third Party Plugin(OverlayScrollbars)-->
|
||||
|
||||
<!--begin::Third Party Plugin(Bootstrap Icons)-->
|
||||
<link rel="stylesheet" href="css/bootstrap-icons.min.css" />
|
||||
<!--end::Third Party Plugin(Bootstrap Icons)-->
|
||||
|
||||
<!--begin::Required Plugin(AdminLTE)-->
|
||||
<link rel="stylesheet" href="./css/adminlte.css?v=2" />
|
||||
<link rel="stylesheet" href="./css/adminlte.min.css?v=2" />
|
||||
<!--end::Required Plugin(AdminLTE)-->
|
||||
|
||||
|
||||
@@ -124,7 +119,7 @@ if(!isset($_GET["floor"]))
|
||||
</a>
|
||||
<ul class="nav nav-treeview ps-4">
|
||||
<li class="nav-item">
|
||||
<a href="?action=solar" class="nav-link<?php if($_GET["action"]=="solar" || $_GET["action"]==""){echo " active";} ?>">
|
||||
<a href="?action=solar" class="nav-link<?php if($_GET["action"]=="solar"){echo " active";} ?>">
|
||||
<i class="nav-icon bi bi-brightness-alt-high"></i>
|
||||
<p>Solar</p>
|
||||
</a>
|
||||
|
||||
@@ -1,163 +1,104 @@
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Heizung</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
|
||||
<div class="col-xxl-3 col-xl-4 col-lg-5 col-md-5 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Heater</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-3 d-flex flex-column">
|
||||
<object data="assets/img/heater.svg"></object>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Heater Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Temperaturen</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="heat-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
<!-- Water Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Wasserverbrauch</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="water-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Temp.</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="temp">--</h3>°C
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Feuchte</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="humidity">--</h3>%rF
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Wind</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDir" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windSpd">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Böen</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDirGust" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windGust">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Druck</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="ambPress">--</h3>hPa
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Heizung</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
|
||||
<div class="col-xxl-3 col-xl-4 col-lg-5 col-md-5 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Heater</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-3 d-flex flex-column">
|
||||
<object data="assets/img/heater.svg"></object>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Heater Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Temperaturen</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="heat-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
<!-- Water Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Wasserverbrauch</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="water-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<?php include __DIR__ . "/weather_cards.html"; ?>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
@@ -1,246 +0,0 @@
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Vergangenheit</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row row-info">
|
||||
<!-- Start col -->
|
||||
<!-- Consumption Graph-->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power consumption</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="consumption-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Production Graph -->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power production</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="production-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.Start col -->
|
||||
</div>
|
||||
<div class="row row-info">
|
||||
<!-- Start col -->
|
||||
<!-- Consumption Graph-->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power consumption</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="consumption-chart-year" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Production Graph -->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power production</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="production-chart-year" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.Start col -->
|
||||
</div>
|
||||
<div class="row row-info">
|
||||
<!-- Start col -->
|
||||
<!-- Consumption Graph-->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power consumption</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="consumption-chart-decade" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Production Graph -->
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power production</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="production-chart-decade" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<!-- /.Start col -->
|
||||
</div>
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Statistik dieses Jahr</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="Stats-Year">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Statistik letztes Jahr</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="Stats-Lastyear">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Statistik vorletztes Jahr</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="Stats-Prelastyear">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
// Die sechs Diagramme unterscheiden sich nur in Zeitraum und Canvas-ID.
|
||||
$periods = [
|
||||
"month" => "Letzter Monat",
|
||||
"year" => "Letzte 13 Monate",
|
||||
"decade" => "Letzte 10 Jahre",
|
||||
];
|
||||
// Die Jahresstatistiken darunter folgen demselben Muster.
|
||||
$statistics = [
|
||||
"Stats-Year" => "Statistik dieses Jahr",
|
||||
"Stats-Lastyear" => "Statistik letztes Jahr",
|
||||
"Stats-Prelastyear" => "Statistik vorletztes Jahr",
|
||||
];
|
||||
?>
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Vergangenheit</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<?php foreach ($periods as $period => $periodTitle): ?>
|
||||
<div class="row row-info">
|
||||
<?php foreach (["consumption" => "Power consumption", "production" => "Power production"] as $kind => $kindTitle): ?>
|
||||
<div class="col-xl-6 col-m-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title"><?= $kindTitle ?> – <?= $periodTitle ?></h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Zoom out">
|
||||
<i class="bi bi-zoom-out"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Zoom in">
|
||||
<i class="bi bi-zoom-in"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="<?= $kind ?>-chart<?= $period == "month" ? "" : "-" . $period ?>" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php foreach ($statistics as $id => $title): ?>
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title"><?= $title ?></h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="<?= $id ?>">
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
+24
-149
@@ -1,3 +1,4 @@
|
||||
<?php require_once(__DIR__ . "/rooms.php"); ?>
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
@@ -104,142 +105,22 @@
|
||||
<use href="#floorBtn" stroke="#aa7713" />
|
||||
<text fill="#aa7713" style="font: 3em sans-serif;" transform="translate(63,90)">UG</text>
|
||||
</g>
|
||||
<g id="OG_Info" <?php if($_GET["floor"] != "OG"){echo "display='none'";} ?> >
|
||||
<g transform="translate(180,140)" onclick="openHeaterSettings('OG_Wohnzimmer');" cursor="pointer">
|
||||
<?php foreach ($floors as $floor): ?>
|
||||
<g id="<?= $floor ?>_Info" <?php if ($floor != "OG") echo 'opacity="0" '; ?><?php if($_GET["floor"] != $floor){echo "display='none'";} ?> >
|
||||
<?php foreach (roomsOnFloor($floor) as $room): ?>
|
||||
<g transform="translate(<?= $room["x"] ?>,<?= $room["y"] ?>)" onclick="openHeaterSettings('<?= $floor ?>_<?= $room["mqtt"] ?>');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="OG_wozi_heater" href="#heater" display="none" />
|
||||
<use id="OG_wozi_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;" cursor="pointer">
|
||||
<tspan id="OG_pres_wozi" y="5" x="12" text-anchor="middle" cursor="pointer">---- hPa</tspan>
|
||||
<tspan id="OG_tmp_wozi" x="12" dy="1em" font-size="1.6em" text-anchor="middle" cursor="pointer">--,- °C</tspan>
|
||||
<tspan id="OG_hum_wozi" x="12" dy="1.2em" text-anchor="middle" cursor="pointer">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(130,80)" onclick="openHeaterSettings('OG_KiZi');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="OG_kizi_heater" href="#heater" display="none" />
|
||||
<use id="OG_kizi_buffer" href="#buffer" display="none" />
|
||||
<use id="<?= $floor ?>_<?= $room["id"] ?>_heater" href="#heater" display="none" />
|
||||
<use id="<?= $floor ?>_<?= $room["id"] ?>_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="OG_pres_kizi" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="OG_tmp_kizi" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="OG_hum_kizi" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(235,70)" onclick="openHeaterSettings('OG_Schlafzimmer');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="OG_schlafen_heater" href="#heater" display="none" />
|
||||
<use id="OG_schlafen_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="OG_pres_schlafen" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="OG_tmp_schlafen" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="OG_hum_schlafen" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(260,120)" onclick="openHeaterSettings('OG_Bad');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="OG_bad_heater" href="#heater" display="none" />
|
||||
<use id="OG_bad_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="OG_pres_bad" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="OG_tmp_bad" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="OG_hum_bad" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(265,175)" onclick="openHeaterSettings('OG_Buero');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="OG_buero_heater" href="#heater" display="none" />
|
||||
<use id="OG_buero_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="OG_pres_buero" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="OG_tmp_buero" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="OG_hum_buero" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g id="EG_Info" opacity="0" <?php if($_GET["floor"] != "EG"){echo "display='none'";} ?> >
|
||||
<g transform="translate(185,150)" onclick="openHeaterSettings('EG_Wohnzimmer');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="EG_wozi_heater" href="#heater" display="none" />
|
||||
<use id="EG_wozi_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="EG_pres_wozi" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="EG_tmp_wozi" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="EG_hum_wozi" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(130,90)" onclick="openHeaterSettings('EG_Florian');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="EG_kizi_heater" href="#heater" display="none" />
|
||||
<use id="EG_kizi_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="EG_pres_kizi" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="EG_tmp_kizi" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="EG_hum_kizi" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(235,80)" onclick="openHeaterSettings('EG_Schlafen');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="EG_schlafen_heater" href="#heater" display="none" />
|
||||
<use id="EG_schlafen_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="EG_pres_schlafen" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="EG_tmp_schlafen" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="EG_hum_schlafen" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(253,130)" onclick="openHeaterSettings('EG_Bad');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="EG_bad_heater" href="#heater" display="none" />
|
||||
<use id="EG_bad_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="EG_pres_bad" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="EG_tmp_bad" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="EG_hum_bad" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(258,180)" onclick="openHeaterSettings('EG_Magdalena');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="EG_buero_heater" href="#heater" display="none" />
|
||||
<use id="EG_buero_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="EG_pres_buero" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="EG_tmp_buero" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="EG_hum_buero" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
<g id="UG_Info" opacity="0" <?php if($_GET["floor"] != "UG"){echo "display='none'";} ?> >
|
||||
<g transform="translate(140,140)" onclick="openHeaterSettings('UG_Buero');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="UG_buero_heater" href="#heater" display="none" />
|
||||
<use id="UG_buero_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="UG_pres_buero" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="UG_tmp_buero" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="UG_hum_buero" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(210,80)" onclick="openHeaterSettings('UG_Bad');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="UG_bad_heater" href="#heater" display="none" />
|
||||
<use id="UG_bad_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="UG_pres_bad" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="UG_tmp_bad" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="UG_hum_bad" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<g transform="translate(190,195)" onclick="openHeaterSettings('UG_Kueche');" cursor="pointer">
|
||||
<rect width="24" height="19" rx="5" fill="#0006" />
|
||||
<use id="UG_kueche_heater" href="#heater" display="none" />
|
||||
<use id="UG_kueche_buffer" href="#buffer" display="none" />
|
||||
<text fill="#fff" style="font: 4px sans-serif;">
|
||||
<tspan id="UG_pres_kueche" y="5" x="12" text-anchor="middle" >---- hPa</tspan>
|
||||
<tspan id="UG_tmp_kueche" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="UG_hum_kueche" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
<tspan id="<?= $floor ?>_pres_<?= $room["id"] ?>" y="5" x="12" text-anchor="middle">---- hPa</tspan>
|
||||
<tspan id="<?= $floor ?>_tmp_<?= $room["id"] ?>" x="12" dy="1em" font-size="1.6em" text-anchor="middle">--,- °C</tspan>
|
||||
<tspan id="<?= $floor ?>_hum_<?= $room["id"] ?>" x="12" dy="1.2em" text-anchor="middle">-- %rF</tspan>
|
||||
</text>
|
||||
</g>
|
||||
<?php endforeach; ?>
|
||||
</g>
|
||||
<?php endforeach; ?>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
@@ -327,21 +208,15 @@
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
|
||||
<?php
|
||||
if(isset($_GET["floor"])){
|
||||
echo "<script> document.addEventListener('readystatechange', function () {
|
||||
if (event.target.readyState === 'complete') {";
|
||||
switch($_GET["floor"]){
|
||||
case "EG":
|
||||
echo "switchFloor('EG');";
|
||||
break;
|
||||
case "OG":
|
||||
break;
|
||||
case "UG":
|
||||
echo "switchFloor('UG');";
|
||||
break;
|
||||
}
|
||||
echo "}
|
||||
});</script>";
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
// Raumtabelle aus restricted/rooms.php - homeMQTT.js aktualisiert darueber
|
||||
// die SVG-Kacheln, ohne die Raeume noch einmal aufzufuehren.
|
||||
const homeRooms = <?= json_encode($rooms) ?>;
|
||||
<?php if ($_GET["floor"] != "OG" && in_array($_GET["floor"], $floors)): ?>
|
||||
document.addEventListener('readystatechange', function () {
|
||||
if (event.target.readyState === 'complete') {
|
||||
switchFloor('<?= $_GET["floor"] ?>');
|
||||
}
|
||||
});
|
||||
<?php endif; ?>
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*
|
||||
* Einzige Quelle für die Räume der Home-Ansicht.
|
||||
*
|
||||
* Aus dieser Tabelle entstehen sowohl die SVG-Kacheln in home.php als auch
|
||||
* die Aktualisierungsschleife in js/solar/homeMQTT.js (die Tabelle wird dafür
|
||||
* als JSON in die Seite geschrieben). Ein neuer oder umbenannter Raum ist
|
||||
* damit eine Zeile hier statt drei Stellen im Code.
|
||||
*
|
||||
* floor Etage; bestimmt zugleich den Zweig Raumtemp/<floor>/
|
||||
* mqtt Name des Raums im MQTT-Baum: Raumtemp/<floor>/<mqtt>/...
|
||||
* id Kürzel in den SVG-Element-IDs: <floor>_tmp_<id>, <floor>_<id>_heater
|
||||
* x, y Position der Kachel im SVG (viewBox 400x300)
|
||||
*/
|
||||
|
||||
// Reihenfolge im Menü und in der Anzeige; OG ist die Standardetage.
|
||||
$floors = ["OG", "EG", "UG"];
|
||||
|
||||
$rooms = [
|
||||
["floor" => "OG", "mqtt" => "Wohnzimmer", "id" => "wozi", "x" => 180, "y" => 140],
|
||||
["floor" => "OG", "mqtt" => "KiZi", "id" => "kizi", "x" => 130, "y" => 80],
|
||||
["floor" => "OG", "mqtt" => "Schlafzimmer", "id" => "schlafen", "x" => 235, "y" => 70],
|
||||
["floor" => "OG", "mqtt" => "Bad", "id" => "bad", "x" => 260, "y" => 120],
|
||||
["floor" => "OG", "mqtt" => "Buero", "id" => "buero", "x" => 265, "y" => 175],
|
||||
["floor" => "EG", "mqtt" => "Wohnzimmer", "id" => "wozi", "x" => 185, "y" => 150],
|
||||
["floor" => "EG", "mqtt" => "Florian", "id" => "kizi", "x" => 130, "y" => 90],
|
||||
["floor" => "EG", "mqtt" => "Schlafen", "id" => "schlafen", "x" => 235, "y" => 80],
|
||||
["floor" => "EG", "mqtt" => "Bad", "id" => "bad", "x" => 253, "y" => 130],
|
||||
["floor" => "EG", "mqtt" => "Magdalena", "id" => "buero", "x" => 258, "y" => 180],
|
||||
["floor" => "UG", "mqtt" => "Buero", "id" => "buero", "x" => 140, "y" => 140],
|
||||
["floor" => "UG", "mqtt" => "Bad", "id" => "bad", "x" => 210, "y" => 80],
|
||||
["floor" => "UG", "mqtt" => "Kueche", "id" => "kueche", "x" => 190, "y" => 195],
|
||||
];
|
||||
|
||||
/** Räume einer Etage, in der Reihenfolge der Tabelle. */
|
||||
function roomsOnFloor($floor)
|
||||
{
|
||||
return array_values(array_filter($GLOBALS["rooms"], function ($room) use ($floor) {
|
||||
return $room["floor"] == $floor;
|
||||
}));
|
||||
}
|
||||
@@ -1,250 +1,191 @@
|
||||
<style>
|
||||
.datepicker-native {
|
||||
position: relative;
|
||||
}
|
||||
.datepicker-native-input {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.datepicker-native-input::-webkit-calendar-picker-indicator {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Solar</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
<div class="col-xxl-12 col-xl-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Realtime</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;max-height:800px;">
|
||||
%%INSERTSVG%%
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Statistik dieses Jahr</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="Stats-Year">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Forecast</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pb-1" id="meteogram">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<!-- Forecast Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Forecast</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="forecast-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Consumption Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power consumption</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Voriger Tag" onclick="prevDay()">
|
||||
<i class="bi bi-skip-backward"></i>
|
||||
</button>
|
||||
<button type="button" type="btn btn-tool" class="btn btn-tool datepicker-native">
|
||||
<i class="bi bi-calendar-week"></i>
|
||||
<input type="date" id="DatePickerCons" class="datepicker-native-input" onInput="changeDay(event);" />
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Nächster Tag" onclick="nextDay()">
|
||||
<i class="bi bi-skip-forward"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="consumption-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Production Graph -->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power production</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Voriger Tag" onclick="prevDay()">
|
||||
<i class="bi bi-skip-backward"></i>
|
||||
</button>
|
||||
<button type="button" type="btn btn-tool" class="btn btn-tool datepicker-native">
|
||||
<i class="bi bi-calendar-week"></i>
|
||||
<input type="date" id="DatePickerProd" class="datepicker-native-input" onInput="changeDay(event);" />
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Nächster Tag" onclick="nextDay()">
|
||||
<i class="bi bi-skip-forward"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="production-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.Start col -->
|
||||
</div>
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Temp.</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="temp">--</h3>°C
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Feuchte</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="humidity">--</h3>%rF
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Wind</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDir" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windSpd">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Böen</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDirGust" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windGust">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Druck</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="ambPress">--</h3>hPa
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<style>
|
||||
.datepicker-native {
|
||||
position: relative;
|
||||
}
|
||||
.datepicker-native-input {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.datepicker-native-input::-webkit-calendar-picker-indicator {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Solar</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
<div class="col-xxl-12 col-xl-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Realtime</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body p-0 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;max-height:800px;">
|
||||
<?php readfile(__DIR__ . "/../assets/img/realtime.svg"); ?>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Statistik dieses Jahr</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-cols-1 row-cols-md-1 g-4 p-2 pb-0" id="Stats-Year">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Forecast</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pb-1" id="meteogram">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
|
||||
<!-- Forecast Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Forecast</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="forecast-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Consumption Graph-->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power consumption</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Voriger Tag" onclick="prevDay()">
|
||||
<i class="bi bi-skip-backward"></i>
|
||||
</button>
|
||||
<button type="button" type="btn btn-tool" class="btn btn-tool datepicker-native">
|
||||
<i class="bi bi-calendar-week"></i>
|
||||
<input type="date" id="DatePickerCons" class="datepicker-native-input" onInput="changeDay(event);" />
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Nächster Tag" onclick="nextDay()">
|
||||
<i class="bi bi-skip-forward"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="consumption-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Production Graph -->
|
||||
<div class="col-lg-12">
|
||||
<div class="card mb-4 p-0">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Power production</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" title="Voriger Tag" onclick="prevDay()">
|
||||
<i class="bi bi-skip-backward"></i>
|
||||
</button>
|
||||
<button type="button" type="btn btn-tool" class="btn btn-tool datepicker-native">
|
||||
<i class="bi bi-calendar-week"></i>
|
||||
<input type="date" id="DatePickerProd" class="datepicker-native-input" onInput="changeDay(event);" />
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" title="Nächster Tag" onclick="nextDay()">
|
||||
<i class="bi bi-skip-forward"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body pb-1">
|
||||
<div class="chart-container" style="position: relative; height:100%; width:100%">
|
||||
<canvas id="production-chart" height="400px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
<!-- /.Start col -->
|
||||
</div>
|
||||
<?php include __DIR__ . "/weather_cards.html"; ?>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
@@ -0,0 +1,46 @@
|
||||
<!--begin::App Main-->
|
||||
<main class="app-main">
|
||||
<!--begin::App Content Header-->
|
||||
<div class="app-content-header">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<!--begin::Row-->
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<h3 class="mb-0">Wetter</h3>
|
||||
</div>
|
||||
</div>
|
||||
<!--end::Row-->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content Header-->
|
||||
<!--begin::App Content-->
|
||||
<div class="app-content">
|
||||
<!--begin::Container-->
|
||||
<div class="container-fluid">
|
||||
<?php include __DIR__ . "/weather_cards.html"; ?>
|
||||
<div class="row">
|
||||
<div class="col-xxl-12 col-xl-12 col-lg-12 col-md-12 d-flex align-items-stretch">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Vorhersage</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-tool" data-lte-toggle="card-remove">
|
||||
<i class="bi bi-x-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pb-1" id="meteogram">
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.row (main row) -->
|
||||
</div>
|
||||
<!--end::Container-->
|
||||
</div>
|
||||
<!--end::App Content-->
|
||||
</main>
|
||||
<!--end::App Main-->
|
||||
@@ -0,0 +1,62 @@
|
||||
<!-- Wetterkacheln - eingebunden von solar.php, heat.php und weather.php.
|
||||
Aktualisiert werden sie von updateWeatherCards() aus js/solar/common.js. -->
|
||||
<div class="row">
|
||||
<!-- Start col -->
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Temp.</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="temp">--</h3>°C
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Feuchte</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="humidity">--</h3>%rF
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Wind</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDir" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windSpd">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Böen</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<div id="windDirGust" class="winddir" style="transform: rotate(180deg);"></div>
|
||||
<h3 id="windGust">--</h3>km/h
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-0 col-xl-2 col-4 d-flex">
|
||||
<div class="card p-0 mb-4" style="width:100%">
|
||||
<div class="card-header pb-0 pt-1">
|
||||
<h3 class="card-title">Druck</h3>
|
||||
</div>
|
||||
<div class="card-body p-2 d-flex flex-column" id="realtimeSVGcontainer" style="position:relative;">
|
||||
<h3 id="ambPress">--</h3>hPa
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
Reference in New Issue
Block a user