phpmqttphpmqtt

Object not available in function


I have an application in which I subscribe to a topic on a MQTT broker. When a message is received I need to process the data in the message and post it back to the same broker, on a different topic. I am using the Lightning branch of PHPMQTT as it is well maintained (github repo).

My script is as follows.

<?php
require("./vendor/autoload.php");
/**
 * An example callback function that is not inline.
 * @param  \Lightning\Response $response
 */
function callbackFunction($response) {
    $topic = $response->getRoute();
    $wildcard = $response->getWildcard();
    $message = $response->getMessage();
    echo "Message recieved:\n =============\n Topic: $topic\n Wildcard: $wildcard\n Message:\n $message\n\n";
}
$host = "m21.cloudmqtt.com";
$port = 18256;
$clientID = md5(uniqid()); // use a unique client id for each connection
$username = ''; // username is optional
$password = ''; // password is optional
$mqtt = new \Lightning\App($host, $port, $clientID, $username, $password);
// Optional debugging
$mqtt->debug(true);
if (!$mqtt->connect()) {
    echo "Failed to connect\n";
    exit;
}
// Add a new subscription for each topic that is needed
$mqtt->subscribe('net/raw/#', 0, function ($response) {
    $topic = $response->getRoute();
    $message = $response->getMessage();
    $attributes = $response->getAttributes(); // Returns all the attributes received
    $id = $response->attr('id'); // Gets a specific attribute by key. Returns null if not present.
    echo "Message recieved:\n =============\n Topic: $topic\n Attribute - id: $id\n Message:\n $message\n\n";

  $topic_id = 524;
  $message = "0A";
  $mqtt->publish("test/request/yes".$topic_id, $message, 1);
});
// Callback functions can be inline or by name as a string
$mqtt->subscribe('test/request/#', 0, 'callbackFunction');
// Call listen to begin polling for messages
$mqtt->listen();
?>

I can subscribe to 'net/raw' just fine. Processing is fine too. Problem occurs when publishing it back to the broker. It the connection started in line 18 is not available to the function and the following error occurs:

Notice: Undefined variable: mqtt in C:\wamp64\www\sub.php on line 35

Fatal error: Uncaught Error: Call to a member function publish() on null in C:\wamp64\www\sub.php:35 Stack trace: 0 [internal function]: {closure}(Object(Lightning\Response)) 1 C:\wamp64\www\vendor\brandonhudson\lightning\Lightning\App.php(353): call_user_func(Object(Closure), Object(Lightning\Response)) 2 C:\wamp64\www\vendor\brandonhudson\lightning\Lightning\App.php(424): Lightning\App->message('0A') 3 C:\wamp64\www\sub.php(40): Lightning\App->listen() 4 {main} thrown in C:\wamp64\www\sub.php on line 35

I can create a new connection inside the function, but I don't want to keep opening and closing new connections when one should be enough. What can I do to make the connection available inside the function?


Solution

  • You are using a closure (anonymous function) as a callback function for the method response. To inherit variables into the closure you can use use instead of additional parameters on the closure.

    So you can change the call of response to the following:

    // Add a new subscription for each topic that is needed
    $mqtt->subscribe('net/raw/#', 0, function ($response) use ($mqtt) {
        $topic = $response->getRoute();
        $message = $response->getMessage();
        $attributes = $response->getAttributes(); // Returns all the attributes received
        $id = $response->attr('id'); // Gets a specific attribute by key. Returns null if not present.
        echo "Message recieved:\n =============\n Topic: $topic\n Attribute - id: $id\n Message:\n $message\n\n";
    
        $topic_id = 524;
        $message = "0A";
        $mqtt->publish("test/request/yes".$topic_id, $message, 1);
    });