Skoda: Ladefenster im neuen Stil, Ladeziel einstellbar

Laden oeffnet jetzt ein Fenster wie auf der Solarseite: Ring mit Ladestand
und Ladeziel, ein Knopf zum Starten oder Stoppen, das Ladeziel in Stufen von
50 bis 100 Prozent. skodaCmd.php kennt dafuer den Befehl ladeziel (PUT
charging/limit) und prueft die Stufe, bevor ein Befehl aus dem Kontingent
draufgeht. Gesendet wird erst, wenn eine Weile keine andere Stufe gewaehlt
wurde; bis das Fahrzeug das Ziel meldet, steht die eigene Wahl im Fenster.
Ohne Kabel ist der Start gesperrt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-16 16:11:32 +02:00
co-authored by Claude Opus 5
parent 05db809140
commit 149cdb46e1
2 changed files with 208 additions and 5 deletions
+24 -5
View File
@@ -3,8 +3,9 @@
* Befehle an das Fahrzeug.
*
* Aufruf per POST: befehl=laden_start | laden_stop | klima_start | klima_stop
* | lueftung_start | lueftung_stop
* | lueftung_start | lueftung_stop | ladeziel
* temperatur=<Grad Celsius> (nur bei klima_start)
* prozent=50..100 in Zehnern (nur bei ladeziel)
*
* Warum über den Server und nicht unmittelbar aus dem Browser? Der API-
* Schlüssel darf die Seite nicht verlassen. Er steht in skoda.conf neben
@@ -62,6 +63,8 @@ const BEFEHLE = [
"klima_stop" => ["pfad" => "air-conditioning/stop", "text" => "Klimatisierung gestoppt"],
"lueftung_start" => ["pfad" => "active-ventilation/start", "text" => "Lüftung gestartet"],
"lueftung_stop" => ["pfad" => "active-ventilation/stop", "text" => "Lüftung gestoppt"],
// Die API nimmt das Ladeziel per PUT, alle anderen Befehle per POST.
"ladeziel" => ["pfad" => "charging/limit", "methode" => "PUT", "text" => "Ladeziel gesetzt"],
];
/* ------------------------------------------------------------------ Zugang */
@@ -79,6 +82,17 @@ if (!isset(BEFEHLE[$name])) {
}
$befehl = BEFEHLE[$name];
// Das Ladeziel vor dem Kontingent pruefen: eine falsche Zahl soll keinen der
// vier Befehle je Stunde kosten. Laut Spec nehmen die Fahrzeuge
// "typischerweise" 50 bis 100 in Zehnern und lehnen alles andere ab.
$prozent = null;
if ($name === "ladeziel") {
$prozent = isset($_POST["prozent"]) ? intval($_POST["prozent"]) : 0;
if ($prozent < 50 || $prozent > 100 || $prozent % 10 !== 0) {
antwort(400, false, "Das Ladeziel geht von 50 bis 100 Prozent in Zehnerschritten.");
}
}
$konfig = skodaBefehlsSchluessel();
if (!$konfig) {
antwort(503, false, "Kein API-Schlüssel hinterlegt - unter Einstellungen "
@@ -94,6 +108,11 @@ if (!budgetFrei(SKODA_BEFEHLE)) {
/* ---------------------------------------------------------------- Ausführen */
$rumpf = null;
$text = $befehl["text"];
if ($name === "ladeziel") {
$rumpf = ["targetStateOfChargeInPercent" => $prozent];
$text = "Ladeziel " . $prozent . "% gesetzt";
}
if ($name === "klima_start") {
// Die Zieltemperatur kommt aus dem Formular und geht in einen Rumpf, den
// die API auswertet - deshalb hart begrenzen statt nur zu vertrauen.
@@ -102,11 +121,11 @@ if ($name === "klima_start") {
$rumpf = ["targetTemperature" => ["value" => $grad, "unit" => "CELSIUS"]];
}
list($status, $inhalt) = senden($konfig, $befehl["pfad"], $rumpf);
list($status, $inhalt) = senden($konfig, $befehl["pfad"], $rumpf, $befehl["methode"] ?? "POST");
if ($status === 202) {
skodaAbrufAnstossen();
antwort(200, true, $befehl["text"] . ". Das Fahrzeug führt den Befehl aus; "
antwort(200, true, $text . ". Das Fahrzeug führt den Befehl aus; "
. "in der Anzeige erscheint es in einer halben Minute.");
}
antwort(200, false, fehlertext($status, $inhalt));
@@ -170,7 +189,7 @@ function budgetFrei($grenze)
}
/** Den Befehl an die API schicken. Liefert [HTTP-Status, Rumpf]. */
function senden($konfig, $pfad, $rumpf)
function senden($konfig, $pfad, $rumpf, $methode = "POST")
{
$url = SKODA_API . rawurlencode($konfig["vin"]) . "/" . $pfad;
$kopf = [
@@ -179,7 +198,7 @@ function senden($konfig, $pfad, $rumpf)
];
$ch = curl_init($url);
$optionen = [
CURLOPT_POST => true,
CURLOPT_CUSTOMREQUEST => $methode,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_USERAGENT => SKODA_KENNUNG,
CURLOPT_TIMEOUT => 20,