Example #1
0
<?php

/**
 *
 * PHP version 5.5
 *
 * @author  Sergey V.Kuzin <*****@*****.**>
 * @license MIT
 */
require __DIR__ . '/../vendor/autoload.php';
$mqtt = new \MQTT\spMQTT('tcp://127.0.0.1:1883/');
\MQTT\spMQTTDebug::Enable();
//$mqtt->setAuth('sskaje', '123123');
$connected = $mqtt->connect();
if (!$connected) {
    die("Not connected\n");
}
$mqtt->ping();
//$msg = str_repeat('1234567890', 209716);
$msg = str_repeat('1234567890', 2);
# mosquitto_sub -t 'sskaje/#'  -q 1 -h test.mosquitto.org
$mqtt->publish('sskaje/test', $msg, 0, 1, 0, 1);
$msg = str_repeat('привет ', 2);
# mosquitto_sub -t 'sskaje/#'  -q 1 -h test.mosquitto.org
$mqtt->publish('sskaje/test', $msg, 0, 1, 0, 1);
Example #2
0
 /**
  * Send packet
  *
  * @return int
  */
 public function write()
 {
     $this->mqtt->getLogger()->debug('Message write: message_type=' . $this->message_type);
     $length = 0;
     $message = $this->build($length);
     $bytes_written = $this->mqtt->socket_write($message, $length);
     $this->mqtt->getLogger()->debug('Message write: message=' . spMQTTDebug::printHex($message, true));
     $this->mqtt->getLogger()->debug('Message write: bytes written=' . $bytes_written);
     return $bytes_written;
 }
