diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..08d03e3
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+mqtt.simps.io
\ No newline at end of file
diff --git a/docs/.nojekyll b/docs/.nojekyll
new file mode 100644
index 0000000..e69de29
diff --git a/docs/_navbar.md b/docs/_navbar.md
new file mode 100644
index 0000000..43a9801
--- /dev/null
+++ b/docs/_navbar.md
@@ -0,0 +1,3 @@
+- Translations
+ - [:cn: 中文](/zh-cn/)
+ - [:uk: English](/en/)
\ No newline at end of file
diff --git a/docs/en/README.md b/docs/en/README.md
new file mode 100644
index 0000000..a0c8975
--- /dev/null
+++ b/docs/en/README.md
@@ -0,0 +1,171 @@
+# MQTT Coroutine Client
+
+MQTT Protocol Analysis and Coroutine Client for PHP.
+
+[![Latest Stable Version](https://poser.pugx.org/simps/mqtt/v)](//packagist.org/packages/simps/mqtt)
+[![Total Downloads](https://poser.pugx.org/simps/mqtt/downloads)](//packagist.org/packages/simps/mqtt)
+[![Latest Unstable Version](https://poser.pugx.org/simps/mqtt/v/unstable)](//packagist.org/packages/simps/mqtt)
+[![License](https://poser.pugx.org/simps/mqtt/license)](https://github.com/simps/mqtt/blob/master/LICENSE)
+
+## Install
+
+```bash
+composer require simps/mqtt
+```
+
+## Examples
+
+see [examples](https://github.com/simps/mqtt/tree/master/examples)
+
+## Client API
+
+### __construct()
+
+Create a MQTT client instance
+
+```php
+Simps\MQTT\Client::__construct(array $config, array $swConfig = [], int $type = SWOOLE_SOCK_TCP)
+```
+
+* `array $config`
+
+An array of client options, you can set the following options:
+
+```php
+$config = [
+ 'host' => '127.0.0.1',
+ 'port' => 1883,
+ 'time_out' => 5,
+ 'user_name' => '',
+ 'password' => '',
+ 'client_id' => '',
+ 'keep_alive' => 10,
+ 'protocol_name' => 'MQTT', // or MQIsdp
+ 'protocol_level' => 4, // or 3
+];
+```
+
+* `array $swConfig`
+
+To set the configuration of `Swoole\Coroutine\Client`, please see Swoole document: [set()](https://www.swoole.co.uk/docs/modules/swoole-coroutine-client-set)
+
+### connect()
+
+Connect Broker
+
+```php
+Simps\MQTT\Client->connect(bool $clean = true, array $will = [])
+```
+
+* `bool $clean`
+
+Clean session. default is `true`. see [Clean Session](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html#_Toc442180843)
+
+* `array $will`
+
+When a client is disconnected, Broker will automatically send a will message to other clients
+
+```php
+$will = [
+ 'topic' => '',
+ 'qos' => 1,
+ 'retain' => 0,
+ 'content' => '',
+];
+```
+
+### publish()
+
+push a message to a topic
+
+```php
+Simps\MQTT\Client->publish($topic, $content, $qos = 0, $dup = 0, $retain = 0)
+```
+
+### subscribe()
+
+Subscribe to one topic or multiple topics
+
+```php
+Simps\MQTT\Client->subscribe(array $topics)
+```
+
+* `array $topics`
+
+```php
+$topics = [
+ // topic => Qos
+ 'topic1' => 0,
+ 'topic2' => 1,
+];
+```
+
+### unSubscribe()
+
+Unsubscribe from a topic or multiple topics
+
+```php
+Simps\MQTT\Client->unSubscribe(array $topics)
+```
+
+* `array $topics`
+
+```php
+$topics = ['topic1', 'topic2'];
+```
+
+### close()
+
+Disconnect from Broker connect. The `DISCONNECT(14)` message is send to Broker
+
+```php
+Simps\MQTT\Client->close()
+```
+
+### recv()
+
+Receive messages
+
+```php
+Simps\MQTT\Client->recv(): bool|arary|string
+```
+
+### send()
+
+Send messages
+
+```php
+Simps\MQTT\Client->send(array $data, $response = true)
+```
+
+* `array $data`
+
+`$data` is the data to be sent and must contain information such as `type`
+
+* `bool $response`
+
+Are acknowledgements required. If `true`, `recv()` is called once
+
+### ping()
+
+Send a heartbeat
+
+```php
+Simps\MQTT\Client->ping()
+```
+
+### buildMessageId()
+
+Generate MessageId
+
+```php
+Simps\MQTT\Client->buildMessageId()
+```
+
+### genClientId()
+
+Generate ClientId
+
+```php
+Simps\MQTT\Client->genClientID()
+```
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..c094215
Binary files /dev/null and b/docs/favicon.ico differ
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..a1e7e0b
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,37 @@
+
+
+
+
+ Simps MQTT 文档
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/zh-cn/README.md b/docs/zh-cn/README.md
new file mode 100644
index 0000000..66f876b
--- /dev/null
+++ b/docs/zh-cn/README.md
@@ -0,0 +1,183 @@
+# MQTT 协程客户端
+
+适用于 PHP 的 MQTT 协议解析和协程客户端。
+
+[![Latest Stable Version](https://poser.pugx.org/simps/mqtt/v)](//packagist.org/packages/simps/mqtt)
+[![Total Downloads](https://poser.pugx.org/simps/mqtt/downloads)](//packagist.org/packages/simps/mqtt)
+[![Latest Unstable Version](https://poser.pugx.org/simps/mqtt/v/unstable)](//packagist.org/packages/simps/mqtt)
+[![License](https://poser.pugx.org/simps/mqtt/license)](https://github.com/simps/mqtt/blob/master/LICENSE)
+
+## 安装
+
+```bash
+composer require simps/mqtt
+```
+
+## 示例
+
+参考 [examples](./examples) 目录
+
+## Client API
+
+### __construct()
+
+创建一个MQTT客户端实例
+
+```php
+Simps\MQTT\Client::__construct(array $config, array $swConfig = [], int $type = SWOOLE_SOCK_TCP)
+```
+
+* 参数`array $config`
+
+客户端选项数组,可以设置以下选项:
+
+```php
+$config = [
+ 'host' => '127.0.0.1', // MQTT服务端IP
+ 'port' => 1883, // MQTT服务端端口
+ 'time_out' => 5, // 连接MQTT服务端超时时间,默认0.5秒
+ 'user_name' => '', // 用户名
+ 'password' => '', // 密码
+ 'client_id' => '', // 客户端id
+ 'keep_alive' => 10, // 默认0秒,设置成0代表禁用
+ 'protocol_name' => 'MQTT', // 协议名,默认为MQTT(3.1.1版本),也可为MQIsdp(3.1版本)
+ 'protocol_level' => 4, // 协议等级,MQTT为4,MQIsdp为3
+];
+```
+
+* 参数`array $swConfig`
+
+用于设置`Swoole\Coroutine\Client`的配置,请参考Swoole文档:[set()](https://wiki.swoole.com/#/coroutine_client/client?id=set)
+
+### connect()
+
+连接Broker
+
+```php
+Simps\MQTT\Client->connect(bool $clean = true, array $will = [])
+```
+
+* 参数`bool $clean`
+
+清理会话,默认为`true`
+
+具体描述请参考[清理会话 Clean Session](https://mcxiaoke.gitbook.io/mqtt/03-controlpackets/0301-connect#qing-li-hui-hua-clean-session)
+
+* 参数`array $will`
+
+遗嘱消息,当客户端断线后Broker会自动发送遗嘱消息给其它客户端
+
+需要设置的内容如下
+
+```php
+$will = [
+ 'topic' => '', // 主题
+ 'qos' => 1, // QoS等级
+ 'retain' => 0, // retain标记
+ 'content' => '', // content
+];
+```
+
+### publish()
+
+向某个主题发布一条消息
+
+```php
+Simps\MQTT\Client->publish($topic, $content, $qos = 0, $dup = 0, $retain = 0)
+```
+
+* 参数`$topic` 主题
+* 参数`$content` 内容
+* 参数`$qos` QoS等级,默认0
+* 参数`$dup` 重发标志,默认0
+* 参数`$retain` retain标记,默认0
+
+### subscribe()
+
+订阅一个主题或者多个主题
+
+```php
+Simps\MQTT\Client->subscribe(array $topics)
+```
+
+* 参数`array $topics`
+
+`$topics`的`key`是主题,值为`QoS`的数组,例如
+
+```php
+$topics = [
+ // 主题 => Qos
+ 'topic1' => 0,
+ 'topic2' => 1,
+];
+```
+
+### unSubscribe()
+
+取消订阅一个主题或者多个主题
+
+```php
+Simps\MQTT\Client->unSubscribe(array $topics)
+```
+
+* 参数`array $topics`
+
+```php
+$topics = ['topic1', 'topic2'];
+```
+
+### close()
+
+正常断开与Broker的连接,`DISCONNECT(14)`报文会被发送到Broker
+
+```php
+Simps\MQTT\Client->close()
+```
+
+### recv()
+
+接收消息
+
+```php
+Simps\MQTT\Client->recv(): bool|arary|string
+```
+
+### send()
+
+发送消息
+
+```php
+Simps\MQTT\Client->send(array $data, $response = true)
+```
+
+* 参数`array $data`
+
+`$data`是需要发送的数据,必须包含`type`等信息
+
+* 参数`bool $response`
+
+是否需要回执。如果为`true`,会调用一次`recv()`
+
+### ping()
+
+发送心跳包
+
+```php
+Simps\MQTT\Client->ping()
+```
+
+### buildMessageId()
+
+生成MessageId
+
+```php
+Simps\MQTT\Client->buildMessageId()
+```
+
+### genClientId()
+
+生成ClientId
+
+```php
+Simps\MQTT\Client->genClientID()
+```
diff --git a/examples/server.php b/examples/server.php
index 7f29af6..de501e5 100644
--- a/examples/server.php
+++ b/examples/server.php
@@ -97,9 +97,9 @@
$payload = [];
foreach ($data['topics'] as $k => $qos) {
if (is_numeric($qos) && $qos < 3) {
- $payload[] = chr($qos);
+ $payload[] = $qos;
} else {
- $payload[] = chr(0x80);
+ $payload[] = 0x80;
}
}
$server->send(
diff --git a/src/Packet/Pack.php b/src/Packet/Pack.php
index 3d66f85..35b93ff 100644
--- a/src/Packet/Pack.php
+++ b/src/Packet/Pack.php
@@ -88,10 +88,10 @@ public static function subscribe(array $array): string
$id = $array['message_id'];
$body = pack('n', $id);
foreach ($array['topics'] as $topic => $qos) {
- $body .= Pack::string($topic);
+ $body .= static::string($topic);
$body .= chr($qos);
}
- $head = Pack::packHeader(Types::SUBSCRIBE, strlen($body), 0, 1);
+ $head = static::packHeader(Types::SUBSCRIBE, strlen($body), 0, 1);
return $head . $body;
}