Man könnte das bequem mit einem 3-Zeiler erledigen. Aber da viele mit Skripten auf Kriegsfuß stehen und ich mal wieder was ausprobieren wollte hier eine Copy&Paste-Lösung:
Man erstelle ein WebUI-Programm das kontinuierlich oder wie auch immer durch die 1. Bedingung des Programms getriggert wird.
Ver-ODER-t fügt man die zu behandelnde Systemvariable mit "nur prüfen" ein. (man kann auch UND wählen, solange die Bedingung immer erfüllt ist)
Dabei ist es egal wie, Hauptsache es ist die 2. Bedingung. Danach dürfen auch weitere Bedingungen folgen. Es dürfen auch mehrere Aktionen im DANN stehen.
Im DANN fügt man das Skript ein.
Dieses konfiguriert man wie folgt:
Delta gibt den Delta-Wert an um den erhöht oder - bei negativen Werten - erniedrigt wird.
rLimit ist der Maximal bzw. Minimal Wert, der erreicht werden darf.
Ist das Limit erreicht, dann wird die Systemvariable auf den Wert von rStart gesetzt.
bDebug kann man auf true stellen und dem Skript dann im Fehlerprotokoll beim arbeiten zu sehen.
Alternativ kann man die Konfigurationswerte auch über Systemvariablen setzen. Das hat den Vorteil, das man über die WebUI, durch ein einfaches WebUi Programm oder eine "App" neue Parameter übergeben kann, ohne das Skript editieren zu müssen.
Dazu legt man parallel zu der eigentlichen Ziel-Systemvariable, die geändert wird, weitere Systemvariablen an. Ziel steht dabei für den Namen der eigentlichen Ziel-SV. In den oben gezeigten Beispiel wäre das xxZahl .
Ziel_Delta legt den Delta-Wert fest - also z.B. xxZahl_Delta
Ziel_Limit legt das Limit fest - also z.B. xxZahl_Limit
Ziel_Start legt den Startwert fest - also z.B. xxZahl_Start
Ob und wenn, welche SV wirkllch benutzt wird, ist vollkommen frei. Wenn die SV nicht existiert, wird der Wert aus dem Skript genommen.
Hier das Skript:
Code: Alles auswählen
! Systemvariable um x hoch/runterzählen
! V1.2 MichaelN https://homematic-forum.de/forum/viewtopic.php?f=31&t=77401
! GPL-3.0-or-later
!
! Das Programm mit diesem Skript wird durch die erste Bedingung im WENN ausgelöst
! Es muss eine Systemvariable Typ Zahl <SV-Ziel> im ODER stehen - die Bedingung ist egal - nur prüfen
! dieses Skript ins DANN
! Die Systemvariable <SV-Ziel> hinter dem ODER wird automatisch ermittelt und um Delta erhöht (oder reduziert, wenn Delta negativ ist)
! <SV-Ziel> steht stellvertretend für den Namen der Systemvariable, die geändert wird
integer Delta = 1; ! Wert um den erhöht wird (oder reduziert wenn negativ) - kann auch durch eine SV mit dem Namen <Ziel-SV>_Delta gesetzt werden
real rLimit = 10; !Wert bis zu dem hoch/runter gezählt wird - kann auch durch eine SV mit dem Namen <Ziel-SV>_Limit gesetzt werden
real rStart = 0; ! Wert auf den nach erreichen des Limits gesetzt wird - kann auch durch eine SV mit dem Namen <Ziel-SV>_Start gesetzt werden
boolean bDebug = false; ! true für Debugging Infos im Fehlerprotokoll
! hier nichts mehr ändern
real Wert; object SV;
integer srcId = ("$src$").ToInteger();
object oPrg = dom.GetObject("$this$");
string Skriptname = oPrg.Name();
string s_text; string s_out; string s_err;
if (bDebug) {
s_text = "START SRC: " # srcId # " - THIS: " # "$this$";
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
if (srcId > 0) {
object oSrc = dom.GetObject(srcId);
if (!oSrc) { s_text = "SRC kein Objekt"; system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err); quit; };
}
else { s_text = "SRC kein Objekt"; system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err); quit; }
! Wo steckt die SV?
integer iCondition = 0; !Nummer der Condition
integer iSingle = 1; !Nummer der SingleCondition
object oCND; object oSCND;
object oRULE= oPrg.Rule ();
oCND=oRULE.RuleCondition(iCondition); ! Condition
! Single Condition
if (oCND.CndSingleCount() == 2 )
{ ! ODER in der 1. Cond
oSCND=oCND.CndSingleCondition(iSingle);
} else {
! ODER in der 2. Cond
iCondition = 1; !Nummer der Condition
iSingle = 0;
oCND=oRULE.RuleCondition(iCondition);
oSCND=oCND.CndSingleCondition(iSingle);
}
! SV ermitteln
object LeftCND = dom.GetObject(oSCND.LeftVal());
if ( LeftCND.Type() == OT_VARDP )
{
! Links Systemvariable?
if (bDebug) {
s_text = "Systemvariable gefunden: " # LeftCND.Name();
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
! Delta in SV?
SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(LeftCND.Name() # "_Delta");
if (SV) { Delta = SV.Value(); }
! Limit in SV?
SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(LeftCND.Name() # "_Limit");
if (SV) { rLimit = SV.Value(); }
! Start in SV?
SV = dom.GetObject(ID_SYSTEM_VARIABLES).Get(LeftCND.Name() # "_Start");
if (SV) { rStart = SV.Value(); }
if (bDebug) {
s_text = "Delta/" # Delta # " / Limit/" # rLimit # " / Start/" # rStart;
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
if (((Delta < 0) && (rStart < rLimit)) || ((Delta > 0) && (rStart > rLimit)))
{
s_text = "Parameter sind nicht logisch definiert: Delta/" # Delta # " / Limit/" # rLimit # " / Start/" # rStart;
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
! aktuellen Wert auslesen
Wert = LeftCND.State();
! Delta hinzu
Wert = Wert + Delta;
s_text = "";
! zulässigen Max Wert beachten
if ( (Delta > 0) && (Wert > rLimit) ) { Wert = rStart; s_text = "max-Limit erreicht / ";}
! zulässigen Min Wert beachten
if ( (Delta < 0) && (Wert < rLimit) ) { Wert = rStart; s_text = "min-Limit erreicht / ";}
LeftCND.State(Wert);
if (bDebug) {
s_text = s_text # "neuen Wert geschrieben /" # Wert.ToString();
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
}
if (bDebug) {
s_text = "Ende";
system.Exec("logger -t "#Skriptname#" -p user.debug "#s_text, &s_out, &s_err);
}
V1.2 - kleinen Logikfehler beseitigt; Log-Meldungen erweitert