[Frage] Realisierung Adapter UDP Keba Wallbox

Forum für Ideen, wie ioBroker verbessert werden kann
gto
Beiträge: 3
Registriert: 13.06.2018, 20:28

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von gto » 13.06.2018, 20:45

Hi
Danke Sneak für das tolle Script.
Ich habe eine Fronius Wechselrichter mit Batterie und die Keba P30c.
Vom Froniusadapter erhalte ich die PV-Produktion als positiven Wert, die Nutzung P_Load ist aber negativ. Ich hab in deinem Script die Berechnung des Ladestrom korrigiert (Vorzeichenwechsel).
Muss ich sonst noch etwas umstellen oder kann ich den neg. Wert im Adapter schon korrigieren, sodass die Grafik stimmt?
Ich würde auch gerne die Automatik Ein/Aus Schaltung automatisieren. Dabei denke ich an das Abschalten der Automatik wenn die produzierte Energie (PV) eine Zeit x unter einem Wert y liegt, als ein Wolkentag oder auch durch Abfrage von Wetterdaten.
Kannst du mir hierbei helfen, kenne mich mit java leider nicht wirklich gut aus.

Danke

Sneak-L8
starter
Beiträge: 45
Registriert: 12.09.2017, 19:50

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von Sneak-L8 » 13.06.2018, 20:58

Hallo gto,

freut mich, wenn dir das Skript gefällt. Eigentlich brauchst Du keine Vorzeichen umdrehen. Es gibt zwei getrennte Felder für Dein Energy Meter. Im einen gibst Du den Namen des States mit dem Netzbezug an, im anderen den mit der Einspeisung. Wenn Dein EnergyMeter beide in einem State liefert (als pos./neg. Werte), dann reicht die Befüllung einer der beiden Felder. Passt das Vorzeichen nicht, dann musst Du das andere Feld nehmen.

Die Funktion, das Laden ganz einzustellen, wenn mind. x Minuten nicht mehr genug PV-Strom zur Verfügung steht, ist schon implementiert. Das ist "nMinLfz". Über nNetzbezug kannst Du angeben, wieviel Watt noch vom Netz gezogen werden dürfen, ohne dass das Laden beendet wird (Bei Erzeugung von 2.200W kann es sich z.B. lohnen die 400W für die minimale Ladeleistung des Autos vom Netz "zuzukaufen").
Und über den State wallboxPVAutomatik kann Du mit "false" auf volle Ladung umschalten, wenn Du mal schnell tanken musst und Dir die Sonne egal ist. Den Schalter kann man das schön im VIS verwalten.

Ich habe zwischenzeitlich noch etwas am Skript geschaubt, weil es oft beim Einstecken für ein paar Minuten geladen hatte, obwohl nicht genug Sonne schien und ich eine Leistungsbegrenzung einbauen musste, weil die Stadtwerke mir sonst kein Laden in der Nacht parallel zur Nachtspeicherheizung erlauben würden.

Hier mal der aktuelle Stand:
Spoiler: Show hidden text
// 01.06.2017 - V1.01 - Ladebeginn wird jetzt bei An- und Abstecken auf null gesetzt
// - Erkennung Ladebeginn nun von 1 W auf 100 W (100.000 mW) erhöht,
// da beim anstecken sonst sofort ein Ladebeginn erkennt wird,
// der zu einer 5 minütigen Ladedauer führt, auch wenn die Sonne
// nicht scheint.
var nMinCurr = 6000; // in mA
var nMaxCurr = getState("kecontact.0.currentHardware"/*Maximum Current Hardware*/).val; // in mA
var nDelta = 500; // Regelgröße der Ladung in mA (damit nicht jedes mA geregelt wird)
var nNetzbezug = 400; // Max. Wattzahl die bei minimaler Ladung auch vom Netz gezogen werden darf.
var nMinLfz = 300; // Sekunden wie lange Ladung mindestens aufrechterhalten wird, auch wenn zu wenig Strom anliegt
var nAktGenau = 0; // Aktueller genauer Ladewert
var nAnzPhasen = 0; // Anzahl der Phasen, mit denen Fahrzeug lädt
var doLog = true; // Aktivieren, um bei der Fehlersuche zu unterstützen
var lAutoVerb = false; // Ist ein Auto mit der Ladebox verbunden?
var oLadeBeginn = null; // Timerbeginn, wenn Laden des Fahrzeugs begonnen wurde
var oSchedule = null; // Schedule-Object
var cStateEinspeisung = "sma-em.0.1901706890.psurplus"; /*Aktuelle Einspeisung, negative Werte werden als Verbrauch interpretiert */
var cStateNetzbezug = "sma-em.0.1901706890.pregard"; /*Aktueller Netzbezug (Stromverbrauch), negative Werte wären Einspeisung */
var cStateVerbrauch1 = "sma-em.0.1901402148.pregard"; /*1. Stromzähler für Leistungsbegrenzung*/
var cStateVerbrauch2 = "sma-em.0.1901706890.pregard"; /*2. Stromzähler für Leistungsbegrenzung*/
var cStateVerbrauch3 = ""; /*3. Stromzähler für Leistungsbegrenzung*/
var nMaxLeistung = 26000; /*Max. Leistung, die über Verbraucher 1-3 abgerufen werden darf*/
var lMaxInklWallbox = true; /*Schalter, ob Wallbox ebenfalls in Verbrauch berücksichtigt wird*/

