Getccusysvar und Warte Aufruf

Programmierung der HomeMatic CCU mittels contronics homeputer CL

Moderator: Co-Administratoren

Antworten
HmTec
Beiträge: 25
Registriert: 08.09.2014, 18:06
Danksagung erhalten: 1 Mal

Getccusysvar und Warte Aufruf

Beitrag von HmTec » 13.12.2017, 13:54

Hallo,

im Winter möchte ich gerne wissen, ob jemand vergessen hat, ein Fenster zu schliessen.
Die Fenster werden mit einem optischen Fensterkontakt überwacht. Beim Öffnen eines Fensters setze ich im verbunden Markro im ersten Durchlauf mit der Funktion Warte() eine Zeitdauer und nachdem diese abgelaufen ist erfolgt eine Alarmierung. Wird das Fenster vor Ablauf der Wartezeit geschlossen, bricht die erneute (zweite) Ausführung des Makros die Alarmierung automatisch ab.

Seit einiger Zeit "zickt" die Funktionalität jedoch. Da ich die Alarmierung nur aktiviert habe, wenn die Außentemperatur tief und die Heizung eingeschaltet ist, kann ich nicht mehr genau sagen, seit welchem Upgrade (CCU oder HPCL) sich da etwas geändert hat.

Bei der Analyse ist mir jedoch aufgefallen, dass beim zweiten Durchlauf des Makros, in dem ja eigentlich auch die Funktion Warte() abbrechen soll, ein Getccusysvar-Aufruf erst durchläuft, wenn die Wartezeit der Wartefunktion abgelaufen ist.

Nachfolgend ein vereinfachtes Beispiel, welches ich zum Testen an eine Virtuelle Taste der CCU gekoppelt habe.
In dem Beispiel wird der Status einer Variablen der CCU gelesen und dann soll zwei Minuten gewartet werden.
Ein erneuter Aufruf des Makros sollte das Warten abbrechen. De facto bleibt das Makro im zweiten Aufruf jedoch vor dem Get stehen, bis die zwei Minuten Wartezeit abgelaufen ist.

Code: Alles auswählen

//! ============================================================
//! OBJEKT CCU_FB_10
//! ============================================================
//! OBJEKT-TYP              : Taster2
//! BEZEICHNUNG             : CCU Fernbedienung 10
//! STARTWERT               :
//! ------------------------------------------------------------
//! AUSFÜHRUNGSINTERVALL    : nein
//! AUSFÜHRUNG BEI EINGABE  : nein
//! AUSFÜHRUNG BEI EMPFANG  : ja
//! AUSFÜHRUNG BEI ÄNDERUNG : nein
//! ------------------------------------------------------------
//! KONF.:xxxxxxxxxxxxxxxxxxxxxx
//!
//! ============================================================
//! VARIABLENDEFINITIONEN
//! ============================================================
//! NAME                TYP                 STARTWERT
//! ------------------------------------------------------------
//! Lokal_Status        Zeichen             Start
//! Lokal_Count         Zahl                0


// Funktion: Test Abbruch Warte()
//
// Letzte Änderung: 13.12.2017
//

Lokal_Status:="Start"
Lokal_Count:=Lokal_Count+1

Lokal_Status:="vorGet"
GETCCUSYSVAR("CCUReset",Global.CCUReset,"127.0.0.1")
Lokal_Status:="NachGet"

Wenn Global.Warten = "Warten" Dann
	Global.Warten:="Weiter"
	Lokal_Status:="Warten"
	WARTE ("00:02:00")
	Lokal_Status:="Warten Fertig"

SONST
	Global.Warten:="Warten"
	Lokal_Status:="Warten abgebrochen"
ENDEWENN

Ich verwende auf der CCU2 die Firmware 2.29.23 zusammen mit HPCL 3.19 Version 170908.
Auf dem PC habe ich HPCL 4.0 Version 171115 installiert.

Es wäre schön, wenn jemand das Codebeispiel nachvollziehen könnte.
Wenn es ein Bug sein sollte, würde ich diesen gerne an Contronics melden.
Vielleicht habe ich aber auch einen Denkfehler gemacht, der nur zufällig eine Zeit lang funktioniert hat.

Vielen Dank für Euer Feedback.

Stefan

Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 34 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von Familienvater » 13.12.2017, 14:05

Hi.

so sehr ich mich auch bemühe, ich verstehe komplett den Sinn nicht, außer die Aufgabe war, "warten" in allen Variantionen möglichst oft in unverständlichem Code zu platzieren, und das über mehrere Module.

Grundsätzlich:
Systemvariablen in HPCL zu benutzen ist Pfui, das geht normalerweise gut, aber das kann auch ganz schnell knirsch geben, vor allem wenn es zu oft/parallel passiert, und die Systemvariablen-Funktionen wurde in der Vergangenheit öfters mal angepasst, von daher ist nicht auszuschließen, das es da vielleicht mal wieder Probleme gibt.

Der Familienvater

HmTec
Beiträge: 25
Registriert: 08.09.2014, 18:06
Danksagung erhalten: 1 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von HmTec » 13.12.2017, 14:33

Hallo Familienvater,

