Skip to content

Mosquitto-PHP - MQTT Client Library Encyclopedia

by Michael Maclean
12 min read

The Mosquitto-PHP library is a wrapper for the client library from the Mosquitto MQTT broker. As such, it implements most of the features in the MQTT 3.1.1 specification. It has been around since around 2013, and is currently in beta. It works with PHP version 5.3 and greater, though not yet PHP 7, and with Mosquitto version 1.3 and above. The source is held on Github, and contributions are always welcome.

Overview of Mosquitto-PHP

PMosquitto-PHP
Language PHP
License New BSD license
Website http://github.com/mgdm/Mosquitto-PHP
API Style Blocking, with callbacks

The library uses Mosquitto’s event loop to handle messages. You’ll construct a new client instance, set some callbacks to handle the various events, and then enter the event loop.

Features Supported by Mosquitto-PHP

Feature
MQTT 3.1 Yes
MQTT 3.1.1 Yes
LWT Yes
SSL/TLS Yes
Automatic Reconnect No

Advance Features Supported by Mosquitto-PHP

Feature
QoS 0 Yes
QoS 1 Yes
QoS 2 Yes
Authentication Yes
Throttling No

Usage

How to Install Mosquitto-PHP?

First off, you’ll need to make sure you have the Mosquitto client library installed, along with its development package. The extension requires version 1.3 or higher. On Linux, this can be compiled from source, or there are some pre-built packages available.

  • On Ubuntu there is a PPA for the latest version here. The package name you’ll need is libmosquitto-dev.

  • Fedora users should be able to install straight away. The package name you want is mosquitto-devel.

  • Mac OS X users can install Mosquitto using Homebrew: brew install mosquitto

The easiest way to install the PHP extension itself is to use PECL. On Linux and OSX, you can just type

pecl install Mosquitto-alpha

This will download the latest version of the package from Github, compile it, and install it. Finally, you may need to add the following to php.ini:

extension = mosquitto.so

Now, you should be all set!

How to Connect Mosquitto-PHP to an MQTT Broker?

To connect to the MQTT broker, you’ll need something like the following code.

<?php

/* Construct a new client instance, passing a client ID of “MyClient” */
$client = new Mosquitto\Client('MyClient');

/* Set the callback fired when the connection is complete */
$client->onConnect(function($code, $message) use ($client) {
    /* Subscribe to the broker's $SYS namespace, which shows debugging info */
    $client->subscribe('$SYS/#', 0);
});

/* Set the callback fired when we receive a message */
$client->onMessage(function($message) {
    /* Display the message's topic and payload */
    echo $message->topic, "\n", $message->payload, "\n\n";
});

/* Connect, supplying the host and port. */
/* If not supplied, they default to localhost and port 1883 */
$client->connect('broker.mqtt-dashboard.com', 1883);

/* Enter the event loop */
$client->loopForever();

In this code, we construct a new client instance, and set a callback for the onMessage event fired when the client connects successfully (receiving a CONNACK message from the broker). In the code above, we pass an anonymous function, but this can be any PHP callable so you can use normal functions or object methods.

When the onConnect callback is fired, we subscribe to the broker’s $SYS namespace, which contains some monitoring information – sufficient for a demonstration. We then specify the onMessage callback, which in this case just prints the topic and the payload of each message to the console.

Finally, we connect to the broker, and enter the event loop. The loopForever() method is a convenience method that loops around and handles events on its own, but if you want more control you can do the event handling yourself using the loop() method.

If you run the code above, you should see some statistics returned from the HiveMQ public broker.

Connect with LWT

It’s possible to supply a Last-Will-and-Testament message, which will be sent by the broker in the event that your client connection goes away without disconnecting cleanly. You must specify this before connecting.

<?php
$client = new Mosquitto\Client('MyClient');
$client->setWill('my/will/topic', 'My will payload', 1, true);
/* Set callbacks etc… */
$client->connect('hostname');

In this code, we set a LWT to be sent on the topic my/will/topic, with the payload My will payload, a QoS value of 1, and the final true indicates that the message should be retained.

If you wish to remove a LWT that you have previously set, you can use the clearWill() method:

$client->clearWill();

Connect with Username/Password

If your broker requires authentication, you can supply a username and password before calling connect(), by using the setCredentials() method:

$client->setCredentials('myusername', 'mypassword');

How to Publish an MQTT Message Using Mosquitto-PHP?

Once connected, you can publish messages with the publish() method. It takes the following parameters:

$client->publish($topic, $payload, $qos, $retain);

The topic and the payload are required. The QoS is an integer value – 0, 1 or 2. If not specified, the QoS will default to 0 and the message will not be retained.

How to Publish a Retained Message Using Mosquitto-PHP?

To publish a message with QoS 1 and have it retained, you can use the fourth parameter to publish():

$client->publish('my/topic', 'My retained message payload', 1, true);

How to Subscribe to an MQTT Message Using Mosquitto-PHP?

You can subscribe to topics with the subscribe() method.

$messageId = $client->subscribe($topic, $qos);

Currently, both the parameters are required. This method returns the message ID of the subscription request. There is a corresponding onSubscribe callback, which is triggered when a subscription has been successful.

Worth noting is that messages for all subscribed topics run through the same onMessage callback. If you need to handle different topics in different ways, you will need to implement that yourself.

