Timeout für while-Endlosschleife

Homematic-, TCL- und Shell-Script, Toolchain, C, etc.

Moderator: Co-Administratoren

dtp
Beiträge: 10655
Registriert: 21.09.2012, 08:09
System: CCU
Wohnort: Stuttgart
Hat sich bedankt: 320 Mal
Danksagung erhalten: 501 Mal

Timeout für while-Endlosschleife

Beitrag von dtp » 04.12.2020, 08:01

Hallo,

mir ist gestern beim Skripten mehrmals ein kleiner Fauxpas passiert, weil ich vergessen hatte, ein Abbruchkriterium für eine while-Schleife mit in das Skript einzubauen. Kurzum, wenn man so eine Schleife unter "Skript testen" auf der CCU ausführt, dann steigt sie bekanntlich nach einigen Minuten aus und verabschiedet sich mit nem Hinweis, dass der ReGaHSS-Dienst nicht mehr erreichbar sei.

Der SDV von @Black fängt sowas durch einen Kill-Befehl und eine entsprechende Timeout-Meldung ab. Daher frage ich mich, ob man eine solche Funktion nicht auch direkt in der ReGaHSS der CCU implementieren könnte, um Abstürze zu vermeiden.

Oder geht das prinzipiell nicht?

Gruß,

Thorsten

PS.: Warum gibt es eigentlich keine normalen for-Schleifen?
CCU3 mit stets aktueller FW und den Addons "CUxD" und "Programmedrucken", ioBroker auf Synology DiskStation DS718+ im Docker-Container;
einige Projekte: zentrales Push-Nachrichten-Programm zPNP, DoorPi-Videotürsprechanlage, An- und Abwesenheitsdetektion per Haustürschloss, zentrales Programm zur Steuerung von Beschattungsgeräten zBSP.

jp112sdl
Beiträge: 12084
Registriert: 20.11.2016, 20:01
Hat sich bedankt: 847 Mal
Danksagung erhalten: 2139 Mal
Kontaktdaten:

Re: Timeout für while-Endlosschleife

Beitrag von jp112sdl » 04.12.2020, 09:30

Laut Doku ist nach 500000 Iterationen ohnehin schluss, um Endlosschleifen zu verhindern.
Funktioniert das nicht (mehr) ?

VG,
Jérôme ☕️

---
Support for my Homebrew-Devices: Download JP-HB-Devices Addon

dtp
Beiträge: 10655
Registriert: 21.09.2012, 08:09
System: CCU
Wohnort: Stuttgart
Hat sich bedankt: 320 Mal
Danksagung erhalten: 501 Mal

Re: Timeout für while-Endlosschleife

Beitrag von dtp » 04.12.2020, 09:33

Das kann ich dir nicht genau sagen. Scheinbar nicht, denn - wie gesagt - ich konnte meine CCU3 reproduzierbar abschmieren lassen. Nach ca. 3 bis 5 Minuten erhielt ich besagte Meldung. Es wurde mir auch während des Schleifendurchlaufs keine WriteLine-Ausgabe im Ausgabefenster angezeigt. Das Fenster bleib einfach weiß, so als wenn es einen Syntax-Fehler gäbe, den es aber nicht gab.
CCU3 mit stets aktueller FW und den Addons "CUxD" und "Programmedrucken", ioBroker auf Synology DiskStation DS718+ im Docker-Container;
einige Projekte: zentrales Push-Nachrichten-Programm zPNP, DoorPi-Videotürsprechanlage, An- und Abwesenheitsdetektion per Haustürschloss, zentrales Programm zur Steuerung von Beschattungsgeräten zBSP.

Benutzeravatar
jmaus
Beiträge: 9818
Registriert: 17.02.2015, 14:45
System: Alternative CCU (auf Basis OCCU)
Wohnort: Dresden
Hat sich bedankt: 459 Mal
Danksagung erhalten: 1855 Mal
Kontaktdaten:

Re: Timeout für while-Endlosschleife

Beitrag von jmaus » 04.12.2020, 09:45

jp112sdl hat geschrieben:
04.12.2020, 09:30
Laut Doku ist nach 500000 Iterationen ohnehin schluss, um Endlosschleifen zu verhindern.
Funktioniert das nicht (mehr) ?
Doch, laut täglichem ReGaHss Test funktioniert das immer noch tadellos. Siehe:

https://github.com/jens-maus/occu-test/ ... #step:7:70