in meiner aktiven Anwendung soll ein dauerhaft offen stehendes Fenster erkannt werden. Die Alarmierung soll nur erfolgen, wenn es wirklich kalt ist (Aussentemperatur unter 14 Grad ist und wir in der Heizperiode sind, d.h. die Fussbodenheizung im Haus läuft.) Die Alarmierung soll nach 15 Minuten mittels optischer Warnmeldung in der Diele erfolgen.
Da mein realer Code etwas länger ist, habe ich versucht ein Beispiel zu finden, das das Problem radikal verkürzt darstellt.

In allen meinen Makros frage ich zunächst den Status der CCU ab, da ich nicht möchte, das die Makros während eines Resets auslösen.
(Das ist hier im Forum so auch mehrfach beschrieben. )

Das von mir beigestellte Beispiel hat keine sinnvolle Funktionalität außer der, zu testen, ob das GETCCUSYSVAR beim zweiten Aufruf des Makros hängen bleibt, bis die Wartezeit des Warte-Funktion abgelaufen ist.

In der bei mir aktiven Funktionalität folgt dort, wo "Warten Fertig" steht, die Alarmierung. Im "Sonst"-Zweig wird nachts der Rolladen wieder heruntergefahren.

Es wäre schön, wenn Du Dir das Codebeispiel anschauen könntest.
Es geht nur um die Frage, ob das GETCCUSYSVAR hängen bleibt, wenn das Makro das zweite Mal aufgerufen wird. (Bei mir im realen Beispiel, wenn das Fenster nach z.B. 10 Minuten geschlossen wird und die Alarmierung, die nach der Warte-Funktion codiert ist, abgebrochen werden soll).

Du bist hier wegen deiner guten Anmerkungen bekannt,
Ich habe im Vergleich noch nicht soviel Erfahrungen. Vielleicht ist mein Codeschnipsel falsch gewählt, aber ich wollte nicht einfach mein langes Makro posten und habe versucht zu vereinfachen.

toby_cgn
Beiträge: 157
Registriert: 15.10.2012, 21:40

Re: Getccusysvar und Warte Aufruf

Beitrag von toby_cgn » 13.12.2017, 15:52

HmTec hat geschrieben:In allen meinen Makros frage ich zunächst den Status der CCU ab, da ich nicht möchte, das die Makros während eines Resets auslösen.
(Das ist hier im Forum so auch mehrfach beschrieben. )
Öhm, mal jetzt ganz blöd gefragt: wie oft resettest Du denn die CCU? Also bei mir kommt das höchstens alle paar Monate mal vor und dann wähle ich den Zeitpunkt so, dass ich absehen kann, dass es keine Komplikationen geben sollte.
Das ist meiner Meinung nach jetzt keine alltägliche Handlung, die eine Abfrage in JEDEM Makro benötigt, denn wie Familienvater schon schrub, wurde hier im (HPCL-) Forum auch schon mehrfach beschrieben, dass die CCU-Systemvariablenabfrage in HPCL mit äußester Vorsicht zu genießen ist. Wenn Du das unbedingt haben willst, würde ich eher in HPCL einen Schalter "CCUReset" anlegen, den Du über eine virtuelle Taste nur bei wirklicher Zustandsänderung entweder ein- oder ausschalten und dann in allen Makros abfragen kannst. Das wäre meines Erachtens sauberer, als der inflationäre Gebrauch von GETCCUSYSVAR, weil Du damit im HPCL-Universum bleibst.
Aber das ist nur meine Meinung und vielleicht liege ich ja auch komplett falsch damit... ;)

Gruß
Toby

Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 34 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von Familienvater » 13.12.2017, 16:17

Hi,

also, fangen wir ganz langsam und vorne an:
Auf deiner CCU2? läuft HPCL bzw. die ExecEngine, richtig? (Muss ja, hast ja die Version 3.19...)

Das ganze "Reboot-Geraffel" braucht es nur in der WebUI, wenn die CCU gerade neu startet, läuft noch kein HPCL, und wenn HPCL dann startet, und je nach dem, wie es konfiguriert ist, dann werden vielleicht auch alle Geräte durch die ExecEngine abgefragt, und dann kann es wirklich vorkommen, das Objekte, die auf Empfang oder Änderung getriggert sind, auslösen.

Toby hat das auch schon angesprochen, meine CCU2 lief schon 370 Tage am Stück durch, Neustarts mache ich normalerweise nur wegen Firmwareupdates, allerdings aktualisiere ich die Homeputer-Zusatzsoftware auf der Zentrale "manuell", dann geht es ohne Neustart der Zentrale.

Ich knalle Dir jetzt einfach mal "unkommentiert" mein Code für einen Drehgriff rein, der im Prinzip genau das macht, was Du willst (es ist aber auch noch ein Teil Rolladensteuerung mit drin), außer das die Heizperiodenprüfung fehlt. Wenn Du Englisch kannst, verstehst Du ihn, und kannst evtl. auch auf die deutschen Befehle kommen, Falls Du dich komplett verlierst, es geht bei "Warnung:" los..., mail. hat mit Email zu tun, syslog. ist mein Textlogger, m_SendPushover. hat mit dem Versenden von Pushover zu tun,

Code: Alles auswählen

