Buffer bei IPS Shutdown sichern

Ich nutze einen Buffer zum Hochzählen einer Message-ID. Beim IPS Shutdown muss ich den Stand in eine Property sichern, damit ich beim Neustart nicht wieder bei Null anfange. Dazu hatte ich die Message KR_UNINIT registriert. Scheinbar wird die Message aber nicht verschickt, so das der letzte Stand nach dem Neustart nicht zur Verfügung steht.

Was ist der vorgesehene Weg innerhalb eines Moduls den Buffer zu sichern? Ich wollte eigentlich nicht permanent jede einzelne Änderung in die Property schreiben und auch nichts in ein zentrales Shutdown-Script frickeln.

Tommi

Du kannst dich nicht direkt auf UNINIT registrieren, sondern nur global auf KERNELMESSAGE
Siehe ähnliche Frage von dir und meine Antwort von hier:
Fragen zu RegisterMessage und MessageSink

Grundsätzlich funktioniert dies auch, aber leider kann IPS, wenn der Shutdown eingeleitet wird, keine Scripte und somit auch keine Methoden der PHP-Module mehr aufrufen :banghead:

Also aktuell keine funktionierende Lösung, leider.

Michael

PS: Ich füge das mal bei den Bugs hinzu.

Da bewegt sich bei mir auch nichts. Es findet sich im Logfile mal GAR keine KernelMessage.


     /**
     * Kernel Message  ID
     */
    const IPS_KERNELMESSAGE = 100;
    const KR_INIT = 10102;
    const KR_READY = 10103;
    const KR_UNINIT= 10104;	

//in create() und ApplyChanges():
$this->RegisterMessage(0, self::IPS_KERNELMESSAGE );

public function MessageSink($TimeStamp, $SenderID, $Message, $Data) {
     
        switch ($Message) {
               case self::IPS_KERNELMESSAGE:
                $kmsg=$Data[0];
                switch ($kmsg) {
                    case self::KR_READY:
                        IPS_LogMessage(__CLASS__,__FUNCTION__." KR_Ready ->register()");
                        $this->Register_All();
                        break;
                    case self::KR_UNINIT:
                        IPS_LogMessage(__CLASS__,__FUNCTION__." KR_UNINIT ->disconnect()");
                        $this->SaveIDs();
                        break;
                    default:
                        IPS_LogMessage(__CLASS__,__FUNCTION__." Kernelmessage unhahndled, ID".$kmsg);
                        break;
                }
            default:
                IPS_LogMessage(__CLASS__,__FUNCTION__." Unknown Message $Message");
                break;
        }
 }

Nehme jetzt eine Variable. finde ich zwar doof, geht aber.

BTW: Stehe gerade auf dem Schlauch: wie verhindere ich einen Loop, wenn ich innerhalb von ApplyChanges eine Funktion verwenden muss die eine Property ändert und die dann natürlich seinerseits mit ApplyChanges festschreiben will.

Tommi

10100 ist Kernelmessage (so aus dem Kopf)
Den Rest wenn ich am Rechner bin :slight_smile:
Michael

PS: Die Doku ist an der Stelle leider falsch, da der Offset von 10000 nicht berücksichtigt wurde.

Ich reisse das Zitat mal aus dem Zusammenhang, weil man das m.E. nicht so generell sagen kann:

Im Modul Event Control, das bei V3.4 zu den Kern Instanzen gehört, kann man doch ein „Herunterfahr-Skript“ definieren.
Ich habe dort jede Menge Skript-Aufrufe stehen (z.B. Benachrichtigung vom Raspi an den Hauptserver per JSON), die auch regelmäßig durchkommen, wenn z.B. Linux einen Shutdown einleitet.

Wenn ich unter Windows „den Dienst beenden“ will, hab ich eher das Problem. dass ich IPS irgendwann über den Windows Task-Manager beenden muß. Liegt bei mir vielleicht daran, dass ich „Langzeit-Skripts“ laufen habe, die sich erst nach einigen Minuten beenden.

Was ich sagen will: m.E. läßt IPS beim Shutdown jede Menge Zeit für noch laufende Skripte.

Viele Grüsse
Harald

Ich habe mir da mit einer zweiten Eigenschaft beholfen, diese setzte ich mit, damit ich im nächsten Durchlauf weiß dass dieses ApplyChanges quasi durch sich selbst aufgerufen wurde.
In deinem Fall würde ich aber erstmal auf eine IPS-Variable ausweichen.