Das ist ja aber eben eine Beschränkung der maximalen Anzahl von Schleifendurchläufen und keine zeitliche Begrenzung. D.h. je nachdem was dtp hier innerhalb einer iteration zeitaufwendiges tut kann das natürlich unterm Strich dann dazu führen, das es auch dann mitunter ewig dauern kann bis er die maximale Anzahl an Iterationen erreicht und somit für diesen Zeitraum die ReGaHss komplett lahmgelegt ist. Ergo, das ist genau einer dieser Cornercases wieso ich immer noch darauf hinweise das das Scripting in WebUI Programmen mit vorsicht zu geniesen ist und man gut bedient ist - wenn möglich - gänzlich darauf zu verzichten und die Arbeit potenteren, externen Logikengines wie ioBroker, RedMatic & Co zu überlassen die dann die umfangreicheren Sprachkonstrukte (z.B. javascript) mit sich bringen die einem nicht zulassen sich dermaßen in die Füße zu schießen oder die CCU derart leicht in die Knie zu zwingen.
RaspberryMatic 3.75.6.20240316 @ ProxmoxVE – ~200 Hm-RF/HmIP-RF/HmIPW Geräte + ioBroker + HomeAssistant – GitHub / Sponsors / PayPal / ☕️

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

Re: Timeout für while-Endlosschleife

Beitrag von MichaelN » 04.12.2020, 09:50

@dtp: Dann hast Du da ggf. Noch einen anderen Bock drin. Mir ist das auch beim Testen paarmal passiert, da kam die CCU aber nach 500000 Iterationen wieder zurück. Ich habe daher dann ein Abbruch Kriterium mit eingebaut, wenn ich in einer Schleife mit unbekannten Daten hantiere, damit die Schleife immer sicher abbricht.

Code: Alles auswählen

Counter = 0;
... 
while ( (StartPos>=0) && (Counter<100) ){
 ... 
 Counter = Counter + 1;
 ... 
  }
  
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 +++

Benutzeravatar
Black
Beiträge: 5463
Registriert: 12.09.2015, 22:31
System: Alternative CCU (auf Basis OCCU)
Wohnort: Wegberg
Hat sich bedankt: 418 Mal
Danksagung erhalten: 1069 Mal
Kontaktdaten:

Re: Timeout für while-Endlosschleife

Beitrag von Black » 04.12.2020, 10:27

Für eine vorher feststehende Anzahl von Iterationen (STart und Endwert bekannt) gibt es auch noch die Möglichkeit mit
[string]=system.GenerateEnum (startvalue,mEndvalue) zu arbeiten

damit lässt sich z.b. EIne For Schleife mit Startwert 2 und Entwert 9 so aufbauen:

Code: Alles auswählen

string n;
foreach (n,system.GenerateEnum (2,9)) {
 WriteLine (n);
}
Black
Wenn das Fernsehprogramm immer mehr durch nervende Werbung unterbrochen wird und der Radiomoderator nur noch Müll erzählt, ist es besser, die Zeit für sinnvolle Dinge zu nutzen -
mal aufs Klo zu gehen, ein Bier zu holen oder einfach mal den roten AUS-Knopf zu drücken. Klick - und weg

Script Time Scheduler V1.3
AstroSteuerung über Zeitmodul flexibel mit Offset / spätestens, frühestens
SDV 5.03.01 Das umfassende Entwicklungs und Diagnosetool für Homematik
Selektive Backups - Nützliche Dinge, die die WebUI nicht kann

Intel NUC6 Celeron 16GB mit 512GB SSD unter Proxxmox mit insgesamt 5 VM: 2 x bloatwarebefreiter Raspberrymatik, 2 x IOBroker als Middleware und einer MariaDB zur Archivierung. Verbrauch: 6W

technical contribution against annoying advertising

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

Re: Timeout für while-Endlosschleife

Beitrag von MichaelN » 04.12.2020, 11:13

Das könnte man auch bei unbestimmter Anzahl zur Begrenzung der maximalen Durchläufe nutzen:

Code: Alles auswählen

string n;
foreach (n,system.GenerateEnum (1,100)) {
 WriteLine (n);
 If (fertig) {break} ! vorzeitig beenden
}
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 +++

alchy
Beiträge: 10752
Registriert: 24.02.2011, 01:34
System: CCU
Hat sich bedankt: 65 Mal
Danksagung erhalten: 672 Mal