//! ============================================================
//! OBJEKT DG_Fenster_Gaestezimmer
//! ============================================================
//! OBJEKT-TYP              : Fenstergriff
//! BEZEICHNUNG             : DG_Fenster_Gaestezimmer
//! STARTWERT               :
//! ------------------------------------------------------------
//! AUSFÜHRUNGSINTERVALL    : nein
//! AUSFÜHRUNG BEI EINGABE  : nein
//! AUSFÜHRUNG BEI EMPFANG  : ja
//! AUSFÜHRUNG BEI ÄNDERUNG : nein
//! ------------------------------------------------------------
//! KONF.:ALLV=0/MAV=3
//!
//! ============================================================
//! VARIABLENDEFINITIONEN
//! ============================================================
//! NAME                TYP                 STARTWERT
//! ------------------------------------------------------------
//! strDelayed          Zeichen
//! drgAlterStatus      Fenstergriff
//! strSelfMove         Zeichen
//! zeitTemp            Zeit
//! lngTimedOut         Zahl                0
//! zeitLastPing        Zeit
//! zeitTimeOutStart    Zeit
//! arrLastEvents       Zeichen             0<<
//! zeitLastBatterie    Zeit
//! strButtonPos        Zeichen
//! strLocation         Zeichen
//! strSide             Zeichen
//! lngHygBeiOpen       Zahl                0
//! sngTempBeiOpen      Zahl                0,0
//! strPushDevices      Zeichen


if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
  // ins Syslog schreiben
  syslog.optNoWrite := 1
  syslog.strMessage := "DG_Fenster_Gaestezimmer alter Zustand -" +drgAlterStatus+"-, neuer Zustand -"+DG_Fenster_Gaestezimmer+"-"
  syslog.strMessage := syslog.strMessage + ", Delayed -"+strDelayed+"-"
  syslog.strMessage := syslog.strMessage + ", SelfMove -"+strSelfMove+"-"
  syslog.strMessage := syslog.strMessage + ", RS_OG_Gaeste -"+RS_OG_Gaeste+"-"
  syslog.strMessage := syslog.strMessage + ", vRS_OG_Gaeste.zeitWartetBis -"+vRS_OG_Gaeste.zeitWartetBis+"-"
  syslog.strMessage := syslog.strMessage + ", RS_OG_Gaeste.strStatus -"+RS_OG_Gaeste.strStatus+"-"
  syslog.strMessage := syslog.strMessage + ", RS_OG_Gaeste.lngInhibit -"+RS_OG_Gaeste.lngInhibit+"-"
  call syslog
endif

// lngTimedOut wird auf 1 gesetzt, wenn eine Meldung des Sensors ausbleibt und dies vom System erkannt wird
// Dies wird normalerweise erst nach ca. 24h vom System erkannt
if lngTimedOut<>0 then
  lngTimedOut := 0

  // ins Syslog schreiben
  syslog.strMessage := "DG_Fenster_Gaestezimmer wieder da nach " + stoppuhr(zeitLastPing) + ", letzte Meldung war am " + zeitLastPing
  call syslog

  // eMail versenden
  mail.strSubject := "DG_Fenster_Gaestezimmer wieder da nach " + stoppuhr(zeitLastPing)
  mail.strTo      := settings.Email
  mail.strMessage := "DG_Fenster_Gaestezimmer wieder da nach " + stoppuhr(zeitLastPing)
  mail.strMessage := mail.strMessage + "<<Letzte Meldung war am: " + zeitLastPing
  mail.strMessage := mail.strMessage + "<<TimeOut wurde erkannt: " + zeitTimeOutStart
  mail.strMessage := mail.strMessage + "<<Letzter Status vor Timeout: " + drgAlterStatus
  mail.strMessage := mail.strMessage + "<<Jetzt empfangener Status  : " + DG_Fenster_Gaestezimmer
  mail.strMessage := mail.strMessage + "<<"
  mail.strMessage := mail.strMessage + "<<Delayed -"+strDelayed+"-"
  mail.strMessage := mail.strMessage + "<<SelfMove -"+strSelfMove+"-"
  mail.strMessage := mail.strMessage + "<<RS_OG_Gaeste -"+RS_OG_Gaeste+"-"
  mail.strMessage := mail.strMessage + "<<vRS_OG_Gaeste.zeitWartetBis -"+vRS_OG_Gaeste.zeitWartetBis+"-"
  mail.strMessage := mail.strMessage + "<<RS_OG_Gaeste.strStatus -"+RS_OG_Gaeste.strStatus+"-"
  call mail
endif

startwatch zeitLastPing

if DG_Fenster_Gaestezimmer = drgAlterStatus then
  return
endif

// Alten Wert speichern
drgAlterStatus:= DG_Fenster_Gaestezimmer

// homestatus-Display updaten, falls eine Button-Position vorgegeben wurde
if strButtonPos<>"" then
  call dm_DG_Fenster_Gaestezimmer
endif