Da hast du recht, nur genau das wollt tommi nicht nutzen und hier geht es auch auch primär um die PHP-Module.
Wie die genaue Logik beim Shutdown aussieht weiß nur paresy.

Dass das EventControl das Shutdown-Script noch vor dem finalisieren der ScriptEngine ausführt ist klar (gilt nicht nur für 3.4, sondern auch für 4.x).
Dann müssten eigentlich die Nachrichten an alle Registrierten PHP-Instanzen versendet werden und erst dann die ScriptEngine finalisiert werden.
Leider scheint dies aber aktuell so nicht der Fall zu sein, so dass die PHP-Instanzen gegen die Wand laufen…


14:19:08 | 00000 | WARNING | Kernel               | Service Shutdown requested!
14:19:08 | 00000 | MESSAGE | Kernel               | Deinitialisiere...
14:19:08 | 00000 | MESSAGE | ScriptEngine         | Waiting for all script threads to terminate...
14:19:08 | 00000 | MESSAGE | TimerPool            | Waiting for 8 timer threads to finish...
14:19:09 | 00000 | MESSAGE | DataServer           | Stoppe Server...
14:19:09 | 00000 | ERROR   | KernelMT             | InstanzManager: Fehler bei Instanz #45222 , Meldung IPS_KERNELMESSAGE: Scripts können nicht gestartet, sobald Abschaltung eingeleitet wurde
14:19:09 | 00000 | ERROR   | KernelMT             | InstanzManager: Fehler bei Instanz #31909 , Meldung IPS_KERNELMESSAGE: Scripts können nicht gestartet, sobald Abschaltung eingeleitet wurde
14:19:09 | 00000 | ERROR   | KernelMT             | InstanzManager: Fehler bei Instanz #46535 , Meldung IPS_KERNELMESSAGE: Scripts können nicht gestartet, sobald Abschaltung eingeleitet wurde

Michael

Bei mir zuckt sich auch nichts, wenn ich IPS_KERNELMESSAGE als 10100 definiere.

Das vorläufige Ergebnis der Aktion könnt Ihr Euch im Modul ansehen. So ganz glücklich bin ich damit noch nicht.

Tommi

:confused: Versteh’ ich jetzt aber auch nicht mehr…

Michael

Das ist in der Tat etwas doof für PHP Module. ABER: Ihr könnt auf die Message registrieren, welche auch das Event Control nutzt. Das ist folgender:


IPS_KERNELSHUTDOWN -> IPS_BASE + 2 -> 10002

Damit sollten auch schön die Skripte abgearbeitet werden. Alles danach arbeitet wie ihr schon gesagt hat keine Skipte mehr ab.

paresy

DANKE :smiley:

Hätte ich ja selber drauf kommen können… diese Nachrichten sind ja auch im Delphi-SDK vorhanden.
Dort ist aber IPS_KERNELSHUTDOWN = 10001 und 10002 als IPS_KERNELSTARTED gelistet :confused:

EDIT: Ein Schnellversuch eben hat noch nicht zum Erfolg geführt, aber eventuell ich ich auch gerade zu müde dafür :wink:
Michael

Also bei mir funktioniert auch Dies nicht… weitere Ideen?
Michael

Ich muss mal selber pushen… Jemand noch ein Idee ?

Zumal nicht nur der Shutdown, sondern auch das löschen (Destroy) ordentlich knallt.

IPS versucht dann noch den MessageSink auszuführen (Löschen von untergeordneten Variablen)-> Meldet aber gleichzeitig das die eigene Instanz nicht existiert :confused:
Der array_key_exists Fehler kommt daher, dass natürlich auch GetBuffer fehlschlägt.

04.01.2017 21:13:47*| ScriptEngine*| Ergebnis für Text (Länge: 0)
<br />
<b>Warning</b>:  Instanz #50224 existiert nicht in <b>C:\IP-Symcon\scripts\__ipsmodule.inc.php</b> on line <b>391</b><br />
<br />
<b>Warning</b>:  Instanz #50224 existiert nicht in <b>C:\IP-Symcon\scripts\__ipsmodule.inc.php</b> on line <b>260</b><br />
<br />
<b>Warning</b>:  Instanz #50224 existiert nicht in <b>C:\IP-Symcon\scripts\__ipsmodule.inc.php</b> on line <b>373</b><br />
<br />
<b>Warning</b>:  array_key_exists() expects parameter 2 to be array, boolean given in <b>C:\IP-Symcon\modules\HomematicExtended\Systemvariablen\module.php</b> on line <b>91</b><br />