Re: Timeout für while-Endlosschleife

Beitrag von alchy » 04.12.2020, 12:00

Black hat geschrieben:
04.12.2020, 10:27
damit lässt sich z.b. EIne For Schleife mit Startwert 2 und Entwert 9 so aufbauen:

genau, oder eben per while

Code: Alles auswählen

integer Count = 2;
while (Count <= 9)
{
  WriteLine(Count);
  Count = Count + 1;
}
Da keiner weiß, was dtp wirklich gemacht hat, wird es schwierig.
z.B. brauch ein Script wie dieses:

Code: Alles auswählen

integer Count = 0;
while (Count <= 500000)
{
  WriteLine(Count);
  Count = Count + 1;
}
nur ca. 15-20Sek. um in den Begrenzer zu rauschen.

Alchy

Blacklist................... almost full
Ignoranz ist die Summe aller Maßnahmen die man ergreift, um bestehende Tatsachen nicht sehen zu müssen.

© Sandra Pulsfort (*1974)

Lies bitte die Logik von WebUI Programmen und die Tipps und Tricks für Anfänger.

Wichtig auch CUxD ersetzt System.exec. Die HM Script Doku (Downloadart Skripte) hilft auch weiter.
Zum Testen von Scripten den >> HomeMatic Script Executor << von Anli benutzen.

dtp
Beiträge: 10655
Registriert: 21.09.2012, 08:09
System: CCU
Wohnort: Stuttgart
Hat sich bedankt: 320 Mal
Danksagung erhalten: 501 Mal

Re: Timeout für while-Endlosschleife

Beitrag von dtp » 04.12.2020, 13:05

Ich poste euch das Skript heute Abend mal. ;) Auf jeden Fall schon mal vielen Dank für die nützlichen Infos.
CCU3 mit stets aktueller FW und den Addons "CUxD" und "Programmedrucken", ioBroker auf Synology DiskStation DS718+ im Docker-Container;
einige Projekte: zentrales Push-Nachrichten-Programm zPNP, DoorPi-Videotürsprechanlage, An- und Abwesenheitsdetektion per Haustürschloss, zentrales Programm zur Steuerung von Beschattungsgeräten zBSP.

dtp
Beiträge: 10655
Registriert: 21.09.2012, 08:09
System: CCU
Wohnort: Stuttgart
Hat sich bedankt: 320 Mal
Danksagung erhalten: 501 Mal

Re: Timeout für while-Endlosschleife

Beitrag von dtp » 05.12.2020, 12:35

Hier mal das Skript. Glaube aber nicht, dass jemand Lust hat, sich damit auseinanderzusetzen. ;)

Hab nun in die while-Schleife eine kleine Zusatzbedingung (cnt < 10) eingaubaut, um eine Endlosschleife zu verhindern.

Was macht das Skript? Nun es teilt eine länger Nachricht in Teilnachrichten auf und schaut dabei, dass Unterbrechungen nicht innerhalb eines HTML-Tags oder eines Wortes vorkommen. Läuft aber noch nicht so richtig rund. Deswegen ja auch die Endlosschleife. 8)

Code: Alles auswählen

string message = "Ich bin heute hier um ein <font color=orange>schönes</font> Buch vorzustellen! Dieses Buch handelt von einem kleinen Mannn, der einen <font color=green>dicken Hund</font> hat. Der dicke Hund hat dem kleinen Mann das Leben gerettet und daher liebt ihn der kleine Mann über alles. Na, seid ihr gespannt, wie die Geschichte weitergeht? Dann lest euch das Buch durch!";

integer msgLength = 90;
boolean msgListInvert = false;

string messageTrc; string messagesList = ""; string gttnSgnsPosList = ""; string gttnSgnPos; string letnSgnsPosList = ""; string letnSgnPos;
integer cnt; integer charCnt; integer fullStopPos = 0; integer exclMarkPos = 0; integer qustMarkPos = 0; integer spaceChrPos = 0;
integer noGttnSgnPos; integer noLetnSgnPos;

