universelles Skript um Systemvariable hoch / runter zu zählen

Problemlösungen und Hinweise von allgemeinem Interesse zur Haussteuerung mit HomeMatic

Moderator: Co-Administratoren

Antworten
MichaelN
Beiträge: 9562
Registriert: 27.04.2020, 10:34
System: CCU
Hat sich bedankt: 696 Mal
Danksagung erhalten: 1608 Mal

universelles Skript um Systemvariable hoch / runter zu zählen

Beitrag von MichaelN » 05.01.2023, 10:19

Angeregt durch einen anderen Thread habe ich ein universelles Skript zu hoch bzw. runterzählen einer Systemvariable erstellt.
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.

Bild
Bild

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);
		}
ChangeLog:
V1.2 - kleinen Logikfehler beseitigt; Log-Meldungen erweitert
LG, Michael.

Wenn du eine App zur Bedienung brauchst, dann hast du kein Smarthome.

Wettervorhersage über AccuWeather oder OpenWeatherMap+++ Rollladensteuerung 2.0 +++ JSON-API-Ausgaben auswerten +++ undokumentierte Skript-Befehle und Debugging-Tipps +++

Antworten

Zurück zu „HomeMatic Tipps & Tricks - keine Fragen!“