MQTT, Mosquitto and PHP

As mentioned in my previous post I use a sheevaplug as a LAMP server and also run the MQTT server Mosquitto. In this post I shall not detail the finer points of MQTT and pub sub messaging, they are well described in this presentation by @andysc if you're not familiar. I intend to cover the more obscure topic of using PHP to write a simple MQTT client which can both publish and subscribe, getting input from an arduino into PHP and subsequently publishing it to Pachube. Currently I use MQTT to monitor temperature, bandwidth usage and cpu usage however this is set to expand in the future.

PHP and MQTT

Currently the majority of MQTT users seem to use clients written in Perl, which is fine for those over a certain age where Perl is common knowledge, but when standing next to some more recent scripting languages like PHP and python it's a bit archaic! Conveniently IBM have provided the SAM PHP library which includes the capabilities to send and receive MQTT messages and is quite simple to use both from the CLI or as part of a web application. However it includes support for other IBM protocols which isn't required for basic MQTT communication so the complicated compilation and installation is not really required here, just the php files, thus the folder can be placed in the same folder as the project using it and included with a standard php include:

[sourcecode language="PHP"]require('<;PHP-SAM folder name>/php_sam.php');[/sourcecode]

Once this has been included it's a trivial process to connect and send a message, this example shows how to get the average cpu usage over the last minute and send it over MQTT on the topic cpu:

<?php 
require('SAM/php_sam.php');

//create a new connection object
$conn = new SAMConnection();

//start initialise the connection
$conn->connect(SAM_MQTT, array(SAM_HOST => '<;Broker IP>',
                                 SAM_PORT => 1883));

//while the connection exists
        while($conn)
        {
            //get the cpu usage using a shell command
            $cmd = 'cat /proc/loadavg';
            $rawCpu=shell_exec($cmd);
            $result=preg_match('/^\d+.\d+/', $rawCpu, $cpu);
            //if successful then send message
             if($result==1)
                {
                //create a new MQTT message with the output of the shell command as the body
                $msgCpu = new SAMMessage('$cpu[0]');

                //send the message on the topic cpu
                $conn->send('topic://cpu', $msgCpu);

                // print sent to the terminal
                echo 'sent';

                //wait for a minute
                sleep(60);
            }
        }
?>

Subscribing to topics is a similarly simple process, in this example we will receive the messages sent by the above example and print them to the terminal:

require('SAM/php_sam.php');

//create a new connection object
$conn = new SAMConnection();

//start initialise the connection
$conn->connect(SAM_MQTT, array(SAM_HOST => '<;Broker IP>',
                                 SAM_PORT => 1883));

//subscribe to topic cpu
    $subUp = $conn->subscribe('topic://cpu') OR die('could not subscribe');

//print confirmation to terminal
 echo 'subscribed';

while($conn)
{
       //receive latest message on topic $subUp
       $msgUp = $conn->receive($subUp);

       //if there is a message
      if (!$msgUp->body=='')
      {
          //echo message to terminal
          echo $msgUp->body;
      }

      //wait 1s
      sleep(1);
}

Simple. These scripts are what I use as CLI scripts however the same methods can also be integrated into a webpage. However things are never quite as simple as they seem, the above code works fine with IBM Really Small Message Broker, but I'm using mosquitto... the PHP SAM library has trouble communicating with mosquitto, the author of Mosquitto provided a patch for the MQTT/sam_mqtt.php file:

Changing line 781 from:

$tlen = fread($conn,2);

to

$tlen = '';
while(strlen($tlen)!=2 {
   $tlen .= fread($conn,1);
}

The patch file can be downloaded here, this solves all problems of connecting to mosquitto using PHP SAM.

Under normal circumstances I would publish the complete code rather than a patch, however the licensing of the PHP SAM package appears to be contradictory, half suggesting I should register with IBM before modifying and republishing and the other saying the code is Apache 2.0 licensed which would allow what I wish. I'm aware MQTT client code licensing is an ongoing issue but this just seems like a mess. I am currently seeking clarification of the issue.

PHP and Arduino

The system I use to monitor temperature and publish to over MQTT relies on an arduino with a Dallas Semiconductor 1-wire sensor which sends the current temperature over serial  back to my sheevaplug, getting serial data into an MQTT message is the simple matter of using a terminal command to get the serial message and then placing the contents into an MQTT message.

This example shows just the recipt of a serial message, it can be inserted into an MQTT message using the same method as above:

//command to initialise serial correctly for communication with arduino
$initSerial = 'stty -F /dev/ttyUSB0 cs8 9600 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts -clocal -hupcl';

//execute command
$initre=shell_exec($initSerial);

//command to get the last line of serial input from arduino on port ttyUSB0
$cmd = 'cat /dev/ttyUSB0|head -n 1';

//execute command $temp is the last line of the serial communication
$temp=shell_exec($cmd);

//print value to terminal
echo $temp;

I choose to use a direct usb connection rather than an arduino ethernet shield with pubsub library because I've had much less success getting the library to work and also I like to build my own arduinos with which shields are not compatible. Ethernet shields also are not cheap!

Pachube

Publishing to pachube using PHP is already well documented so not something I feel the need to repeat suffice to say that I combine each MQTT subscriber client with a pachube publishing client and publish my data http://www.pachube.com/users/chemicaloliver/feeds. Again direct publishing is possible from an arduino + ethernet shield but I like all my data to go via MQTT as I'm developing other things which use the data.

What Next

I'm working on interfacing an old meter to show my current internet speed usage which I might get round to documenting once I've sorted out the problems I've having interfacing the arduino with mosquitto.