diff --git a/Monitoring Client/module.php b/Monitoring Client/module.php index 014bdfd..ce054cf 100644 --- a/Monitoring Client/module.php +++ b/Monitoring Client/module.php @@ -26,14 +26,78 @@ class MonitoringClient extends IPSModule { } // Überschreibt die intere IPS_ApplyChanges($id) Funktion - public function ApplyChanges() { - // Diese Zeile nicht löschen - parent::ApplyChanges(); + public function ApplyChanges() { + // Diese Zeile nicht löschen + parent::ApplyChanges(); $this->SetTimerInterval("Update", $this->ReadPropertyInteger("Updatetime") * 1000); $this->SetTimerInterval("ForceUpdate", $this->ReadPropertyInteger("ForceUpdatetime") * 1000 * 60); - - } + + } + + private function isMqttConnectionReady($instanceId, $logError = true) { + $checked = array(); + while ($instanceId > 0) { + if (isset($checked[$instanceId]) || !IPS_InstanceExists($instanceId)) { + return false; + } + + $checked[$instanceId] = true; + $instance = IPS_GetInstance($instanceId); + if ($instance["InstanceStatus"] != 102) { + if ($logError) { + IPS_LogMessage("Monitoring Client", "MQTT connection is not ready: " . IPS_GetName($instanceId) . " (Status " . $instance["InstanceStatus"] . ")"); + } + return false; + } + + $instanceId = isset($instance["ConnectionID"]) ? $instance["ConnectionID"] : 0; + } + + return true; + } + + private function getMqttClientSocketId($instanceId) { + $checked = array(); + while ($instanceId > 0 && !isset($checked[$instanceId]) && IPS_InstanceExists($instanceId)) { + $checked[$instanceId] = true; + $instance = IPS_GetInstance($instanceId); + if (isset($instance["ModuleInfo"]["ModuleName"]) && $instance["ModuleInfo"]["ModuleName"] == "Client Socket") { + return $instanceId; + } + + $instanceId = isset($instance["ConnectionID"]) ? $instance["ConnectionID"] : 0; + } + + return 0; + } + + private function reconnectMqttClientSocket($serverId) { + $socketId = $this->getMqttClientSocketId($serverId); + if ($socketId === 0) { + IPS_LogMessage("Monitoring Client", "No Client Socket found for the configured MQTT Client."); + return false; + } + + for ($attempt = 1; $attempt <= 20; $attempt++) { + IPS_SetProperty($socketId, "Open", false); + IPS_ApplyChanges($socketId); + IPS_Sleep(100); + + IPS_SetProperty($socketId, "Open", true); + IPS_ApplyChanges($socketId); + IPS_Sleep(500); + + if ($this->isMqttConnectionReady($serverId, false)) { + IPS_LogMessage("Monitoring Client", "MQTT Client Socket reconnected on attempt " . $attempt . "."); + return true; + } + } + + IPS_LogMessage("Monitoring Client", "MQTT Client Socket could not be reconnected after 20 attempts."); + return false; + } + /** * Die folgenden Funktionen stehen automatisch zur Verfügung, wenn das Modul über die "Module Control" eingefügt wurden. * Die Funktionen werden, mit dem selbst eingerichteten Prefix, in PHP und JSON-RPC wiefolgt zur Verfügung gestellt: @@ -45,10 +109,13 @@ class MonitoringClient extends IPSModule { a given topic without having to manually create a MQTT server device */ public function MqttPublish($server_id, $topic, $payload, $retain) { - // ensure server instance exists - if(!IPS_InstanceExists($server_id)) { - return false; - } + // ensure server instance exists + if(!IPS_InstanceExists($server_id)) { + return false; + } + if (!$this->isMqttConnectionReady($server_id)) { + return false; + } // convert array structure to json string if(is_array($payload)) $payload = json_encode($payload); @@ -113,6 +180,9 @@ class MonitoringClient extends IPSModule { IPS_SetConfiguration($id, $config_str); IPS_SetHidden($id,true); IPS_ApplyChanges($id); + if (!$this->isMqttConnectionReady($id)) { + return false; + } // get Value variable and use it to publish the payload $var_id = @IPS_GetObjectIDByIdent("Value", $id); @@ -153,10 +223,13 @@ class MonitoringClient extends IPSModule { } // ensure server instance exists - if(!IPS_InstanceExists($server_id)) { - IPS_LogMessage("Monitoring Client", "Server instance does not exist for Setpoint Sync."); - return false; - } + if(!IPS_InstanceExists($server_id)) { + IPS_LogMessage("Monitoring Client", "Server instance does not exist for Setpoint Sync."); + return false; + } + if (!$this->isMqttConnectionReady($server_id)) { + return false; + } // determine data type if(is_string($payload)) { @@ -209,12 +282,15 @@ class MonitoringClient extends IPSModule { $inst_config = IPS_GetInstance($id); if($inst_config["ConnectionID"] != $server_id) { IPS_DisconnectInstance($id); - if(!@IPS_ConnectInstance($id, $server_id)) { - return false; - IPS_LogMessage("Monitoring Client", "Could not connect device to server instance for Setpoint Sync."); - } - } - IPS_LogMessage("Monitoring Client", "Parentid was :".$id); + if(!@IPS_ConnectInstance($id, $server_id)) { + return false; + IPS_LogMessage("Monitoring Client", "Could not connect device to server instance for Setpoint Sync."); + } + } + if (!$this->isMqttConnectionReady($id)) { + return false; + } + IPS_LogMessage("Monitoring Client", "Parentid was :".$id); $id = IPS_GetChildrenIDs($id)[0]; IPS_LogMessage("Monitoring Client", "ID was :".$id); @@ -367,6 +443,12 @@ class MonitoringClient extends IPSModule { $projectname = $this->ReadPropertyString("Projectname"); $ispnumber = $this->ReadPropertyInteger("ISP"); + // A manual force update starts with a clean MQTT socket connection. + // Normal timer-driven sends do not interrupt the connection. + if (!$this->reconnectMqttClientSocket($mqttId)) { + return; + } + $catIds = array( array("id" => $this->ReadPropertyInteger("ParseNotifyCategoryID"), "top" => "Projekte" . $projectyear . "/P" . $projectnumber . "/ISP" . $ispnumber . "/Notify/"), array("id" => $this->ReadPropertyInteger("ParseAlarmCategoryID"), "top" => "Projekte" . $projectyear . "/P" . $projectnumber . "/ISP" . $ispnumber . "/Alarm/"), @@ -378,7 +460,9 @@ class MonitoringClient extends IPSModule { foreach ($this->getCategoryVariables($catId["id"]) as $variable) { $topic = $this->getTopicForVariable($catId["top"], $variable, true); $payload = round(GetValue($variable["id"]), 2); - $this->MqttPublish($mqttId, $topic, $payload, false); + if (!$this->MqttPublish($mqttId, $topic, $payload, false)) { + return; + } } } diff --git a/library.json b/library.json index fda9eff..fe65015 100644 --- a/library.json +++ b/library.json @@ -8,6 +8,6 @@ "date": 1491343200 }, "version": "3.0", - "build": 2, + "build": 4, "date": 0 }