// Wenn der gekoppelte Rolladen gerade verfährt (Status Moving) gibt das undefinierte Zustände, nix machen!!!
// Problem:
// Fenster wurde morgens zum Lüften geöffnet während der Rolladen gerade beim Hochfahren ist, nach dem Schließen der Türe fährt der Rolladen herunter...
// Mögliche Zustände:
// 1. Rolladen öffnet automatisch, Türe war geschlossen und wird geöffnet gekippt
// 2. Rolladen öffnet automatisch, Türe ist nicht geschlossen. Bei Offen müsste Rollo eigentlich schon oben sein, bei gekippt wäre möglich
// 3. Rolladen schließt automatisch, Türe war geschlossen und wird geöffnet gekippt
// 4. Rolladen schließt automatisch, Türe war nicht geschlossen. Eigentlich nicht möglich, soll die Steuerung gerade verhindern!
if RS_OG_Gaeste.strStatus = "Moving" then
  // springe an die Marke:
  goto Warnung
endif

// ///////////////////////////////////////////////////
// Historie der letzten Änderungen im Array aufheben

// Element dem Array zufügen, vorne anhängen
fArrAddElementFirst.strSource    := "DG_Fenster_Gaestezimmer"
fArrAddElementFirst.strDelimiter := "<<"
fArrAddElementFirst.strElemIn    := DG_Fenster_Gaestezimmer.ct +" "+DG_Fenster_Gaestezimmer
fArrAddElementFirst.strArrayIn   := arrLastEvents

// Funktion aufrufen
call fArrAddElementFirst

// Anzahl der Elemente im Array begrenzen
fArrLimitSizeTo.strSource    := "DG_Fenster_Gaestezimmer"
fArrLimitSizeTo.strDelimiter := "<<"
fArrLimitSizeTo.lngMaxSize   := 9
fArrLimitSizeTo.strArrayIn   := fArrAddElementFirst.strArrayReturn

// Funktion aufrufen
call fArrLimitSizeTo

// neues Array abholen
arrLastEvents := fArrLimitSizeTo.strArrayReturn

if (DG_Fenster_Gaestezimmer = "verriegelt" or DG_Fenster_Gaestezimmer = "gekippt") and RS_OG_Gaeste.lngInhibit > 0 then
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    Syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer: Drehgriff ist "+DG_Fenster_Gaestezimmer+", INHIBIT bei RS_OG_Gaeste gesetzt, lösche INHIBIT"
    call syslog
  endif
  RS_OG_Gaeste.lngInhibit := 2
  m_InhibitRS_OG_Gaeste.uhrDelay := "00:00:05"
  // Makro in die Ausführungsschlange stellen
  run m_InhibitRS_OG_Gaeste
endif

if DG_Fenster_Gaestezimmer = "offen" and RS_OG_Gaeste.lngInhibit = 0 then
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    Syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer: Drehgriff ist "+DG_Fenster_Gaestezimmer+", INHIBIT bei RS_OG_Gaeste ist nicht gesetzt, setze INHIBIT"
    call syslog
  endif
  RS_OG_Gaeste.lngInhibit := 3
  m_InhibitRS_OG_Gaeste.uhrDelay := "00:00:05"
  // Makro in die Ausführungsschlange stellen
  run m_InhibitRS_OG_Gaeste
endif

// ///////////////////////////////////////////////////
// Verhinderte Rolladenbewegungen nachholen
startwatch zeitTemp
// Hysterese-Zeit ausrechnen, es macht keinen Sinn, denn Rolladen 5 Min vor der automatischen Öffnung runterzufahren, damit er dann wieder geöffnet wird
zeitTemp := zeitTemp + "0:30:00"

// Türe ist jetzt gekippt, nachdem eine automatische Rolladenbewegung verhindert wurde, Rolladen auf dreiviertel fahren
// Nur wenn Rolladenbetriebsart für Runter ist <> Aus!
if DG_Fenster_Gaestezimmer = "gekippt" and strDelayed <> "" and swRBRRS_OG_Gaeste<>"Aus" then
  if vRS_OG_Gaeste.zeitWartetBis < zeitTemp then
    if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
      // ins Syslog schreiben
      Syslog.optNoWrite := 1
      syslog.strMessage := "DG_Fenster_Gaestezimmer hat Delayed -"+strDelayed+"- für RS_OG_Gaeste gesetzt, fahre jetzt den Rolladen nach dreiviertel"
      call syslog
    endif

    RS_OG_Gaeste := "dreiviertel"
    // Keine Änderung bei Selfmove oder Delayed
    return
  else
    if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
      // ins Syslog schreiben
      Syslog.optNoWrite := 1
      syslog.strMessage := "DG_Fenster_Gaestezimmer hat Delayed -"+strDelayed+"- für RS_OG_Gaeste gesetzt, mache aber nichts, zeitWartetBis ist "+vRS_OG_Gaeste.zeitWartetBis
      call syslog
    endif
    strDelayed := ""
    return
  endif
endif

// Türe ist jetzt verriegelt, nachdem eine automatische Rolladenbewegung verhindert wurde, Rolladenbewegung nachholen
if DG_Fenster_Gaestezimmer = "verriegelt" and strDelayed <> "" and swRBRRS_OG_Gaeste<>"Aus" then
  if vRS_OG_Gaeste.zeitWartetBis < zeitTemp then
    if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
      // ins Syslog schreiben
      Syslog.optNoWrite := 1
      syslog.strMessage := "DG_Fenster_Gaestezimmer hat Delayed für RS_OG_Gaeste gesetzt, fahre jetzt den Rolladen nach "+strDelayed
      call syslog
    endif

    RS_OG_Gaeste := strDelayed
  else
    if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
      // ins Syslog schreiben
      Syslog.optNoWrite := 1
      syslog.strMessage := "DG_Fenster_Gaestezimmer hat Delayed -"+strDelayed+"- für RS_OG_Gaeste gesetzt, mache aber nichts, zeitWartetBis ist "+vRS_OG_Gaeste.zeitWartetBis
      call syslog
    endif
  endif

  strDelayed := ""
  strSelfMove := ""
  // springe an die Marke:
  goto Warnung