// Konstanten für States
var cStateWallboxAnAus = "kecontact.0.enableUser"; /*Enable User*/
var cStateWallboxLadung = "kecontact.0.currentUser"; /*Current User*/
var cStateWallboxP1 = "kecontact.0.i1"; /*Current 1*/
var cStateWallboxP2 = "kecontact.0.i2"; /*Current 2*/
var cStateWallboxP3 = "kecontact.0.i3"; /*Current 3*/
var cStateWallboxVerb = "kecontact.0.plug"; /*Plug, Steckerverbindung */
var cStateWallboxStatus = "kecontact.0.state"; /*State, Status der Ladung */
var cStateAktLadung = "kecontact.0.p"; /*Power - Aktuelle Ladung E-Auto*/
var cStateLadebeginn = "wallboxStart"; /*Zeitpukt, wann mit dem Laden des Autos aktiv begonnen wurde*/
var cStateLadeverbindung = "wallboxVerbindung"; /*Zeitpukt, wann das Auto mit der Wallbox zuletzt verbunden wurde*/
var cStateLadestopp = "wallboxSperre"; /*grundsätzliches Ladeverbot z.B. wegen Nachtspeicherheizung*/
var cStateLadeautomatik = "wallboxPVAutomatik"; /*Ladung E-Auto abhängig von PV-Leistung, false = max Ladung unabh. von PV */

createState(cStateLadeautomatik, true, {
read: true,
write: true,
name: "Gibt an, ob die Wallbox abhängig vom PV-Überschuss laden soll (aus = mit voller Leistung laden)",
type: "boolean",
def: true
});

createState(cStateLadestopp, false, {
read: true,
write: false,
name: "Gibt an, ob die Wallbox derzeit gesperrt ist (z.B. wegen aktiver Nachtspeicherheizung)",
type: "boolean",
def: false
});

createState(cStateLadebeginn, null, {
read: true,
write: false,
name: "Gibt an, wann die Wallbox begonnen hat, das Auto zu laden",
type: "string",
role: "datetime",
def: null
});

createState(cStateLadeverbindung, null, {
read: true,
write: false,
name: "Gibt an, wann das Auto zuletzt mit der Wallbox verbunden wurde",
type: "string",
role: "datetime",
def: null
});

function schreibeInfo(text, wichtig) {
if (doLog) {
if (wichtig === true) {
log(text, "info");
} else {
log(text, "debug");
}
}
}

function switchWallbox(enabled) {
schreibeInfo("schalte wallbox: " + enabled);
if (getState(cStateWallboxAnAus).val != enabled) {
setState(cStateWallboxAnAus, enabled);
schreibeInfo("Schalt-Kommando " + enabled + " abgesetzt", true);
if (! enabled) {
oLadeBeginn = null;
}
}
}
function regulateWallbox(milliAmpere) {
schreibeInfo("regle wallbox: " + milliAmpere);
if (getState(cStateWallboxLadung).val != milliAmpere) {
setState(cStateWallboxLadung, milliAmpere);
schreibeInfo("Regler-Kommando auf " + milliAmpere + " abgesetzt", true);
}
}
function getUeberschussOhneWallbox() {
// zunächst ist mal nichts verfügbar
var nVerfuegbar = 0;
if (cStateEinspeisung !== '') {
nVerfuegbar = nVerfuegbar + getState(cStateEinspeisung).val;
}
if (cStateNetzbezug !== '') {
nVerfuegbar = nVerfuegbar - getState(cStateNetzbezug).val;
}
nVerfuegbar = nVerfuegbar + (getState(cStateAktLadung).val / 1000);
return(nVerfuegbar);
}

function getAktGesamtVerbrauch() {
// zunächst mal kein Verbrauch
var nResult = 0;
if (cStateVerbrauch1 !== '') {
nResult = nResult + getState(cStateVerbrauch1).val;
}
if (cStateVerbrauch2 !== '') {
nResult = nResult + getState(cStateVerbrauch2).val;
}
if (cStateVerbrauch3 !== '') {
nResult = nResult + getState(cStateVerbrauch3).val;
}
if (lMaxInklWallbox) {
nResult = nResult - (getState(cStateAktLadung).val / 1000);
}
return nResult;
}

