SendQueue um Nachrichten an SeriaPort zu schicken

Hallo zusammen,

ich möchte an eine SerialPort Instanz aus einem Modul gerne Nachrichten schicken, brauche aber 200ms-1000ms (muss ich noch genau testen) Pause zwischen den Nachrichten, da der USB-Stick sonst Nachrichten verschluckt. Ich könnte die Nachrichten statt zu Senden in einen Buffer schreiben, aber wie bekomme ich die in den passenden Zeitabständen da raus?

Vielen Dank!

Gruß baba

SetTimer ?
Zum Beispiel alles als Array (jeder Index ein Befehl) in einen Buffer schreiben und mit SetTimerInterval (200) einen SendeThread starten.
Sobald das Array leer ist, Timer auf 0.
Alternativ nach dem SendDataToParent einfach IPS_Sleep(200).

Gibt es den keine Quittung vom Stick?
Sonst wäre das ja die Wartezeit und erst dann wieder senden. Das geht z.B. mit einer Semaphore.
Michael

Danke für die Ideen. Ja es gibt ein ACK für jeden Befehl vom Stick. Das berechnete ACK tue ich in einen ReceiveBuffer und warte dann bis es wirklich kommt und schicke es dann als return der Send Methode an das Device. Wenn alles aus einem Script aufgerufen wird, passt dass dann glaube so, aber Scripte können ja parallel laufen.

Ja, dann kann passieren.
Dann nutze eine Semaphore, so dass immer nur eine Senderoutine laufen kann und wartet bis der ACK kommt, dann wieder freigeben.
Michael

Das ist eine sehr gute Idee, danke! Damit kann ich dann auch verhindern, dass während des Init noch kein Befehl gesendet wird. Reicht da das normale IPS_Semaphore, oder sollte ich zu so einer Funktion wie in deinem Plugwise Modul greifen, wo du die Wartezeiten random setzt?

Das Problem ist nur, wenn er in SendDataToParent nen trigger_error aufruft, weil die Nachricht nicht gesendet wurde, verlässt er das Semaphore nie mehr.

SendMsg von den Devices:


    private function SendMsg($msg)
    {
        // check valid msg
        if (!preg_match(DuoFernRegex::DUOFERN_REGEX_MSG, $msg)) {
            return false;
        }

        // convert data from hex to string
        $data = $this->ConvertMsgToSend($msg);

        // return false if msg semaphore could not be set
        if (!IPS_SemaphoreEnter('DUOFERN_SendMsg', 10000)) {
            return false;
        }

        // send to parent io
        $result = $this->SendDataToParent($data);

        // leave msg semaphore
        IPS_SemaphoreLeave('DUOFERN_SendMsg');

        if ($result !== false) {
            $this->SendDebug("RECEIVED RESPONSE", $this->ConvertMsgToSend($result), 1);
        } else { // never entered because of trigger_error in SendDataToParent
            $this->SendDebug("TIMEOUT WAITFORRESPONSE", $this->ConvertMsgToSend($this->ExpectedResponse($msg)), 1);
        }

        return $result;
    }

Das SendMsg Methode, welche hier drin aufgerufen wird, ist eine andere Methode (die vom Splitter/Gateway):


    private function Init($retry = 5)
    {
        // get gateway duo fern code
        $gatewayDuoFernCode = $this->ReadPropertyString('duoFernCode');

        // get device duo fern codes
        $deviceDuoFernCodes = $this->GetDeviceDuoFernCodes();

        // return false if msg semaphore could not be set
        if (!IPS_SemaphoreEnter('DUOFERN_SendMsg', 10000)) {
            return false;
        }

        for ($i = 0; $i < $retry; $i++) {
            $this->SendDebug("INIT START", $this->ConvertMsgToSend("00000000000000000000000000000000000000000000"), 1);

            // init 1
            $response = $this->SendMsg(DuoFernMessage::DUOFERN_MSG_INIT_1);
            if ($response !== $this->ExpectedResponse(DuoFernMessage::DUOFERN_MSG_INIT_1)) {
                $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                continue;
            }

            // init 2
            $response = $this->SendMsg(DuoFernMessage::DUOFERN_MSG_INIT_2);
            if ($response !== $this->ExpectedResponse(DuoFernMessage::DUOFERN_MSG_INIT_2)) {
                $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                continue;
            }

            // init serial
            $response = $this->SendMsg(DuoFernMessage::MsgInitSerial($gatewayDuoFernCode));
            if ($response !== $this->ExpectedResponse(DuoFernMessage::MsgInitSerial($gatewayDuoFernCode))) {
                $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                continue;
            }

            // init 3
            $response = $this->SendMsg(DuoFernMessage::DUOFERN_MSG_INIT_3);
            if ($response !== $this->ExpectedResponse(DuoFernMessage::DUOFERN_MSG_INIT_3)) {
                $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                continue;
            }

            // init pair table
            foreach ($deviceDuoFernCodes as $number => $deviceDuoFernCode) {
                $msg = DuoFernMessage::MsgInitPairtable($number, $deviceDuoFernCode);
                $response = $this->SendMsg($msg);
                if ($response !== $this->ExpectedResponse($msg)) {
                    $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                    continue;
                }
            }

            // init end
            $response = $this->SendMsg(DuoFernMessage::DUOFERN_MSG_INIT_END);
            if ($response !== $this->ExpectedResponse(DuoFernMessage::DUOFERN_MSG_INIT_END)) {
                $this->SendDebug("INIT FAIL", $this->ConvertMsgToSend($response), 1);
                continue;
            }

            $this->SendDebug("INIT SUCCESS", $this->ConvertMsgToSend("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"), 1);

            // set instance status to active
            $this->SetStatus(IS_ACTIVE);

            // leave msg semaphore
            IPS_SemaphoreLeave('DUOFERN_SendMsg');

            return true;
        }

        // set instance status to initialization failed
        $this->SetStatus(self::IS_INIT_FAILED);

        // leave msg semaphore
        IPS_SemaphoreLeave('DUOFERN_SendMsg');

        return false;
    }

Gruß baba