Akkugroessen der beiden Autos stimmen und stehen in der Konfiguration
Der Schieberegler "Zusaetzlich benoetigte Ladung" rechnet Prozent in Wattstunden um. Dafuer standen bisher drei verschiedene Zahlen im Code: 140 Wh/% beim Schreiben der EG-Wallbox, 90 Wh/% beim go-e und feste 14000 Wh beim Zurueckrechnen im Browser - fuer beide Autos dieselbe. Eine Einstellung von 50 % am go-e schrieb 4500 Wh und las sich beim naechsten Oeffnen als 32 % zurueck. Jetzt kommt die Zahl aus einer Quelle: restricted/config.php nennt Auto und nutzbare Akkukapazitaet je Wallbox, carForm.php gibt die Wattstunden je Prozent als data-Attribut an den Schieberegler weiter, und das JavaScript rechnet damit zurueck statt mit einer festen Konstanten. EG: Skoda Enyaq RS, Modelljahr 2026, 84 kWh brutto / 79 kWh nutzbar OG: Jeep Compass 4xe, 11,4 kWh Das Lademodal zeigt Auto und Kapazitaet jetzt unter dem Regler an - damit sichtbar ist, worauf sich die Prozente beziehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+73
-56
@@ -105,44 +105,44 @@ function svgElement(id) {
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// Nur schreiben, wenn sich der Wert wirklich geaendert hat. Jeder Schreibzugriff
|
||||
// macht Style und Paint des Elements ungueltig - bei einem gefilterten Element
|
||||
// wird dabei sein Filter neu gerastert. Gemessen waren rund 71 % der Zugriffe
|
||||
// pro Update reine Wiederholungen desselben Werts; die entfallen damit.
|
||||
const letzterWert = new Map();
|
||||
function schreibe(schluessel, wert, anwenden) {
|
||||
const s = String(wert);
|
||||
if (letzterWert.get(schluessel) === s) return;
|
||||
letzterWert.set(schluessel, s);
|
||||
anwenden(s);
|
||||
}
|
||||
// textContent statt innerHTML: setzt einen Textknoten, ohne den HTML-Parser zu bemuehen.
|
||||
function setText(id, wert) { schreibe("t:" + id, wert, s => { svgElement(id).textContent = s; }); }
|
||||
function setHTML(id, markup) { schreibe("h:" + id, markup, s => { svgElement(id).innerHTML = s; }); }
|
||||
function setAttr(id, name, wert) { schreibe("a:" + id + ":" + name, wert, s => { svgElement(id).setAttribute(name, s); }); }
|
||||
function setDisplay(id, wert) { schreibe("d:" + id, wert, s => { svgElement(id).style.display = s; }); }
|
||||
|
||||
|
||||
// Nur schreiben, wenn sich der Wert wirklich geaendert hat. Jeder Schreibzugriff
|
||||
// macht Style und Paint des Elements ungueltig - bei einem gefilterten Element
|
||||
// wird dabei sein Filter neu gerastert. Gemessen waren rund 71 % der Zugriffe
|
||||
// pro Update reine Wiederholungen desselben Werts; die entfallen damit.
|
||||
const letzterWert = new Map();
|
||||
function schreibe(schluessel, wert, anwenden) {
|
||||
const s = String(wert);
|
||||
if (letzterWert.get(schluessel) === s) return;
|
||||
letzterWert.set(schluessel, s);
|
||||
anwenden(s);
|
||||
}
|
||||
// textContent statt innerHTML: setzt einen Textknoten, ohne den HTML-Parser zu bemuehen.
|
||||
function setText(id, wert) { schreibe("t:" + id, wert, s => { svgElement(id).textContent = s; }); }
|
||||
function setHTML(id, markup) { schreibe("h:" + id, markup, s => { svgElement(id).innerHTML = s; }); }
|
||||
function setAttr(id, name, wert) { schreibe("a:" + id + ":" + name, wert, s => { svgElement(id).setAttribute(name, s); }); }
|
||||
function setDisplay(id, wert) { schreibe("d:" + id, wert, s => { svgElement(id).style.display = s; }); }
|
||||
|
||||
|
||||
// Punktgroesse einer Flusslinie setzen und die Animation anhalten, wenn kein
|
||||
// Fluss anliegt. --w ist der Durchmesser, die CSS-Regel macht daraus den Radius
|
||||
// aller Punkte der Gruppe. will-change nur solange die Gruppe laeuft: es fordert
|
||||
// eine eigene Compositor-Ebene an, und die kostet Speicher.
|
||||
function setFlowWidth(id, width) {
|
||||
const flow = svgElement(id);
|
||||
// Eine negative Breite heisst "kein Fluss in dieser Richtung" - die
|
||||
// Aufrufer rechnen 55*(1-exp(x)), was bei umgekehrtem Vorzeichen negativ
|
||||
// wird. Frueher zeichnete eine negative stroke-width schlicht nichts.
|
||||
// Math.max haelt das bei; Math.abs wuerde stattdessen einen Fluss in der
|
||||
// falschen Richtung mit voller Staerke anzeigen.
|
||||
const breite = Math.max(0, width);
|
||||
const sichtbar = breite >= 0.5;
|
||||
flow.style.setProperty("--w", breite + "px");
|
||||
flow.style.animationPlayState = sichtbar ? "running" : "paused";
|
||||
flow.style.willChange = sichtbar ? "transform" : "auto";
|
||||
}
|
||||
|
||||
|
||||
// Punktgroesse einer Flusslinie setzen und die Animation anhalten, wenn kein
|
||||
// Fluss anliegt. --w ist der Durchmesser, die CSS-Regel macht daraus den Radius
|
||||
// aller Punkte der Gruppe. will-change nur solange die Gruppe laeuft: es fordert
|
||||
// eine eigene Compositor-Ebene an, und die kostet Speicher.
|
||||
function setFlowWidth(id, width) {
|
||||
const flow = svgElement(id);
|
||||
// Eine negative Breite heisst "kein Fluss in dieser Richtung" - die
|
||||
// Aufrufer rechnen 55*(1-exp(x)), was bei umgekehrtem Vorzeichen negativ
|
||||
// wird. Frueher zeichnete eine negative stroke-width schlicht nichts.
|
||||
// Math.max haelt das bei; Math.abs wuerde stattdessen einen Fluss in der
|
||||
// falschen Richtung mit voller Staerke anzeigen.
|
||||
const breite = Math.max(0, width);
|
||||
const sichtbar = breite >= 0.5;
|
||||
flow.style.setProperty("--w", breite + "px");
|
||||
flow.style.animationPlayState = sichtbar ? "running" : "paused";
|
||||
flow.style.willChange = sichtbar ? "transform" : "auto";
|
||||
}
|
||||
|
||||
const solarSVG = {
|
||||
updateCnt: 99,
|
||||
/**
|
||||
@@ -222,7 +222,7 @@ const solarSVG = {
|
||||
h = "0" + h;
|
||||
if (m < 10)
|
||||
m = "0" + m;
|
||||
setText("evRemText", h + ":" + m);
|
||||
setText("evRemText", h + ":" + m);
|
||||
}
|
||||
} else {
|
||||
setText("evRemText", "");
|
||||
@@ -234,9 +234,9 @@ const solarSVG = {
|
||||
setText("pv1txt", powerToString(pv1));
|
||||
setText("pv2txt", powerToString(pv2));
|
||||
setText("pv3txt", powerToString(pv3));
|
||||
setText("il1txt", Math.round(i_l1evu * 10) / 10 + " A");
|
||||
setText("il2txt", Math.round(i_l2evu * 10) / 10 + " A");
|
||||
setText("il3txt", Math.round(i_l3evu * 10) / 10 + " A");
|
||||
setText("il1txt", Math.round(i_l1evu * 10) / 10 + " A");
|
||||
setText("il2txt", Math.round(i_l2evu * 10) / 10 + " A");
|
||||
setText("il3txt", Math.round(i_l3evu * 10) / 10 + " A");
|
||||
setText("batText", powerToString(pbatt));
|
||||
setText("heatText", powerToString(Pheat));
|
||||
setText("evText", powerToString(evPower * 1000));
|
||||
@@ -264,7 +264,7 @@ const solarSVG = {
|
||||
i++;
|
||||
}
|
||||
|
||||
setHTML("invList", tttext);
|
||||
setHTML("invList", tttext);
|
||||
setAttr("egArc", "d", describeArc(100, 100, 95, 0, Math.round(eg / angleFactor)));
|
||||
setAttr("ugArc", "d", describeArc(100, 100, 95, 0, Math.round(ug / angleFactor)));
|
||||
setAttr("pvArc", "d", describeArc(100, 100, 95, 0, Math.round(pv1 / angleFactor)));
|
||||
@@ -602,6 +602,15 @@ var chartSettings = {
|
||||
|
||||
|
||||
|
||||
// Setzt den Schieberegler aus den Wattstunden, die die Wallbox meldet.
|
||||
function setzeLadeRegler(wattstunden) {
|
||||
const regler = document.getElementById("modal-slider");
|
||||
const whProProzent = Number(regler.dataset.whProProzent);
|
||||
if (whProProzent > 0) {
|
||||
regler.value = Math.round(Number(String(wattstunden)) / whProProzent);
|
||||
}
|
||||
}
|
||||
|
||||
function openModal(type) {
|
||||
document.getElementById("modalSaveBtn").style.display = type === "watering" ? "none" : "";
|
||||
switch(type){
|
||||
@@ -663,7 +672,11 @@ var chartSettings = {
|
||||
else if (mode == "AutomaticStop") { document.getElementById("EV_NextTrip").click(); }
|
||||
else { alert(mode); }
|
||||
document.getElementById("EV_NextTripTime").value = time.toHHMM();
|
||||
document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
|
||||
// Wattstunden je Prozent liefert das Formular mit (carForm.php);
|
||||
// die Akkugroesse steht in restricted/config.php. Frueher standen
|
||||
// hier feste 14000 Wh - fuer beide Autos dasselbe, und fuer keines
|
||||
// von beiden richtig.
|
||||
setzeLadeRegler(energy);
|
||||
document.getElementById("modal-slider").dispatchEvent(new Event('input'));
|
||||
if (amp == "16") { document.getElementById("EV_16A").click(); }
|
||||
else if (amp == "10") { document.getElementById("EV_10A").click(); }
|
||||
@@ -685,7 +698,11 @@ var chartSettings = {
|
||||
else if (mode == "5") { document.getElementById("EV_NextTrip").click(); }
|
||||
else { alert(mode); }
|
||||
document.getElementById("EV_NextTripTime").value = time.toHHMM();
|
||||
document.getElementById("modal-slider").value = Math.round(energy * 100 / 14000);
|
||||
// Wattstunden je Prozent liefert das Formular mit (carForm.php);
|
||||
// die Akkugroesse steht in restricted/config.php. Frueher standen
|
||||
// hier feste 14000 Wh - fuer beide Autos dasselbe, und fuer keines
|
||||
// von beiden richtig.
|
||||
setzeLadeRegler(energy);
|
||||
document.getElementById("modal-slider").dispatchEvent(new Event('input'));
|
||||
if (amp == "16") { document.getElementById("EV_16A").click(); }
|
||||
else if (amp == "10") { document.getElementById("EV_10A").click(); }
|
||||
@@ -1069,21 +1086,21 @@ var chartSettings = {
|
||||
// "Aus" bleibt bei nicht geplant stehen; bei geplant ersetzt die
|
||||
// Stoppuhr (U+23F1, ohne Emoji-Variationsselektor -> einfarbig, folgt
|
||||
// der Icon-Farbe) den Text, um Platz auf der textPath zu sparen.
|
||||
// Laeuft im Sekundentakt, aendert sich aber selten - ohne Pruefung
|
||||
// wuerde jede Sekunde derselbe Wert geschrieben und das Icon samt
|
||||
// Filter neu gezeichnet.
|
||||
const text = state === "aus" ? (planned ? "⏱" : "Aus") : state;
|
||||
if (status.textContent !== text) status.textContent = text;
|
||||
// Laeuft im Sekundentakt, aendert sich aber selten - ohne Pruefung
|
||||
// wuerde jede Sekunde derselbe Wert geschrieben und das Icon samt
|
||||
// Filter neu gezeichnet.
|
||||
const text = state === "aus" ? (planned ? "⏱" : "Aus") : state;
|
||||
if (status.textContent !== text) status.textContent = text;
|
||||
// Geplant-Blau ("#3A6292") entspricht dem Wassertropfen-Icon (id="water").
|
||||
const color = state !== "aus" ? (paused ? "#ffc107" : "#20c997") : planned ? "#3A6292" : "#6c757d";
|
||||
if (icon.getAttribute("color") !== color) {
|
||||
icon.setAttribute("color", color);
|
||||
icon.setAttribute("fill", color);
|
||||
icon.style.color = color;
|
||||
}
|
||||
const titel = name + ": " + (state === "aus" && planned ? "Aus (Automatik heute noch geplant)" : state);
|
||||
const titelKnoten = icon.querySelector("title");
|
||||
if (titelKnoten.textContent !== titel) titelKnoten.textContent = titel;
|
||||
if (icon.getAttribute("color") !== color) {
|
||||
icon.setAttribute("color", color);
|
||||
icon.setAttribute("fill", color);
|
||||
icon.style.color = color;
|
||||
}
|
||||
const titel = name + ": " + (state === "aus" && planned ? "Aus (Automatik heute noch geplant)" : state);
|
||||
const titelKnoten = icon.querySelector("title");
|
||||
if (titelKnoten.textContent !== titel) titelKnoten.textContent = titel;
|
||||
}
|
||||
|
||||
window.setInterval(updateWateringStatus, 1000);
|
||||
|
||||
Reference in New Issue
Block a user