function getLeistungVerfuegbar() {
// Wenn keine Leistungsbegrenzung eingestelt ist, dann max. liefern
if (nMaxLeistung <= 0) {
return 999999;
}
return nMaxLeistung - getAktGesamtVerbrauch();
}

function checkAutoLadung() {
var nCurr = 0; // in mA
var nTempMax = nMaxCurr;
var oAutoState = getState(cStateLadeautomatik);
// Wenn Wallbox lädt, dann die Anzahl der Phasen ermitteln
var nAktPhasen = nAnzPhasen;

if (getState(cStateAktLadung).val > 100000) {
// Wenn Auto wirklich geladen wird, dann merken, wann das begonnen hat,
// damit man gem. Schalter oben dafür sorgen kann, dass mind. eine
// eingestellte Zeitpsanne geladen wird.
if (oLadeBeginn === null) {
oLadeBeginn = new Date();
schreibeInfo("Auto beginnt zu laden", true);
setState(cStateLadebeginn, oLadeBeginn, true);
}
var nTempAnz = 0;
if (getState(cStateWallboxP1).val > 100) {
nTempAnz ++;
}
if (getState(cStateWallboxP2).val > 100) {
nTempAnz ++;
}
if (getState(cStateWallboxP3).val > 100) {
nTempAnz ++;
}
if (nTempAnz > 0) {
// Jetzt die Anzahl Phasen merken
nAnzPhasen = nTempAnz;
nAktPhasen = nTempAnz;
schreibeInfo("Wallbox lädt mit " + nAnzPhasen + " Phasen");
} else {
schreibeInfo("Trotz Ladung keine Phasenanzahl für Wallbox ermittelt", true);
}
}
// Wenn bisher keine Phasenzahl bekannt, dann mit einer Phase rechnen
if (nAktPhasen <= 0) {
nAktPhasen = 1;
}
// State "reparieren", weil VIS-Control 0/1 anstelle false/true setzt
if (typeof oAutoState.val != "boolean") {
setState(cStateLadeautomatik, oAutoState.val == 1, true);
}
// Zunächst Leistungsbegrenzung prüfen
var nMaxAmpere = Math.round(getLeistungVerfuegbar() / 230 / 3 * 1000 / nDelta) * nDelta; // Zur Sicherheit immer mit drei Phasen rechnen
if (nMaxAmpere < nTempMax) {
nTempMax = nMaxAmpere;
}
// Wallbox sperren, wenn entweder eine Ladestopp vorliegt oder die max. verfügbare Leistung unter dem Mindestwert der Wallbox liegt
if (getState(cStateLadestopp).val || (nTempMax < nMinCurr)) {
// Ladung aktuell gesperrt
schreibeInfo("Wallbox ist aktuell gesperrt");
} else {
if (lAutoVerb && getState(cStateLadeautomatik).val) {
var nVerfuegbar = getUeberschussOhneWallbox();
// Ladesteuerung in Stufen von 500mA regeln
nCurr = Math.round(nVerfuegbar / 230 * 1000 / nDelta / nAktPhasen) * nDelta;
if (nCurr < nMinCurr) {
if (oLadeBeginn !== null) {
// Wenn das Auto gerade lädt bzw. laden darf, dann Grenzwerte zum Abschalten berücksichtigen
nCurr = Math.round((nVerfuegbar + nNetzbezug) / 230 * 1000 / nDelta / nAktPhasen) * nDelta;
if (nCurr >= nMinCurr) {
schreibeInfo("Minimale Unterschreitung Ladestrom, Laden wird fortgesetzt", true);
nCurr = nMinCurr;
} else {
if (nMinLfz > 0) {
oAktZeit = new Date();
if ((oAktZeit.getTime() - oLadeBeginn.getTime()) / 1000 < nMinLfz) {
// Mindestladedauer unterschritten? Dann mit minimaler Stärke weiter laden
nCurr = nMinCurr;
schreibeInfo("Minimale Ladezeit noch nicht erreicht, Laden wird fortgesetzt", true);
}
}
}
}
} else {
schreibeInfo("dynamische Anpassung mit " + nCurr + " mA");
}
} else {
nCurr = nTempMax; // Automatik aus oder kein Auto verbunden? Dann mit voller Leistung laden
schreibeInfo("Wallbox wird aktuell mit voller Leistung betrieben");
}
}
if (nCurr < nMinCurr) {
// Wallbox deaktivieren
switchWallbox(false);
regulateWallbox(nMinCurr);
} else {
if (nCurr > nTempMax) {
nCurr = nTempMax;
}
schreibeInfo("Wallbox auf " + nCurr + " mA");
regulateWallbox(nCurr);
switchWallbox(true);
}
}
function checkSchedule(obj) {
schreibeInfo("Status ist: " + getState(cStateWallboxVerb).val);
// 0 unplugged
// 1 plugged on charging station
// 3 plugged on charging station plug locked
// 5 plugged on charging station plugged on EV
// 7 plugged on charging station plug locked plugged on EV
// Bei Ladestation mit ist Status immer mind. 3
var lNewVerb = (getState(cStateWallboxVerb).val >= 5);
if (lAutoVerb != lNewVerb) {
// Es hat sich was geändert, Ladung begonnen oder beendet
// Aber eigentlich uninteressant, Schedule sollte imm geprüft werden
lAutoVerb = lNewVerb;
// Egal ob Auto an- oder abgesteckt wird, dann ist der Ladebeginn
// erstmal zu initialisieren
oLadeBeginn = null;
if (lAutoVerb) {
schreibeInfo("Auto wurde mit Wallbox verbunden", true);
setState(cStateLadeverbindung, new Date(), true);
setState(cStateLadebeginn, oLadeBeginn, true);
} else {
schreibeInfo("Auto wurde von Wallbox getrennt", true);
}
checkAutoLadung();
}
// Wenn die Leistungsbegrenzung aktiv ist, dann muss der Schedule immer laufen
if (lAutoVerb || nMaxLeistung >= 0) {
if (oSchedule === null) {
oSchedule = schedule("*/30 * * * * *", checkAutoLadung);
schreibeInfo("Schedule für Ladeautomatik aktiviert", true);
}
} else {
if(oSchedule) {
clearSchedule(oSchedule);
oSchedule = null;
schreibeInfo("Schedule für Ladeautomatik beendet", true);
}
}

}
subscribe({id: cStateWallboxStatus, change: "ne"}, checkSchedule);
subscribe({id: cStateLadeautomatik, change: "ne"}, checkAutoLadung);
subscribe({id: cStateLadestopp, change: "ne"}, checkAutoLadung);
/* schedule({hour: 6, minute: 1}, function () {
// Nachtspeicherzeit ist vorbei, Wallbox freigeben
setState(cStateLadestopp, false, true);
});
schedule({hour: 21, minute: 39}, function () {
// Nachtspeicherzeit beginnt, Wallbox sperren
setState(cStateLadestopp, true, true);
}); */
// bei Scriptstart States löschen und alles einmal ausführen
setState(cStateLadeverbindung, null, true);
oLadeBeginn = null;
setState(cStateLadebeginn, oLadeBeginn, true);
checkSchedule();
checkAutoLadung();