cnt = 1;
if(msgLength < 50){msgLength = 50;} if(msgLength > 1000){msgLength = 1000;}
if(message.Length() > msgLength){
  while((message.Length() >= msgLength) && (cnt < 10)){
    messageTrc = message.Substr(0, msgLength);

    charCnt = messageTrc.Length();
    while(charCnt > 0){
      if((messageTrc.Substr(charCnt, 1)).Contains(">")){gttnSgnsPosList = gttnSgnsPosList#(charCnt)#";";}
      if((messageTrc.Substr(charCnt, 1)).Contains("<")){letnSgnsPosList = letnSgnsPosList#(charCnt)#";";}
      if((messageTrc.Substr(charCnt, 1)).Contains(".")){if(charCnt >= fullStopPos){fullStopPos = charCnt + 1;}}
      if((messageTrc.Substr(charCnt, 1)).Contains("!")){if(charCnt >= exclMarkPos){exclMarkPos = charCnt + 1;}}
      if((messageTrc.Substr(charCnt, 1)).Contains("?")){if(charCnt >= qustMarkPos){qustMarkPos = charCnt + 1;}}
      if((messageTrc.Substr(charCnt, 1)).Contains(" ")){if(charCnt >= spaceChrPos){spaceChrPos = charCnt + 1;}}
      charCnt = charCnt - 1;
    }
    gttnSgnsPosList = gttnSgnsPosList.RTrim(";"); noGttnSgnPos = web.webGetValueListCount(gttnSgnsPosList);
    letnSgnsPosList = letnSgnsPosList.RTrim(";"); noLetnSgnPos = web.webGetValueListCount(letnSgnsPosList);
    WriteLine("cnt = "#cnt);
    WriteLine(">: "#gttnSgnsPosList);
    WriteLine("<: "#letnSgnsPosList);
    WriteLine(".: "#fullStopPos);
    WriteLine("!: "#exclMarkPos);
    WriteLine("?: "#qustMarkPos);
    WriteLine(" : "#spaceChrPos);

WriteLine(noGttnSgnPos); WriteLine(noLetnSgnPos); 
WriteLine(noGttnSgnPos.Mod(2));
    if((noGttnSgnPos.Mod(2) != 0) || (noLetnSgnPos.Mod(2) != 0)){
      if(noGttnSgnPos < noLetnSgnPos){
        letnSgnPos = letnSgnsPosList.StrValueByIndex(";",1).ToInteger();
      }
      else{
        letnSgnPos = letnSgnsPosList.StrValueByIndex(";",0).ToInteger();
      }
   WriteLine("letnSgnPos = "#letnSgnPos);
      messageTrc = message.Substr(0, letnSgnPos - 1);
      message = message.Substr(letnSgnPos - 1, message.Length());
    }
    elseif(fullStopPos > 0){
      messageTrc = message.Substr(0, fullStopPos);
      message = message.Substr(fullStopPos, message.Length());
    }
    elseif(exclMarkPos > 0){
      messageTrc = message.Substr(0, exclMarkPos);
      message = message.Substr(exclMarkPos, message.Length());
    }
    elseif(qustMarkPos > 0){
      messageTrc = message.Substr(0, qustMarkPos);
      message = message.Substr(qustMarkPos, message.Length());
    }
    elseif(spaceChrPos > 0){
      messageTrc = message.Substr(0, spaceChrPos);
      message = message.Substr(spaceChrPos, message.Length());
    }
    else{message = message.Substr(msgLength, message.Length());}
 WriteLine(message.Length());
    if(msgListInvert){messagesList = "Teilnachricht Nr. "#cnt#"\n"#messageTrc.Trim()#"\t"#messagesList;}
    else{messagesList = messagesList#"\tTeilnachricht Nr. "#cnt#"\n"#messageTrc.Trim();}

    cnt = cnt + 1;
    gttnSgnsPosList = ""; letnSgnsPosList = "";
  }
  if(message.Length() >= 1){
    if(msgListInvert){messagesList = "Teilnachricht Nr. "#cnt#"\n"#message.Trim()#"\t"#messagesList;}
    else{messagesList = messagesList#"\tTeilnachricht Nr. "#cnt#"\n"#message.Trim();}
  }
  messagesList = messagesList.Trim();
}

WriteLine(messagesList);
CCU3 mit stets aktueller FW und den Addons "CUxD" und "Programmedrucken", ioBroker auf Synology DiskStation DS718+ im Docker-Container;
einige Projekte: zentrales Push-Nachrichten-Programm zPNP, DoorPi-Videotürsprechanlage, An- und Abwesenheitsdetektion per Haustürschloss, zentrales Programm zur Steuerung von Beschattungsgeräten zBSP.

Antworten

Zurück zu „Softwareentwicklung für die HomeMatic CCU“