Dann kommt auch noch mal der Destroy, welche mit den gleichen Fehler.
foreach Fehler kommt auch durch den fehlerhaften GetBuffer.


04.01.2017 21:13:47*| HMSystemVariable*| <br />
<b>Warning</b>:  Instanz #50224 existiert nicht in <b>C:\IP-Symcon\scripts\__ipsmodule.inc.php</b> on line <b>373</b><br />
<br />
<b>Warning</b>:  Invalid argument supplied for foreach() in <b>C:\IP-Symcon\modules\HomematicExtended\Systemvariablen\module.php</b> on line <b>60</b><br />

(Und ein rechtsklick auf diese Meldung bringt noch eine Fehlermeldung der Console)


Zugriffsverletzung bei Adresse 009AC5C1 in Modul 'ips_console.exe'. Lesen von Adresse 00000008.

Dann kommt endlich :

04.01.2017 21:13:47*| HMSystemVariable*| Entferne...

Öh… wie jetzt ? Ich dachte die war weiter ‚oben‘ schon gelöscht. Irgendwas ist da durcheinander.

Michael

Ab Version IP-Symcon 4.2:

Start = IPS_KERNELSTARTED = 10001
Beenden = IPS_KERNELSHUTDOWN = 10002

IPS_KERNELMESSAGE bitte nicht mehr verwenden.

paresy

muss das Thema nach oben pushen, nachdem ich es nicht gebacken bekomme.

Ich starte aus einem Modul einen externen Prozess, den ich beim Beenden des Symcon Dienstes wieder beenden möchte bzw es muss, weil sonst Symcon hängen bleibt:


  public function ApplyChanges()
  {

    $this->RegisterMessage(0, IPS_BASE);

$output = array();
$command = "cd ".__DIR__."/../js && nohup node main.js connect > /dev/null 2>&1 & echo $!";

exec($command, output);
$pid = output[0];

$this->SetBuffer($pid);

  public function MessageSink($TimeStamp, $SenderID, $Message, $Data)
  {

    $this->SendDebug("<Gateway|MessageSink:SenderID>", $SenderID, 0);
    $this->SendDebug("<Gateway|MessageSink:Message>", $Message, 0);
    $this->SendDebug("<Gateway|MessageSink:Data>", json_encode($Data), 0);

    switch ($Message) {
      case IPS_BASE:
        switch ($Data[0]) {
          case IPS_KERNELSTARTED:
            $this->SetBuffer("applyMode", 1);
            $this->ApplyChanges();
            break;

          case IPS_KERNELSHUTDOWN:
            $this->SendDebug("<Gateway|MessageSink:pid>", $this->GetBuffer("nodePID"), 0);
            exec("kill ".$this->GetBuffer("nodePID"));
            break;
        }
        break;
    }
  }

leider wird der Process nicht beendet :confused: Bin für jeden Tipp dankbar.
PS: habe nur die wesentlichen Code Teile zusammenkopiert

Du hast die falschen Nachrichten abonniert.
IPS_KERNELSHUTDOWN ist direkt eine Nachricht und nicht Data[0].

Keine Ahnung was dein externer Prozess macht, aber wäre es nicht besser das direkt in Symcon zu integrieren?
Michael

Danke, habe es gerade auch selbst bemerkt :banghead:

Einen Server Sent Events client direkt in Symcon / PHP zu realisieren ist sicherlich eine nette Herausforderung :D.
Ich habe derzeit leider die Zeit nicht und habe es daher in javascript umgesetzt.

Geht so, habe ich ja bei den Websockets auch umgesetzt :wink:
IPS stellt alle Mitteln zur Verfügung, man muss sie nur nutzen :smiley:
Michael

:smiley: würde es Dich dann nicht reizen ? :wink:
Leider unterstützt NEST (Stand Heute) keinen Websocket, sonst hätte ich auf dein Modul zurückgegriffen.

Reizen immer, aber irgendwie schaut meine Frau mich gerade böse an… Schnell weg :smiley:
Michael