gto
Beiträge: 3
Registriert: 13.06.2018, 20:28

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von gto » 15.06.2018, 06:45

Hallo, danke für die Antwort

Ich werde mir einen state einbauen um Hausverbrauch, Netzbezug und PV-Produktion einzurechnen. Wegen der Batterie kann nämlich nicht vom Netzbetreiberbezug auf den Hausverbrauch umgerechnet werden. Das bringe ich sicher hin.

Beim 2. Punkt hast du mich missverstanden. Ich würde gerne die Ladestromberechnungsautomatik automatisieren (lustiges Wortspiel). Das soll bedeuten, dass an Wolkentagen die Automatik sich selbstständig deaktiviert, also Frauenfreundlich.

Geht das??

Sneak-L8
starter
Beiträge: 45
Registriert: 12.09.2017, 19:50

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von Sneak-L8 » 15.06.2018, 06:51

Klar. Schreib Dir ein Skript, das eine Prognose für heute abfragt. Bei schlechtem Wetter änderst Du den State PVAutomatik auf false, sonst auf true.
Aber man muss sein Auto auch nicht unbedingt täglich laden, wenn die Reichweite noch ausreichend ist. Das kommt auch den Akkus zugute. Da warte ich lieber auf die Sonne und stelle nur im Notfall die Automatik aus.

gto
Beiträge: 3
Registriert: 13.06.2018, 20:28

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von gto » 15.06.2018, 16:20

Muss täglich laden, haben Hybrid und da fahren wir den Akku jeden Tag leer.

Danke für deine Hilfe

Sneak-L8
starter
Beiträge: 45
Registriert: 12.09.2017, 19:50

Re: [Frage] Realisierung Adapter UDP Keba Wallbox

Beitrag von Sneak-L8 » 15.06.2018, 17:30

Klar, das ist was anderes, lohnt das Laden immer

Antworten