endif

// Ende Delayed-Fälle

// ///////////////////////////////////////////////////
// Spontane Rolladenbewegungen durch den Drehgriff
// Nur wenn Rolladenbetriebsart für Runter ist <> Aus!
if DG_Fenster_Gaestezimmer = "verriegelt" und strSelfMove <> "" und swRBRRS_OG_Gaeste <> "Aus" then
  startwatch zeitTemp
  if zeitTemp < vRS_OG_Gaeste.zeitWartetBis then
    // Rolladen wartet auf eine Bewegung

    // Hysterese-Zeit ausrechnen, es macht keinen Sinn, denn Rolladen 5 Min vor der automatischen Öffnung runterzufahren, damit er dann wieder geöffnet wird
    zeitTemp := zeitTemp + "0:30:00"
    if vRS_OG_Gaeste.zeitWartetBis < zeitTemp  then

      if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
        // ins Syslog schreiben
        Syslog.optNoWrite := 1
        syslog.strMessage := "DG_Fenster_Gaestezimmer hat SelfMove für RS_OG_Gaeste gesetzt, fahre jetzt aber wegen Hysterese den Rolladen nicht, lösche SelfMove und Delayed!"
        call syslog
      endif

      strDelayed := ""
      strSelfMove := ""
      // springe an die Marke:
      goto Warnung
    endif
  endif

  if RS_OG_Gaeste.lngDebug > 0 then
    // ins Syslog schreiben
    syslog.strMessage := "DG_Fenster_Gaestezimmer hat SelfMove für RS_OG_Gaeste gesetzt, fahre jetzt den Rolladen wieder nach "+strSelfMove
    call syslog
  endif

  RS_OG_Gaeste := strSelfMove
  strSelfMove := ""
  // springe an die Marke:
  goto Warnung
endif

if DG_Fenster_Gaestezimmer = "gekippt" und RS_OG_Gaeste = "oben" und strSelfMove = "unten" und swRBRRS_OG_Gaeste<>"Aus" then
  // Sollte nur vorkommen, wenn Rollo vom Drehgriff hochfahren wurde und jetzt auf gekippt steht
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer wurde gekippt, fahre jetzt RS_OG_Gaeste von oben nach dreiviertel"
    call syslog
  endif

  RS_OG_Gaeste := "dreiviertel"
  // SelfMove stehen lassen
  // springe an die Marke:
  goto Warnung
endif

if DG_Fenster_Gaestezimmer = "gekippt" und RS_OG_Gaeste = "unten" und swRBHRS_OG_Gaeste<>"Aus"  then
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer wurde gekippt, fahre jetzt RS_OG_Gaeste von unten nach dreiviertel"
    call syslog
  endif

  strSelfMove := "unten"
  RS_OG_Gaeste := "dreiviertel"
  // springe an die Marke:
  goto Warnung
endif

// Egal wie Selfmove/Delayed steht, wenn der Rollo auf dreiviertel steht und die Türe wird geöffnet, Rollo hoch!
// wenn DG_Fenster_Gaestezimmer = "offen" und RS_OG_Gaeste = "dreiviertel" und strSelfMove = "unten" then
if DG_Fenster_Gaestezimmer = "offen" und RS_OG_Gaeste = "dreiviertel" und swRBHRS_OG_Gaeste<>"Aus" then
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer wurde geöffnet, fahre jetzt RS_OG_Gaeste von dreiviertel nach oben"
    call syslog
  endif

  RS_OG_Gaeste := "oben"
  // SelfMove/delayed stehen lassen
  // springe an die Marke:
  goto Warnung
endif

//wenn DG_Fenster_Gaestezimmer = "offen" und RS_OG_Gaeste = "unten" then
if DG_Fenster_Gaestezimmer = "offen" und RS_OG_Gaeste = "unten" und swRBHRS_OG_Gaeste<>"Aus" then
  if RS_OG_Gaeste.lngDebug > 0 or comerror(RS_OG_Gaeste) then
    // ins Syslog schreiben
    syslog.optNoWrite := 1
    syslog.strMessage := "DG_Fenster_Gaestezimmer wurde geöffnet, fahre jetzt RS_OG_Gaeste von unten nach oben"
    call syslog
  endif

  strSelfMove := "unten"
  RS_OG_Gaeste := "oben"

  // springe an die Marke:
  goto Warnung
endif

Warnung:


