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