Workaround für Timer

Hier mal ein paar Methoden um einen einfachen Timer in einem Modul zu nutzen.

Verwendung :


    public function Create()
    {
//Never delete this line!
        parent::Create();
        $this->RegisterTimer('RequestPinState', $this->ReadPropertyInteger('Interval'), 'XBee_RequestState($_IPS[\'TARGET\']);');
//                                                              IDENT                           INTERVAL                                           FUNKTION

    }
    public function ApplyChanges()
    {
        //Never delete this line!
        parent::ApplyChanges();
        $this->SetTimerInterval('RequestPinState', $this->ReadPropertyInteger('Interval'));
}

Methoden:


    protected function RegisterTimer($Name, $Interval, $Script)
    {
        $id = @IPS_GetObjectIDByIdent($Name, $this->InstanceID);
        if ($id === false)
            $id = 0;


        if ($id > 0)
        {
            if (!IPS_EventExists($id))
                throw new Exception("Ident with name " . $Name . " is used for wrong object type");

            if (IPS_GetEvent($id)['EventType'] <> 1)
            {
                IPS_DeleteEvent($id);
                $id = 0;
            }
        }

        if ($id == 0)
        {
            $id = IPS_CreateEvent(1);
            IPS_SetParent($id, $this->InstanceID);
            IPS_SetIdent($id, $Name);
        }
        IPS_SetName($id, $Name);
        IPS_SetHidden($id, true);
        IPS_SetEventScript($id, $Script);
        if ($Interval > 0)
        {
            IPS_SetEventCyclic($id, 0, 0, 0, 0, 1, $Interval);

            IPS_SetEventActive($id, true);
        }
        else
        {
            IPS_SetEventCyclic($id, 0, 0, 0, 0, 1, 1);

            IPS_SetEventActive($id, false);
        }
    }

    protected function UnregisterTimer($Name)
    {
        $id = @IPS_GetObjectIDByIdent($Name, $this->InstanceID);
        if ($id > 0)
        {
            if (!IPS_EventExists($id))
                throw new Exception('Timer not present');
            IPS_DeleteEvent($id);
        }
    }

    protected function SetTimerInterval($Name, $Interval)
    {
        $id = @IPS_GetObjectIDByIdent($Name, $this->InstanceID);
        if ($id === false)
            throw new Exception('Timer not present');
        if (!IPS_EventExists($id))
            throw new Exception('Timer not present');

        $Event = IPS_GetEvent($id);

        if ($Interval < 1)
        {
            if ($Event['EventActive'])
                IPS_SetEventActive($id, false);
        }
        else
        {
            if ($Event['CyclicTimeValue'] <> $Interval)
                IPS_SetEventCyclic($id, 0, 0, 0, 0, 1, $Interval);
            if (!$Event['EventActive'])
                IPS_SetEventActive($id, true);
        }
    }

Ich hab was ähnliches gebaut, aber etwas anders als du


  protected function RegisterTimer($ident, $interval, $script) {
    $id = @IPS_GetObjectIDByIdent($ident, $this->InstanceID);

    if ($id && IPS_GetEvent($id)['EventType'] <> 1) {
      IPS_DeleteEvent($id);
      $id = 0;
    }

    if (!$id) {
      $id = IPS_CreateEvent(1);
      IPS_SetParent($id, $this->InstanceID);
      IPS_SetIdent($id, $ident);
    }

    IPS_SetName($id, $ident);
    IPS_SetHidden($id, true);
    IPS_SetEventScript($id, "\$id = \$_IPS['TARGET'];
$script;");

    if (!IPS_EventExists($id)) throw new Exception("Ident with name $ident is used for wrong object type");

    if (!($interval > 0)) {
      IPS_SetEventCyclic($id, 0, 0, 0, 0, 1, 1);
      IPS_SetEventActive($id, false);
    } else {
      IPS_SetEventCyclic($id, 0, 0, 0, 0, 1, $interval);
      IPS_SetEventActive($id, true);
    }
  }

Unterschied zu deinem, mir war wichtig das ich immer nur eine Funktion aufrufe die das Event anlegt und updaten kann. Das sorgt dafür das auch bei einem Update der Timer angelegt wird, ohne das ich die Instanz wegwerden muss. Außerdem glaube ich nicht, dass es ein Performancenachteil darstellt immer vorher zu prüfen ob es das Event schon gibt. Ansonsten sind wir recht nah bei einander. Habe mir auch die Idee mit dem Interval von 0 abgeschaut, um das Script abzuschalten! Achja, zusätzlich wollte ich das $id im Script verwendet wird, so wie bei den Forms auch. Wobei mir eigentlich lieber gewesen wäre, nur den Funktionsnamen anzugeben, wie das auch in der Oberfläche geht, aber hier habe ich keine Funktion in der Doku gefunden.

Die Umsetzung von mir ist an dem alten Delphi-SDK angeleht.
Damit ist der Aufbau der alten und neuen Module bei mir ähnlich, was für mich einfacher zu warten ist.
Klar kann man es jetzt (mit PHP) auch mit einer Funktion lösen, nur müßte ich dann jedesmal das Script mit übergeben.
Aber es ist ja eh nur als Übergangslösung gedacht.

Das mit der $id kommt aber aus der Konsole, und hat nichts mit dem PHP in IPS selbst zu tun.
Die Konsole interpretiert $id in einem Konfig-Formular, als InstanzID welche du gerade geöffnet hast.

Michael