if DG_Fenster_Gaestezimmer = "offen" and strlen(strPushDevices)>1 then

  // -> ist im Master-Makro... Warnung:
  if TS_Norden <= 10 then
    if stopwatch(zeitLastPing)<10 then
      sngTempBeiOpen := WT_Gaestezimmer.Temperatur
      lngHygBeiOpen := WT_Gaestezimmer.Luftfeuchtigkeit
    endif

    wait "00:10:00"

    temp.lngVar1 := stopwatch(zeitLastPing)
    temp.lngVar1 := temp.lngVar1 / 60
    // Sprache auf einem HomeStatus-Display ausgeben
    dm_Say.strDisplays := "3,5"
    dm_Say.strText := "Fenster im Gästezimmer steht seit " + temp.lngVar1 + " Minuten offen. "
    dm_Say.strText := dm_Say.strText  + "Zeit, das Ding langsam wieder zu schließen. "
    temp.strTemp := replace(TS_Norden,".",",")
    dm_Say.strText := dm_Say.strText  + "Im Norden sind es zur Zeit " + temp.strTemp + " Grad Aussentemperatur. "
    temp.sngVar10 := sngTempBeiOpen - WT_Gaestezimmer.Temperatur
    if temp.sngVar10 > 0 then
      dm_Say.strText := dm_Say.strText  + "Die Raumtemperatur ist um " + temp.sngVar10 + " Grad auf "+WT_Gaestezimmer.Temperatur+" Grad gesunken. "
    else
      if temp.sngVar10 < 0 then
        temp.sngVar10 := temp.sngVar10 * -1
        temp.strTemp := replace(temp.sngVar10,".",",")
        dm_Say.strText := dm_Say.strText  + "Die Raumtemperatur ist um " + temp.strTemp + " Grad auf "+replace(WT_Gaestezimmer.Temperatur,".",",")+" Grad gestiegen. "
      endif
    endif
    temp.lngVar1  := lngHygBeiOpen - WT_Gaestezimmer.Luftfeuchtigkeit
    if temp.lngVar1 > 0 then
      dm_Say.strText := dm_Say.strText  + "Die relative Luftfeuchtigkeit ist um " + temp.lngVar1 + " Prozent auf " + WT_Gaestezimmer.Luftfeuchtigkeit + " Prozent gesunken. "
    else
      if temp.lngVar1 > 0 then
        temp.lngVar1 := temp.lngVar1 * -1
      dm_Say.strText := dm_Say.strText  + "Die relative Luftfeuchtigkeit ist um " + temp.lngVar1 + " Prozent auf " + WT_Gaestezimmer.Luftfeuchtigkeit + " Prozent gestiegen. "
      endif
    endif

    // In die Ausführungswarteschlange stellen
    run dm_Say

    // Pushovernachricht versenden
    m_SendPushover.strAppToken := const.AppTokenInfo
    m_SendPushover.strUserToken := const.UserTokenCS
    temp.lngVar1 := stopwatch(zeitLastPing)
    temp.lngVar1 := temp.lngVar1 / 60
    m_SendPushover.strTitle := "Fenster im Gästezimmer steht seit " + temp.lngVar1 + " Minuten offen."
    m_SendPushover.strMessage := "Zeit, das Ding langsam wieder zu zumachen..."
    temp.strTemp := replace(TS_Norden,".",",")
    m_SendPushover.strMessage := m_SendPushover.strMessage + "<<Im Norden sind es zur Zeit " + temp.strTemp + " Grad Aussentemperatur..."

    temp.sngVar10 := sngTempBeiOpen - WT_Gaestezimmer.Temperatur
    if temp.sngVar10 > 0 then
      m_SendPushover.strMessage := m_SendPushover.strMessage  + "<<Die Raumtemperatur ist um " + replace(temp.sngVar10,".",",") + " Grad auf "+replace(WT_Gaestezimmer.Temperatur,".",",")+" Grad gesunken. "
    else
      if temp.sngVar10 < 0 then
        temp.sngVar10 := temp.sngVar10 * -1
        m_SendPushover.strMessage := m_SendPushover.strMessage  + "<<Die Raumtemperatur ist um " + replace(temp.sngVar10,".",",") + " Grad auf "+replace(WT_Gaestezimmer.Temperatur,".",",")+" Grad gestiegen. "
      endif
    endif
    temp.lngVar1  := lngHygBeiOpen - WT_Gaestezimmer.Luftfeuchtigkeit
    if temp.lngVar1 > 0 then
      m_SendPushover.strMessage := m_SendPushover.strMessage  + "<<Die relative Luftfeuchtigkeit ist um " + temp.lngVar1 + " Prozent auf " + WT_Gaestezimmer.Luftfeuchtigkeit + " Prozent gesunken. "
    else
      if temp.lngVar1 > 0 then
        temp.lngVar1 := temp.lngVar1 * -1
        m_SendPushover.strMessage := m_SendPushover.strMessage  + "<<Die relative Luftfeuchtigkeit ist um " + temp.lngVar1 + " Prozent auf " + WT_Gaestezimmer.Luftfeuchtigkeit + " Prozent gestiegen. "
      endif
    endif

    if temp.lngVar1 > 30 or (TS_Norden <=0 and temp.lngVar1 > 15) then
      m_SendPushover.lngPriority := 2
      // Nur für Priority 2
      m_SendPushover.lngExpire := 90
      m_SendPushover.lngRetry := 30
      // Sounds: bike, bugle (+), cashregister, classical, cosmic, falling, gamelan, incoming, intermission, magic, mechanical, pianobar, siren (+), spacealarm, tugboat (+)
      // Long-Sound: alien, climb, persistent (++), echo, updown (++)
      // Silent: none
      m_SendPushover.strDevice := strPushDevices
      m_SendPushover.strSound := "persistent"
    else
      m_SendPushover.lngPriority := 1
      // Nur für Priority 2
      //  m_SendPushover.lngExpire := 900
      //  m_SendPushover.lngRetry := 30
      // Sounds: bike, bugle (+), cashregister, classical, cosmic, falling, gamelan, incoming, intermission, magic, mechanical, pianobar, siren (+), spacealarm, tugboat (+)
      // Long-Sound: alien, climb, persistent (++), echo, updown (++)
      // Silent: none
      m_SendPushover.strDevice := "galaxynexus"
      m_SendPushover.strSound := "cashregister"
    endif
    call m_SendPushover
    // springe an die Marke:
    goto Warnung
  else
    // Falls es jetzt noch nicht zu kalt ist, vielleicht wird es das ja später noch...
    wait "00:10:00"
    goto Warnung
  endif
