Das Widget von meteoblue war ein fremdes Dokument im iframe: es passte farblich nicht, liess sich nicht aendern, wurde auf schmalen Schirmen als Ganzes heruntergerechnet und konnte die eigenen Messwerte nicht zeigen. Genau das kann das neue Modul - links vom Jetzt-Strich steht, was die Wetterstation gemessen hat, rechts die Vorhersage. Aufgebaut wie die uebrigen Anzeige-Module: meteogrammKatalog.js sagt, WAS gezeigt wird, meteogramm.js nur, WIE. Der Renderer kennt kein Feld und keine Spur beim Namen. Eine weitere Spur ist damit ein Objekt im Katalog und keine Codeaenderung. Ein einziges SVG ueber alle drei Felder, damit Zeitachse, Nachtstreifen, Jetzt-Linie und Zeiger nur einmal existieren und ueberall gleich sitzen. Zwei Entscheidungen, die man sonst sucht: Das Wolkenband zeichnet je Schicht ein Rechteck mit waagerechtem Farbverlauf. Ein Rechteck je Stunde war der erste Versuch und sah aus wie Fernsehrauschen - zweihundert harte Kanten nebeneinander. Open-Meteo kennt ohnehin nur drei Schichten statt eines Hoehenprofils. Die Strahlung teilt sich das Feld mit der Temperatur, statt ein viertes zu bekommen: gleicher Tagesrhythmus, gleiche Nacht-Schattierung, und ein viertes Feld machte das Ganze am Handy hoeher als das externe Widget. Die alte Einbindung bleibt vorerst und ist umschaltbar. mountMeteogram() laeuft jetzt erst beim Umschalten - wer meteoblue nie ansieht, laedt es auch nicht mehr. Die Karte heisst "Wetter" statt "Forecast": darunter steht bereits eine zweite Karte dieses Namens. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
232 lines
9.6 KiB
PHP
232 lines
9.6 KiB
PHP
<?php require_once(__DIR__ . "/energiefluss.php"); ?>
|
|
<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 -->
|
|
<!-- Energiefluss. Gezeichnet von js/solar/energiefluss.js aus dem Katalog
|
|
(energieflussKatalog.js) und den Einstellungen dieses Hauses
|
|
(Einstellungen -> Übersicht). Bis September 2026 stand hier
|
|
assets/img/realtime.svg mit festen Kreisen. -->
|
|
<div class="col-xxl-12 col-xl-12 d-flex align-items-stretch">
|
|
<div class="card p-0 mb-4" style="width:100%" id="energieflussKarte">
|
|
<div class="card-header pb-1 pt-1 d-flex align-items-center">
|
|
<h3 class="card-title me-auto d-none d-sm-block">Realtime</h3>
|
|
<span class="me-auto d-sm-none"></span>
|
|
<div class="enf-umschalter me-2" role="tablist" aria-label="Ansicht">
|
|
<button type="button" class="btn btn-sm active" role="tab" aria-selected="true" data-enf-ansicht="fluss">Übersicht</button>
|
|
<button type="button" class="btn btn-sm" role="tab" aria-selected="false" data-enf-ansicht="anlage">Anlage</button>
|
|
<button type="button" class="btn btn-sm" role="tab" aria-selected="false" data-enf-ansicht="speicher">Speicher</button>
|
|
</div>
|
|
<div class="card-tools">
|
|
<a class="btn btn-tool" href="index.php?action=settings#energiefluss" title="Übersicht einstellen">
|
|
<i class="bi bi-sliders"></i>
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="card-body p-2 p-md-3">
|
|
<div class="enf-ansicht enf-behaelter" data-enf-ansicht-flaeche="fluss" id="energiefluss"></div>
|
|
<!-- Lageplan der PV-Anlage: js/solar/anlage.js aus anlageKatalog.js -->
|
|
<div class="enf-ansicht" data-enf-ansicht-flaeche="anlage" id="anlage" hidden></div>
|
|
<!-- Batterie bis zur Zelle: js/solar/speicher.js, Verlauf aus ajax/speicher.php -->
|
|
<div class="enf-ansicht" data-enf-ansicht-flaeche="speicher" id="speicher" hidden></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<script>
|
|
// Abweichungen dieses Hauses vom Katalog, siehe restricted/energiefluss.php.
|
|
const energieflussEinstellungen = <?= json_encode((object)energieflussLaden(), JSON_UNESCAPED_UNICODE) ?>;
|
|
</script>
|
|
|
|
<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%">
|
|
<!--
|
|
Wetter. Der Titel hiess frueher "Forecast" wie die Karte
|
|
darunter, die aus simPower die PV-Ernte vorhersagt - zwei
|
|
gleichnamige Karten uebereinander.
|
|
-->
|
|
<div class="card-header pb-1 pt-1 d-flex align-items-center flex-wrap gap-2">
|
|
<h3 class="card-title me-auto">Wetter</h3>
|
|
<!-- Hier haengt das Modul seine Zeitraumknoepfe ein (opt.kopf). -->
|
|
<div class="mtg-kopf"></div>
|
|
<!--
|
|
Eigenes Meteogramm oder das eingebettete von meteoblue.
|
|
data-mtg-quelle und nicht data-enf-ansicht: zeigeAnsicht() in
|
|
solarMQTT.js greift seitenweit zu und wuerde sonst die
|
|
Realtime-Karte mitschalten.
|
|
-->
|
|
<div class="enf-umschalter" role="tablist" aria-label="Quelle">
|
|
<button type="button" class="btn btn-sm active" role="tab" aria-selected="true" data-mtg-quelle="eigen">Eigenes</button>
|
|
<button type="button" class="btn btn-sm" role="tab" aria-selected="false" data-mtg-quelle="blue">meteoblue</button>
|
|
</div>
|
|
<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-2 p-md-3">
|
|
<!-- js/solar/meteogramm.js aus meteogrammKatalog.js, Daten aus ajax/meteogramm.php -->
|
|
<div data-mtg-flaeche="eigen" id="meteogramm"></div>
|
|
<!--
|
|
Ziel des meteoblue-Rahmens. Die id heisst weiterhin
|
|
"meteogram" mit einem m, damit mountMeteogram() in common.js
|
|
unveraendert bleiben kann.
|
|
-->
|
|
<div data-mtg-flaeche="blue" id="meteogram" hidden></div>
|
|
</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">
|
|
<canvas id="forecast-chart"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</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>
|
|
<!-- Gefuellt von baueJahresstatistik() aus js/solar/jahresstatistik.js -
|
|
dieselbe Tabelle wie auf der Historienseite, nur einspaltig. -->
|
|
<div class="card-body statistik" id="Stats-Year"></div>
|
|
</div>
|
|
<!-- /.card -->
|
|
</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">
|
|
<canvas id="consumption-chart"></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">
|
|
<canvas id="production-chart"></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-->
|