130 lines
4.5 KiB
PHP
130 lines
4.5 KiB
PHP
<?php
|
||
|
||
namespace app\modules\api\components;
|
||
|
||
use PhpMqtt\Client\MQTTClient;
|
||
|
||
class Mqtt
|
||
{
|
||
|
||
public $mqtt;
|
||
public $data = [];
|
||
|
||
public function __construct()
|
||
{
|
||
try {
|
||
$redis_name = "api:cxaibc:mqtt:config";
|
||
$data = \Yii::$app->redis->get($redis_name);
|
||
if (!empty($data)) {
|
||
$data = json_decode($data, true);
|
||
$server = $data['mqtt_server'];
|
||
$port = intval($data['mqtt_port']);
|
||
$username = $data['mqtt_user'];
|
||
$password = $data['mqtt_pass'];
|
||
} else {
|
||
$server = \Yii::$app->params['mqtt']['server'];
|
||
$port = \Yii::$app->params['mqtt']['port'];
|
||
$username = \Yii::$app->params['mqtt']['username'];
|
||
$password = \Yii::$app->params['mqtt']['password'];
|
||
}
|
||
$clientId = md5(microtime(true));
|
||
$this->mqtt = new MqttClient($server, $port, $clientId);
|
||
$this->mqtt->connect($username, $password);
|
||
} catch (\Exception $e) {
|
||
$this->data = ['code' => 1, 'msg' => "链接mqtt失败"];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @ Author : Lw
|
||
* @ CreateTime : 2022-11-02
|
||
* @ Info : 启动,关闭车辆
|
||
* @param string $number 球车编号
|
||
* @param int $OPERATION_ENABLE -- 0.禁止使用,1.允许使用
|
||
* @param int $OPERATION_LEVEL -- 0.助力模式,1.遥杆模式,2.跟随模式 -- 现在应该是传入0
|
||
* @return array 此操作仅做请求,最终车辆的信息请查找redis中车辆的最新数据
|
||
*/
|
||
public function sendOpen(string $number, int $OPERATION_ENABLE, int $OPERATION_LEVEL)
|
||
{
|
||
if (!empty($this->data)) {
|
||
return $this->data;
|
||
}
|
||
// 车辆状态,1.启动,0.关闭
|
||
$redis_name = "api:cxaibc:sendOpen:{$number}";
|
||
try {
|
||
$time_base = time();
|
||
$str_res = pack('l', $time_base) . pack('C', $OPERATION_ENABLE) . pack('C', $OPERATION_LEVEL) . strtoupper(md5(str_pad($number, 16, "0", STR_PAD_LEFT) . '+' . $time_base));//请求启动车辆
|
||
$res = $this->x_o($str_res);
|
||
$str_res .= chr($res);
|
||
$this->mqtt->publish("$number/Permission", $str_res);
|
||
// $this->sendAck($number);
|
||
\Yii::$app->redis->set($redis_name, $OPERATION_ENABLE);
|
||
} catch (\Exception $e) {
|
||
return ['code' => 1, 'msg' => $e->getMessage()];
|
||
}
|
||
$this->getInfo($number,1);
|
||
return ['code' => 0, 'msg' => '成功'];
|
||
}
|
||
|
||
/**
|
||
* @ Author : Lw
|
||
* @ CreateTime : 2022-11-02
|
||
* @ Info : 主动获取车辆状态,请求后对方服务器会及时推送一条消息到本服务器上
|
||
* @param string $number 球车编号
|
||
* @param int $type 类型,1.车辆详情,2、定位信息,4.告警信息,7.三种信息都查
|
||
* @return array 查询的信息都会订阅中,先存入redis后再存入mysql,此操作只做请求
|
||
*/
|
||
public function getInfo(string $number, int $type)
|
||
{
|
||
if (!empty($this->data)) {
|
||
return $this->data;
|
||
}
|
||
try {
|
||
$time_base = time();
|
||
$str_res = pack('l', $time_base) . pack('L', $type);
|
||
$res = $this->x_o($str_res);
|
||
$str_res .= chr($res);
|
||
$this->mqtt->publish("$number/Query", $str_res);
|
||
// $this->sendAck($number);
|
||
} catch (\Exception $e) {
|
||
return ['code' => 1, 'msg' => $e->getMessage()];
|
||
}
|
||
return ['code' => 0, 'msg' => ''];
|
||
}
|
||
|
||
/**
|
||
* @ Author : Lw
|
||
* @ CreateTime : 2022-11-07
|
||
* @ Info : 发送ack消息,用于同步时间戳
|
||
*/
|
||
public function sendAck(string $number)
|
||
{
|
||
if (!empty($this->data)) {
|
||
return $this->data;
|
||
}
|
||
try {
|
||
$time_base = time();
|
||
$str_res = pack('l', $time_base) . pack('l', 1);
|
||
$res = $this->x_o($str_res);
|
||
$str_res .= chr($res);
|
||
$this->mqtt->publish("$number/Ack", $str_res);
|
||
} catch (\Exception $e) {
|
||
return ['code' => 1, 'msg' => $e->getMessage()];
|
||
}
|
||
return ['code' => 0, 'msg' => ''];
|
||
}
|
||
|
||
public function x_o($data)
|
||
{
|
||
$t = 0;
|
||
for ($i = 0; $i < strlen($data); $i++) {
|
||
if ($i) {
|
||
$t ^= ord($data[$i]);
|
||
} else {
|
||
$t = ord($data[$i]) ^ 0;
|
||
}
|
||
}
|
||
return $t;
|
||
}
|
||
|
||
} |