endif

Ende:
Der Familienvater

HmTec
Beiträge: 25
Registriert: 08.09.2014, 18:06
Danksagung erhalten: 1 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von HmTec » 14.12.2017, 10:08

Hallo Familienvater,

vielen Dank für Deinen Code-Beispiel.

Ich habe einiges aus Deinem Beispiel gelernt. Da ist eine Menge an grundsätzlicher Konzeption und Feinarbeit zu sehen. Ich wünschte mir mehr solche Beispiele und auch Anregungen zur Grundkonzeption. Vielleicht kannst Du mir hierzu ein paar Tips oder Hinweise geben, wo ich diese und die erforderlichen Hintergrundinformationen finden kann. Ich versuche immer mal wieder, die Struktur zu verbessern, aber wie bei vielen ist da auch eine ganze Menge an "gewachsene" Dingen entstanden und oft fehlt es an der Zeit, alles grundsätzlich neu zu machen.... Aber das ist eine andere Diskussion.

Soweit ich Deine Logik verstanden habe, unterscheidet sich diese nicht komplett von der meinen. Vereinfacht ausgedrückt wird auch bei Dir im Abschnitt "Warnungen" "10 Minuten" gewartet, dann erfolgt die Alarmierung ggf. wird wieder gewartet und alarmiert, wenn niemand reagiert. Wird das Fenster vor Ablauf der Wartezeit geschlossen, wir die laufende Instanz des Makros abgebrochen und eine neue gestartet.
Die gleiche Grundlogik verwende ich auch. Aber in meinem ersten Post ging es mir auch nicht um diese grundsätzliche Logik offene Fenster zu erkennen.

Ich habe aus meinem Programmierung die blockierten GETCCUSYSVAR Aufrufe herausgenommen, danach läuft alles wie gewohnt und der erforderliche WAF bei meiner Frau ist wieder hergestellt.

Im Grunde nach ist das, was ich zu Anfang gepostet habe, Wasser auf Deine Mühle "Systemvariablen in HPCL zu benutzen ist Pfui".

Nun aber noch einmal zu meinem ursprünglichen Anliegen:
Laut Dokumentation von HPCL wird eine laufende Instanz eines Markros abgebrochen, wenn das Makro erneut ausgelöst wird. Ergo müssten alle laufenden Anweisungen abgebrochen werden.
In meinem Fall wird die Wait-Function jedoch nicht vollständig abgeräumt. Vermutlich nutzt die Wait-Funciton irgendwo etwas wie eine Semaphore ( ggf auch auf einen anderen Ebene im System), die beim Abbruch nicht sofort abgeräumt wird. Gibt es in der neuen Instanz des Makro nun Systemaufrufe GETCCUSYS oder SETCCUSYS, so sind diese blockiert, bis die ursprüngliche Wartezeit abgelaufen ist.

Da dies in frühren Versionen definitiv anders war, wollte ich ursprünglich nur wissen, ob jemand das Problem nachvollziehen kann. Ob es ein Problem von HPCL oder der CCU Firmware ist, kann ich gar nicht sagen.
Wenn es sich nicht um ein lokalen Fehler in meiner Installation handelt, könnte es wichtig sein, dieses neue Verhalten zu dokumentieren, damit andere nicht in die gleiche Falle tappen.
Ich hatte naiv gedacht, jemand hier im Forum könnte sich meinen kleinen Code kopieren, an einen Button der CCU koppeln und ausprobieren, wie dieser sich bei ihm verhält.
Der Code ist natürlich funktionslos, kann aber kinderleicht mit den SPG-Tools debuggt werden.

Also, wenn es kein lokaler Fehler meiner Instanz ist, wäre es meines Erachtens wichtig, das Zusammenspiel der Systemaufrufe dokumentieren (Is a feature) oder zu korrigieren (It a bug).

Grüße

Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 34 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von Familienvater » 14.12.2017, 10:55

Hi,

ich bitte um Verständnis, das ich nicht einfach so zum Testen Code in mein Produktivsystem packe :-), mein Projekt ist auf lange Laufzeiten ausgelegt, und ich habe nur eine Lizenz für HPCL, für einen Betrieb auf dem Testsystem bräuchte ich entweder eine 2. Lizenz, oder ich würde die Seriennummer des Funkmoduls "verbrennen", weil ich damit den einmaligen kostenlosen Testzeitraum starte. Ich werde aber beim nächsten Update meines Projekts mal so einen Testfall mit reinbauen, um es auch bei mir mal zu prüfen, was passiert.

