DatabaseMan
DatabaseMan

Reputation: 17

Using php-mqtt to ping a device

so I'm trying to publish a "ping" request to a public mqtt server from my php website and wait for the device to answer.

✅ Publishing (PHP -> Broker) works

✅ Device Subscription (Broker -> Device

✅ Publishing the answer (Device -> Broker) works

But... the timeout is always reached even though the answer is sent to the correct topic about 2-3 sec. after the request. Do you have any ideas??

Here is my code:

<?php
require 'vendor/autoload.php';

use PhpMqtt\Client\MqttClient;
use PhpMqtt\Client\ConnectionSettings;
use PhpMqtt\Client\Message;

$broker = 'test.mosquitto.org';
$port = 1883;

$username = '';
$password = ''; 
$mainTopic = '!!!testlab';
$ackTimeout = 30;

$testMessage = 'Broker Test';
$brokerStatus = sendText($broker, $port, $username, $password, $mainTopic, $testMessage, $ackTimeout);

if ($brokerStatus === 0) {
    echo "Broker OK, RPi OK\n";
} elseif ($brokerStatus === 1) {
    die("Broker offline\n");
} else {
    die("Broker OK, RPi Timeout\n");
}

function sendText($broker, $port, $username, $password, $mainTopic, $message, $ackTimeout)
{
    try {
        $client = new MqttClient($broker, $port, 'php-client');
        $settings = (new ConnectionSettings);

        if (!empty($username)) {
            $settings->setUsername($username);
        }

        if (!empty($password)) {
            $settings->setPassword($password);
        }

        $client->connect($settings);

        $messageId = uniqid();
        $subTopic = $mainTopic . '/' . $messageId;
        $acknowledgmentTopic = $subTopic . '/ack';

        $messageData = [
            'id' => $messageId,
            'message' => $message,
            'timestamp' => time(),
        ];
        $messagePayload = json_encode($messageData);

        $acknowledgment = null;

        $startTime = microtime(true);

        $client->subscribe($acknowledgmentTopic, function (Message $message) use ($acknowledgmentTopic, &$acknowledgment) {
            
            $acknowledgmentData = json_decode($message->getPayload(), true);

            if ($acknowledgmentData && isset($acknowledgmentData['code'])) {
                $acknowledgmentCode = $acknowledgmentData['code'];
                $acknowledgmentMessage = isset($acknowledgmentData['message']) ? $acknowledgmentData['message'] : '';

                if ($acknowledgmentCode == 0) {
                    $acknowledgment = 0;
                } else {
                    $acknowledgment = (int)$acknowledgmentCode;
                }
            }
        });

        $client->registerLoopEventHandler(function (MqttClient $client) use ($acknowledgmentTopic, &$acknowledgment, $ackTimeout, $startTime) {
            if ($acknowledgment !== null) {
                $client->interrupt();
            }

            $elapsedTime = microtime(true) - $startTime;

            if ($elapsedTime >= $ackTimeout) {
                $acknowledgment = 2;
                $client->interrupt();
            }
        });
        
        $client->publish($subTopic . '/text', $messagePayload);

        $client->loop();

        $client->disconnect();

        return $acknowledgment ?? 2;
    } catch (\Throwable $e) {
        if($debug){echo "Fehler: " . $e->getMessage() . "\n";}
        return 1; // Verbindungsfehler zum Broker
    }
}
?>

Upvotes: 0

Views: 88

Answers (0)

Related Questions