How to Unsubscribe to an MQTT Message Using Mosquitto-PHP?

Unsubscribing is simple. Just use the unsubscribe() method:

$messageId = $client->unsubscribe($topic);

Again, this will return the message ID of the unsubscription request, which can be useful for accounting purposes. Again, there is an onUnsubscribe callback, triggered on a successful unsubscribe request.

How to Disconnect from an MQTT Broker While Using Mosquitto-PHP?

To disconnect from the MQTT broker, simply call disconnect():

$client->disconnect();

If you’re using loopForever(), the client will not exit the loop until all the messages required for a clean disconnection have been passed, at which point it will return. There is an onDisconnect() callback which will be triggered when the disconnection is complete. If you are using loopForever(), the loop will exit at this point.

Using TLS/SSL

Mosquitto-PHP provides full support for using TLS to connect to brokers. It can use the traditional certificate-based authentication, or use TLS pre-shared keys (PSK) if the broker supports it. Finally, it also supports using client certificates for authenticating to the broker.

Validating the Server Certificate

The most basic mode is to verify that the broker’s TLS certificate is trusted by a known certificate authority. To do this, you can supply the path to the CA certificate file, or to a directory containing them:

/* CA certificate is contained in a file */
$client->setTlsCertificates('/path/to/ca.crt');

/* CA certificate is contained within a directory */
$client->setTlsCertificates('/path/to/ca/directory');

This must be done before calling connect().

Using a Client Certificate

Additionally, you can supply a client certificate in order to identify your client to the broker. These are additional parameters to setTlsCertificates(). You must also supply the path to the private key for the client certificate, and the passphrase for the key if it’s encrypted.

$client->setTlsCertificates('/path/to/ca.crt', '/path/to/client.crt', '/path/to/client.key', 'passphrase');

Using TLS Pre-Shared Keys

Some brokers support TLS PSK, which is a recent addition to the standard. To use this, you use the setTlsPSK() method.

$client->setTlsPSK('1234567890abcdef', 'MyIdentity');

The first parameter is the key, in hex format, but with the leading 0x removed. The second parameter is the identity to use, which will correspond to one configured on the server.

Example Application of Using Mosquitto-PHP

The code below will subscribe to a list of topics, with a given QoS value for each topic, and record every message in a MySQL database. It contains a class, which is handed a pre-connected Client instance and a DB connection. These are configured outside of the class to avoid having to deal with the intricacies of setting up the connections. In the class constructor, it sets the onConnect and onMessage callbacks to its own methods: the onConnect callback handles subscribing to the topics requested by the user, and onMessage handles inserting the data into a database using a prepared statement.

The database table structure is as below.

CREATE TABLE `mqtt_logs` (
  `id` int(11) DEFAULT NULL,
  `topic` text,
  `payload` blob,
  `received` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

The code is as follows.

<?php

use Mosquitto\Client;
use Mosquitto\Message;

class MqttToDb {

    /* Our Mosquitto\Client instance */
    /**
     * @var Client The MQTT client
     */
    private $mqtt;

    /**
     * @var PDO A PDO database connection
     */
    private $db;

    /**
     * @var array The list of topics to subscribe to
     */
    private $topics = [];

    /**
     * @var PDOStatement A prepared statement used when we record a message
     */
    private $insertMessage;

    /**
     * @param Client $mqtt The Mosquitto\Client instance
     * @param PDO $db a PDO database connection
     */
    public function __construct(Client $mqtt, PDO $db)
    {
        $this->mqtt = $mqtt;
        $this->db = $db;

        $this->insertMessage = $this->db->prepare(
            'INSERT INTO mqtt_logs (id, topic, payload, received) VALUES (?, ?, ?, NOW());'
        );

        /* Subscribe the Client to the topics when we connect */
        $this->mqtt->onConnect([$this, 'subscribeToTopics']);
        $this->mqtt->onMessage([$this, 'handleMessage']);
    }

    /**
     * @param array $topics
     *
     * An associative array of topics and their QoS values
     */
    public function setTopics(array $topics)
    {
        $this->topics = $topics;
    }

    /**
     * The internal callback used when the Client instance connects
     */
    public function subscribeToTopics() {
        foreach ($this->topics as $topic => $qos) {
            $this->mqtt->subscribe($topic, $qos);
        }
    }

    /**
     * @param Message $message
     * The internal callback used when a new message is received
     */
    public function handleMessage($message)
    {
        $this->insertMessage->execute([$message->mid, $message->topic, $message->payload]);
    }

    /**
     * Start recording messages
     */
    public function start()
    {
        $this->mqtt->loopForever();
    }
}

/* Create a new DB connection */
$db = new PDO('mysql:host=localhost;dbname=mqtt_logs;charset=utf8', 'mqtt_logs', 'mqtt_logs');

/* Configure our Client */
$mqtt = new Client();
$mqtt->connect('broker.mqtt-dashboard.com');

$logger = new MqttToDb($mqtt, $db);
$logger->setTopics([
    'sensors/room1/temperature' => 0,
    'sensors/room2/temperature' => 0,
]);

$logger->start();

Michael Maclean

Michael Maclean is a developer based in Scotland, with a variety of interests including scalability, embedded systems and IoT. He maintains and contributes to a number of open source projects including Mosquitto-PHP and other PHP extensions.

Related content:

HiveMQ logo
Review HiveMQ on G2