Ich arbeite sehr viel mit Warte-Anweisungen, die "gewollt" abgebrochen werden sollen, z.B. am Ende eines Makros warte ich einfach 2h, laufen die 2h ab, dann schicke ich mir eine Mail, das eine Kommunikationsstörung aufgetreten ist, weil sonst wäre das Warte ja durch einen erneuten Empfang abgebrochen worden. Es gibt nur wenige Befehle in HPCL, die eine Ausführung des Makros bis zur Abarbeitung des Befehls "anhalten", das ist GetSite, Get/SetCcuSysvar (hoffe nix vergessen) und auch ein Sprung nach oben im Code führt dazu, das erstmal andere (wartende Dinge/Events) erledigt werden könnten. Und eigentlich läuft das ganze bei mir rund...

Zur Struktur:
Ja, ich nutze homeputer-"Derivate" seit 2004?, und seit dem habe ich einiges über Fehler gelernt, die man machen kann, und so habe ich nach ca. 10 Jahren Erfahrung mit dem Start in HPCL gewisse Ideen gehabt, was ich besser machen könnte (weil das vorher im gewachsenen Kuddelmuddel suboptimal war). Außerdem hänge ich beruflich meistens 8h am Tag programmierend in anderen Programmiersprachen vor dem Computer, so das ich auch von daher vielleicht eine gewisse Vorschädigung besitze. Und bei der Größe meines HPCL-Projekts geht es nur noch sauber strukturiert, um Dich ein wenig zu schockieren, das geben die SPG-Tools aktuell aus:

Code: Alles auswählen

 Informationen zum Homeputer-Projekt:
 ------------------------------------
   Anzahl der Ansichten: 17
   Anzahl der Objekte:   885 (davon 802 mit Textdatei)
   Gesamtzahl programmierter Makrozeilen: 87013
   Gesamtzahl Variablendefinitionen:      3315
   Anzahl Hardwaremodule:                 146
Zieh bei den Codezeilen 50% ab, für Kommentare etc, dann isses aber immer noch riesengroß.

Ich tue mir massiv schwer, mein "Framework" zu veröffentlichen, weil man dazu erst ein Buch über die dahinterstehende Philosophie schreiben müsste, und wie man damit umzugehen hat, und meine Umgebung ist ggf. wesentlich komplexer, weil ich z.B. anstelle des USB-Sticks/SD-Karte an dieser Stelle im Dateisystem auf der Zentrale einen NFS-Mount habe, womit ich mir mit viel Schreibzugriffen keine Flashspeicher kaputtschreibe, und netter Nebeneffekt, auch von meinem PC direkt mit GBit auf eine History-Datei mit 300 MB in sekundenschnelle zugreifen kann.

Der Familienvater

Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 34 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von Familienvater » 15.12.2017, 01:19

Hi,

habe Testcases in mein Projekt eingebaut, da ist wirklich ein Problem, auch mit Getsite ist es so (wahrscheinlich auch das gleiche mit SetCcuSysVar und sendesms, falls das jemand benutzt), das ein "abgebrochenes" Warte seine Restwartezeit dort verbummelt.
RK hat hier zumindest schon mal kurz mitgelesen gehabt, aber wahrscheinlich noch keinen Bug draus gemacht, ich schreib Ihm noch mal eine Mail mit Beispielcode zum Nachvollziehen.

Der Familienvater

Familienvater
Beiträge: 7151
Registriert: 31.12.2006, 15:18
System: Alternative CCU (auf Basis OCCU)
Wohnort: Rhein-Main
Danksagung erhalten: 34 Mal

Re: Getccusysvar und Warte Aufruf

Beitrag von Familienvater » 22.12.2017, 19:21

Hi,

hatte eine Rückmeldung von RK bekommen, das er es sich angeschaut hat, aber "auf die Schnelle nicht lösen kann", das Thema ist wohl komplex, er hat es auf die ToDo-Liste gesetzt, also erstmal keine schnelle grundsätzliche Lösung.

Beim Testen habe ich einen Workaround ausprobiert: Einfach ein warte("00:00:00") vor eine "kritische" Anweisung mit Get/SetCCUSysVar, GetSite oder SendeSMS etzen, damit wird intern ggf. der Zeitstempel vorher korrigiert, und die "Hintergrundanweisung" wartet am Ende nicht unnötig.
Da ich spontan immer mal einzelne Ausfälle bei einer Aktion aus einer Zeittabellen habe, könnte das auch mit dem Problem zusammenhängen, auch weil danach im Makro teilweise Warte-Anweisungen mit Wartezeit nicht zu einer Wartezeit geführt haben, auch da habe testweise mal ein "überflüssiges" warte("00:00:00") eingebaut, da kann ich vielleicht in zwei Monaten sagen, das hat was gebracht, es gab keine Probleme damit mehr, aber der Zeittabellen-Fehler tritt bei mir auch nur selten auf (manchmal wochenlang gar nicht, manchmal an 2 Tagen hintereinander und dann wieder nicht, ohne das irgendwas neu gestartet/geändert wird).

Der Familienvater

Antworten

Zurück zu „homeputer CL“