Wechselrichter ueber ihren Namen, Symbole auf den Kacheln
Carport EG und Veranda OG zeigen jetzt ihre PV-Leistung. Der SolarManager legt die Hoymiles unter solarManager/inverters0, /inverters1 und so fort ab - die Nummer ist eine Position in einer Liste und sagt nichts darueber, welches Dach gemeint ist. Ein fest eingetragenes "inverters3" waere stillschweigend falsch, sobald sich die Reihenfolge aendert. Deshalb sucht wechselrichterWert() ueber invertersN/name und summiert die genannten auf. Das ist eine dritte Art, an einen Wert zu kommen - neben Topic und JSON-Pfad -, aber sie bleibt auf einen Schluessel und eine Funktion beschraenkt, und der gewoehnliche Weg ist unberuehrt. Findet sie keinen der Namen, schreibt sie die vorhandenen in die Konsole; sonst stuende nur ein Strich auf der Kachel und niemand wuesste, woran es liegt. tileTopics() unterschied bisher nicht und machte aus dem fehlenden Topic ein "/#" - eine Anmeldung auf einen leeren Zweig. Dazu Symbole vor den Zahlen. "0 W" allein sagt nicht, ob geladen, erzeugt oder verbraucht wird, und die Einheit beantwortet das nicht. Die Icons kommen als Schrift und nicht als Pfad: css/bootstrap-icons.min.css ist ohnehin eingebunden, und SVG-Text darf dieselbe Schriftfamilie benutzen wie HTML. Die Codepunkte stehen in kachelIcon() mit dem Namen daneben, abgeschrieben aus genau dieser CSS. Wegen font-display:block bleiben die Symbole bis zum Laden der Schriftdatei unsichtbar - die Werte stehen so lange ohnehin auf einem Strich. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+52
-2
@@ -72,9 +72,59 @@ const homeSVG = {
|
||||
* schneidet Nachkommastellen ab; ohne Angabe bleibt der Text so, wie das
|
||||
* Geraet ihn meldet.
|
||||
*/
|
||||
/**
|
||||
* Die Leistung benannter Wechselrichter, aufsummiert.
|
||||
*
|
||||
* Der SolarManager legt sie unter solarManager/inverters0, /inverters1
|
||||
* und so fort ab - die Nummer ist eine Position in einer Liste und sagt
|
||||
* nichts darueber, welches Dach gemeint ist. Deshalb wird ueber
|
||||
* invertersN/name gesucht: aendert sich die Reihenfolge, findet die
|
||||
* Kachel ihren Wechselrichter trotzdem, statt stillschweigend das
|
||||
* falsche Dach anzuzeigen.
|
||||
*/
|
||||
wechselrichterWert: function (mqttData, wert) {
|
||||
const zweig = mqttData["solarManager"];
|
||||
if (!zweig) return null;
|
||||
|
||||
const gesucht = wert.wechselrichter;
|
||||
const feld = wert.feld || "p_AC";
|
||||
let summe = 0;
|
||||
const gefunden = [];
|
||||
const vorhanden = [];
|
||||
|
||||
for (const schluessel in zweig) {
|
||||
if (!schluessel.startsWith("inverters")) continue;
|
||||
const wr = zweig[schluessel];
|
||||
if (!wr || typeof wr.name === "undefined") continue;
|
||||
const name = String(wr.name);
|
||||
vorhanden.push(name);
|
||||
if (gesucht.indexOf(name) === -1) continue;
|
||||
if (typeof wr[feld] === "undefined") continue;
|
||||
summe += Number(wr[feld]);
|
||||
gefunden.push(name);
|
||||
}
|
||||
|
||||
if (!gefunden.length) {
|
||||
// Ein Name, den es nicht gibt, ergaebe sonst nur einen Strich auf
|
||||
// der Kachel und keinen Hinweis, woran es liegt.
|
||||
if (vorhanden.length && !homeSVG.gemeldet[gesucht.join("|")]) {
|
||||
homeSVG.gemeldet[gesucht.join("|")] = true;
|
||||
console.warn("Kachel: kein Wechselrichter namens " + gesucht.join(", ")
|
||||
+ ". Vorhanden sind: " + vorhanden.join(", "));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return summe;
|
||||
},
|
||||
|
||||
/** Merkt sich gemeldete Namen, damit die Konsole nicht zulaeuft. */
|
||||
gemeldet: {},
|
||||
|
||||
kachelWert: function (mqttData, wert) {
|
||||
const roh = homeSVG.ausTopic(mqttData, wert.topic);
|
||||
if (typeof roh === "undefined") return null;
|
||||
const roh = wert.wechselrichter
|
||||
? homeSVG.wechselrichterWert(mqttData, wert)
|
||||
: homeSVG.ausTopic(mqttData, wert.topic);
|
||||
if (roh === null || typeof roh === "undefined") return null;
|
||||
let text = String(roh);
|
||||
if (wert.pfad) {
|
||||
try {
|
||||
|
||||
+12
-1
@@ -144,10 +144,21 @@
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($room["werte"] as $i => $wert): ?>
|
||||
<?php $zeichen = kachelIcon($wert["icon"] ?? ""); ?>
|
||||
<?php if ($zeichen !== ""): ?>
|
||||
<!-- Ein Symbol vor der Zahl. "0 W" allein sagt nicht,
|
||||
ob geladen, erzeugt oder verbraucht wird; die
|
||||
Einheit beantwortet das nicht. Die Zahl rueckt
|
||||
dafuer nach rechts, damit Symbol und Wert
|
||||
zusammen mittig stehen. -->
|
||||
<tspan x="4" y="<?= $y[$i] ?>" text-anchor="middle" opacity=".8"
|
||||
style="font-family:bootstrap-icons"><?= $zeichen ?></tspan>
|
||||
<?php endif; ?>
|
||||
<!-- Der Platzhalter ist nur ein Strich: bevor der
|
||||
erste Wert da ist, soll hier keine Einheit
|
||||
stehen, die vielleicht gar nicht passt. -->
|
||||
<tspan id="<?= $floor ?>_w<?= $i ?>_<?= $room["id"] ?>" x="12" y="<?= $y[$i] ?>"
|
||||
<tspan id="<?= $floor ?>_w<?= $i ?>_<?= $room["id"] ?>"
|
||||
x="<?= $zeichen !== "" ? 15 : 12 ?>" y="<?= $y[$i] ?>"
|
||||
<?= empty($wert["gross"]) ? "" : 'font-size="1.6em"' ?> text-anchor="middle">–</tspan>
|
||||
<?php endforeach; ?>
|
||||
</text>
|
||||
|
||||
+53
-6
@@ -98,20 +98,38 @@ $rooms = [
|
||||
// Zwei Carports, einer je Wohnpartei - deshalb dieselben Kuerzel wie die
|
||||
// Etagen. Die Wattpilot der EG-Partei steht dagegen in der Garage, siehe
|
||||
// restricted/config.php; am Carport OG haengt der go-e Charger.
|
||||
["floor" => "AG", "mqtt" => "Carport EG", "id" => "carport_eg", "x" => 156, "y" => 214, "werte" => []],
|
||||
// Die PV des Carports haengt an mehreren Hoymiles. Sie werden ueber
|
||||
// ihren Namen gesucht und aufsummiert, nicht ueber ihre Nummer: die
|
||||
// Topics heissen solarManager/invertersN, und N ist eine Position in
|
||||
// einer Liste. Aendert der SolarManager die Reihenfolge, zeigte eine
|
||||
// fest eingetragene Nummer stillschweigend das falsche Dach an.
|
||||
//
|
||||
// Die Namen muessen genau so lauten wie unter invertersN/name. Passt
|
||||
// einer nicht, schreibt homeMQTT.js die vorhandenen Namen in die
|
||||
// Browser-Konsole - dann steht dort, was hier hingehoert.
|
||||
["floor" => "AG", "mqtt" => "Carport EG", "id" => "carport_eg", "x" => 156, "y" => 214,
|
||||
"werte" => [
|
||||
["wechselrichter" => ["Carport 1-6", "Carport 7-12", "Carport 13-16",
|
||||
"Carport 17-19"],
|
||||
"feld" => "p_AC", "einheit" => "W", "stellen" => 0, "icon" => "sun"],
|
||||
]],
|
||||
// Am Carport OG haengt der go-e Charger. Die Ladeleistung ist das
|
||||
// Einzige, was sich hier messen laesst - und sie beantwortet die Frage,
|
||||
// die man sich vor dem Carport stellt: laedt gerade jemand?
|
||||
["floor" => "AG", "mqtt" => "Carport OG", "id" => "carport_og", "x" => 38, "y" => 155,
|
||||
"werte" => [
|
||||
["topic" => "solarManager/evPowerOG", "einheit" => "W", "stellen" => 0,
|
||||
"gross" => true],
|
||||
"icon" => "ev-station"],
|
||||
]],
|
||||
// Veranda und Terrasse gibt es zweimal, je Wohnpartei eine. In der
|
||||
// Draufsicht laege das obere Paar genau auf dem unteren - deshalb die
|
||||
// Schraegsicht, siehe restricted/aussenplan.php.
|
||||
["floor" => "AG", "mqtt" => "Veranda EG", "id" => "veranda_eg", "x" => 156, "y" => 132, "werte" => []],
|
||||
["floor" => "AG", "mqtt" => "Veranda OG", "id" => "veranda_og", "x" => 150, "y" => 92, "werte" => []],
|
||||
["floor" => "AG", "mqtt" => "Veranda OG", "id" => "veranda_og", "x" => 150, "y" => 92,
|
||||
"werte" => [
|
||||
["wechselrichter" => ["Veranda OG2-4", "Veranda UG/OG1"],
|
||||
"feld" => "p_AC", "einheit" => "W", "stellen" => 0, "icon" => "sun"],
|
||||
]],
|
||||
["floor" => "AG", "mqtt" => "Terrasse EG", "id" => "terrasse_eg", "x" => 212, "y" => 160, "werte" => []],
|
||||
["floor" => "AG", "mqtt" => "Terrasse OG", "id" => "terrasse_og", "x" => 205, "y" => 122, "werte" => []],
|
||||
["floor" => "AG", "mqtt" => "Pergola", "id" => "pergola", "x" => 339, "y" => 108, "werte" => []],
|
||||
@@ -120,7 +138,7 @@ $rooms = [
|
||||
["floor" => "AG", "mqtt" => "Garage", "id" => "garage", "x" => 103, "y" => 134,
|
||||
"werte" => [
|
||||
["topic" => "solarManager/evPower", "einheit" => "W", "stellen" => 0,
|
||||
"gross" => true],
|
||||
"icon" => "ev-station"],
|
||||
]],
|
||||
// Der Garten ist kein Bauteil wie die anderen, aber ein Ort: hier haengen
|
||||
// der Regensensor und die beiden Ventilsteuerungen.
|
||||
@@ -131,7 +149,7 @@ $rooms = [
|
||||
// laufende Tag - die Zahl, die man im Garten wissen will. Ein
|
||||
// laengeres Fenster ist ein geaenderter Pfad und sonst nichts.
|
||||
["topic" => "Wetter/Regen", "pfad" => "tage1", "einheit" => "mm",
|
||||
"stellen" => 1, "gross" => true],
|
||||
"stellen" => 1, "icon" => "cloud-rain"],
|
||||
]],
|
||||
];
|
||||
|
||||
@@ -161,6 +179,28 @@ function floorLabel($floor)
|
||||
return $GLOBALS["floorLabels"][$floor] ?? $floor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codepunkt eines Bootstrap-Icons für die Kacheln.
|
||||
*
|
||||
* Die Icons kommen als Schrift, nicht als Pfad: css/bootstrap-icons.min.css
|
||||
* ist ohnehin eingebunden (restricted/header.php), und SVG-Text darf dieselbe
|
||||
* Schriftfamilie benutzen wie HTML. Ein eingebettetes <path> je Symbol wäre
|
||||
* dieselbe Wirkung mit mehr Zeilen.
|
||||
*
|
||||
* Die Zahlen stehen in genau dieser CSS unter .bi-<name>::before und sind von
|
||||
* dort abgeschrieben - deshalb steht der Name daneben, sonst prüft das nie
|
||||
* wieder jemand nach.
|
||||
*/
|
||||
function kachelIcon($name)
|
||||
{
|
||||
$icons = [
|
||||
"ev-station" => "F83A", // Wallbox, Ladeleistung
|
||||
"cloud-rain" => "F2B6", // Regenmenge
|
||||
"sun" => "F5A2", // PV-Erzeugung
|
||||
];
|
||||
return isset($icons[$name]) ? mb_chr(hexdec($icons[$name]), "UTF-8") : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Etagen mit Grundriss - die, die im Menü und im SVG auftauchen.
|
||||
*
|
||||
@@ -225,7 +265,14 @@ function tileTopics()
|
||||
$zweige = [];
|
||||
foreach (roomsWithTile() as $room) {
|
||||
foreach ($room["werte"] as $wert) {
|
||||
$zweige[explode("/", $wert["topic"])[0] . "/#"] = true;
|
||||
// Ein Wert nennt entweder sein Topic oder einen Wechselrichter,
|
||||
// den homeMQTT.js unter solarManager/invertersN sucht. Ohne diese
|
||||
// Unterscheidung entstand aus dem fehlenden Topic ein "/#" - eine
|
||||
// Anmeldung auf einen leeren Zweig.
|
||||
$zweig = isset($wert["topic"])
|
||||
? explode("/", $wert["topic"])[0]
|
||||
: "solarManager";
|
||||
$zweige[$zweig . "/#"] = true;
|
||||
}
|
||||
}
|
||||
return array_keys($zweige);
|
||||
|
||||
Reference in New Issue
Block a user