Example #3
0
 /**
  * loop
  * @param callback $callback function(spMQTT $mqtt, $topic, $message)
  * @throws \Exception
  */
 public function loop($callback)
 {
     $this->logger->debug(__METHOD__);
     if (empty($this->topics) && empty($this->topics_to_subscribe)) {
         $this->logger->critical('No topic subscribed/to be subscribed');
         throw new \LogicException('No topic subscribed/to be subscribed', 100601);
     }
     $last_subscribe_msgid = 0;
     $last_subscribe_qos = array();
     $last_unsubscribe_msgid = 0;
     while (1) {
         # Subscribe topics
         if (!empty($this->topics_to_subscribe)) {
             list($last_subscribe_msgid, $last_subscribe_qos) = $this->do_subscribe();
         }
         # Unsubscribe topics
         if (!empty($this->topics_to_unsubscribe)) {
             $last_unsubscribe_msgid = $this->do_unsubscribe();
         }
         if (!$this->socket || !$this->checkAndPing()) {
             $this->logger->error('loop(): EOF detected');
             $this->reconnect();
             $this->subscribe($this->topics);
         }
         $sockets = array($this->socket);
         $w = $e = null;
         if (stream_select($sockets, $w, $e, $this->keepalive / 2)) {
             if (feof($this->socket) || !$this->checkAndPing()) {
                 $this->logger->error('loop(): EOF detected');
                 $this->reconnect();
                 $this->subscribe($this->topics);
             }
             # The maximum value of remaining length is 268 435 455, FF FF FF 7F.
             # In most cases, 4 bytes is enough for fixed header and remaining length.
             # For PUBREL and UNSUBACK, 4 bytes is the maximum length.
             # For SUBACK, QoS list should be checked.
             # So, read the first 4 bytes and try to figure out the remaining length,
             # then read else.
             # read 4 bytes
             $read_bytes = 4;
             $read_message = $this->socket_read($read_bytes);
             if (empty($read_message)) {
                 continue;
             }
             $cmd = $this->unpackCommand(ord($read_message[0]));
             $message_type = $cmd['message_type'];
             $dup = $cmd['dup'];
             $qos = $cmd['qos'];
             $retain = $cmd['retain'];
             $this->logger->debug(__METHOD__, ['message_type' => $message_type, 'dup' => $dup, 'QoS' => $qos, 'RETAIN' => $retain]);
             $flag_remaining_length_finished = 0;
             for ($i = 1; isset($read_message[$i]); $i++) {
                 if (ord($read_message[$i]) < 0x80) {
                     $flag_remaining_length_finished = 1;
                     break;
                 }
             }
             if (empty($flag_remaining_length_finished)) {
                 # read 3 more bytes
                 $read_message .= $this->socket_read(3);
             }
             $pos = 1;
             $len = $pos;
             $remaining_length = $this->remainingLengthDecode($read_message, $pos);
             if ($flag_remaining_length_finished) {
                 $to_read = $remaining_length - (3 + $len - $pos);
             } else {
                 $to_read = $remaining_length - 2;
             }
             $this->logger->debug(__METHOD__, ['remaining length' => $remaining_length, 'to read' => $to_read]);
             $read_message .= $this->socket_read($to_read);
             $this->logger->debug(__METHOD__, ['message' => spMQTTDebug::printHex($read_message, true)]);
             switch ($message_type) {
                 # Process PUBLISH
                 case spMQTTMessageType::PUBLISH:
                     $this->logger->debug('loop(): PUBLISH');
                     # topic length
                     $topic_length = $this->toUnsignedShort(substr($read_message, $pos, 2));
                     $pos += 2;
                     # topic content
                     $topic = substr($read_message, $pos, $topic_length);
                     $pos += $topic_length;
                     # PUBLISH QoS 0 doesn't have msgid
                     if ($qos > 0) {
                         $msgid = $this->toUnsignedShort(substr($read_message, $pos, 2));
                         $pos += 2;
                     }
                     # message content
                     $message = substr($read_message, $pos);
                     if ($qos == 0) {
                         $this->logger->debug('loop(): PUBLISH QoS=0 PASS');
                         # Do nothing
                     } elseif ($qos == 1) {
                         # PUBACK
                         $pubackobj = $this->getMessageObject(spMQTTMessageType::PUBACK);
                         $pubackobj->setDup($dup);
                         $pubackobj->setMsgID($msgid);
                         $puback_bytes_written = $pubackobj->write();
                         $this->logger->debug('loop(): PUBLISH QoS=1 PUBACK written=' . $puback_bytes_written);
                     } elseif ($qos == 2) {
                         # PUBREC
                         $pubrecobj = $this->getMessageObject(spMQTTMessageType::PUBREC);
                         $pubrecobj->setDup($dup);
                         $pubrecobj->setMsgID($msgid);
                         $pubrec_bytes_written = $pubrecobj->write();
                         $this->logger->debug('loop(): PUBLISH QoS=2 PUBREC written=' . $pubrec_bytes_written);
                     } else {
                         # wrong packet
                         $this->logger->error('loop(): PUBLISH Invalid QoS');
                     }
                     # callback
                     call_user_func($callback, $this, $topic, $message);
                     break;
                     # Process PUBREL
                 # Process PUBREL
                 case spMQTTMessageType::PUBREL:
                     $this->logger->debug('loop(): PUBREL');
                     $msgid = $this->toUnsignedShort(substr($read_message, $pos, 2));
                     $pos += 2;
                     # PUBCOMP
                     $pubcompobj = $this->getMessageObject(spMQTTMessageType::PUBCOMP);
                     $pubcompobj->setDup($dup);
                     $pubcompobj->setMsgID($msgid);
                     $pubcomp_bytes_written = $pubcompobj->write();
                     $this->logger->debug('loop(): PUBREL QoS=2 PUBCOMP written=' . $pubcomp_bytes_written);
                     break;
                     # Process SUBACK
                 # Process SUBACK
                 case spMQTTMessageType::SUBACK:
                     $this->logger->debug('loop(): SUBACK');
                     $msgid = $this->toUnsignedShort(substr($read_message, $pos, 2));
                     $pos += 2;
                     $qos_list = array();
                     for ($i = $pos; isset($read_message[$i]); $i++) {
                         # pick bit 0,1
                         $qos_list[] = ord($read_message[$i]) & 0x3;
                     }
                     # check msg id & qos payload
                     if ($msgid != $last_subscribe_msgid) {
                         $this->logger->debug('loop(): SUBACK message identifier mismatch: ' . $msgid . ':' . $last_subscribe_msgid);
                     } else {
                         $this->logger->debug('loop(): SUBACK msgid=' . $msgid);
                     }
                     if ($last_subscribe_qos != $qos_list) {
                         $this->logger->debug('loop(): SUBACK returned qos list doesn\'t match SUBSCRIBE');
                     }
                     break;
                     # Process UNSUBACK
                 # Process UNSUBACK
                 case spMQTTMessageType::UNSUBACK:
                     $this->logger->debug('loop(): UNSUBACK');
                     $msgid = $this->toUnsignedShort(substr($read_message, $pos, 2));
                     $pos += 2;
                     # TODO:???
                     if ($msgid != $last_unsubscribe_msgid) {
                         $this->logger->debug('loop(): UNSUBACK message identifier mismatch ' . $msgid . ':' . $last_unsubscribe_msgid);
                     } else {
                         $this->logger->debug('loop(): UNSUBACK msgid=' . $msgid);
                     }
                     break;
             }
         }
     }
 }