新しいオープンソースPHP MQTTクライアントコードライブラリ--PHPMQTT

8747 ワード

It seems finally we may be freed from the unstable shakiness which is embodied in PHP_SAM – the only PHP based MQTT client….until now.
Project SAM is a PHP library for several different pubsub messaging systems, one being MQTT. However it suffers from a very restrictive licence, a lack of maintenance and quite a few bugs. Previously there was no choice if you wished to use MQTT and PHP, now Andrew Milsted(@bluerhinos) has started to produce an alternative: phpMQTT
phpMQTT is only in infancy at the moment and currently only publishing is fully functional, with some bugs to be ironed out of subscriptions, however for anyone who has used PHP_SAM it provides a refreshingly easy way to start using MQTT – consisting of just one file and a handful of simple functions. An example of publishing a message (written by Andrew Milsted) is shown below:
require("phpMQTT.php");  
$mqtt = new phpMQTT();  /* broker(broker address, broker port, client id); */ 
$mqtt->broker("example.com", 1883, "PHP MQTT Client"); 
$mqtt->connect();  /* publish( topic, message, qos); */ 
$mqtt->publish("bluerhinos/phpMQTT/examples/publishtest","Hello World!",0); 
$mqtt->close();

The main point to note from this example is that unlike PHP_SAM I could just download the library and run it straight away, no looking through to see why it was causing errors, no patching to work with mosquitto, it just worked (all the bits that claimed to work anyway). It’s also simple enough that anyone with a basic grasp of any C style language and MQTT could start using straight away with any documentation!
The MQTT scene has seen quite an influx of interest of late and the OSS community is responding to this by producing an increasingly large range of associated software, phpMQTT being the latest in a series of projects driving MQTT away from being an niche IBM employee interest into a more widely known technology, this can only be good for all involved.
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:
require('<PHP-SAM folder name>/php_sam.php');

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:
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 aDallas 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 librarybecause 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.