193 lines
5.1 KiB
PHP
193 lines
5.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\common\workerman\wechat\traits;
|
|
use GuzzleHttp\Client;
|
|
|
|
/**
|
|
* 设备能力
|
|
* - 检查设备合法性
|
|
* - 获取设备信息
|
|
* - 更新设备状态
|
|
* - 设备在线状态
|
|
* - 更新心跳时间
|
|
*
|
|
* @author Qasim
|
|
* @package app\traits
|
|
*/
|
|
trait DeviceTrait
|
|
{
|
|
use LoggerTrait, CacheTrait;
|
|
|
|
protected static $CLIENT_TOKEN_TTL = 3600;
|
|
protected static $DEVICE_TOKEN_TTL = 86400;
|
|
|
|
/**
|
|
* 检查设备
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @return bool
|
|
*/
|
|
protected function checkDevice(string $deviceId): bool
|
|
{
|
|
// 获取设备信息
|
|
$deviceInfo = $this->getDeviceInfo($deviceId);
|
|
return $deviceInfo ? true : false;
|
|
}
|
|
|
|
/**
|
|
* 获取设备信息
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @return array
|
|
*/
|
|
protected function getDeviceInfo(string $deviceId): array
|
|
{
|
|
try {
|
|
|
|
$result = \app\common\service\ToolsService::Auth()->checkDevice($deviceId);
|
|
if((int)$result['code'] === 10000){
|
|
return $result['data'];
|
|
}else{
|
|
return [];
|
|
}
|
|
} catch (\Throwable $e) {
|
|
//throw $th;
|
|
$this->withChannel('wechat_socket')->withLevel('error')->withTitle('updateDevices')->withContext([
|
|
'deviceId' => $deviceId,
|
|
'trace' => $e->getTraceAsString(),
|
|
])->log();
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新设备池
|
|
*
|
|
* @param array $device 设备池
|
|
* @return void
|
|
*/
|
|
protected function updateDevices(array $device): void
|
|
{
|
|
try {
|
|
|
|
$body = \app\common\service\ToolsService::Auth()->deviceUpdate($device);
|
|
|
|
$this->withChannel('wechat_socket')->withLevel('info')->withTitle('updateDevices')->withContext([
|
|
'deviceInfo' => $body
|
|
])->log();
|
|
|
|
} catch (\Throwable $e) {
|
|
//throw $th;
|
|
|
|
$this->withChannel('wechat_socket')->withLevel('error')->withTitle('updateDevices')->withContext([
|
|
'deviceInfo' => $device,
|
|
'trace' => $e->getTraceAsString(),
|
|
])->log();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 检查设备是否在线
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @return bool
|
|
*/
|
|
protected function isDeviceOnline(string $deviceId): bool
|
|
{
|
|
$statusKey = $this->getDeviceKey($deviceId, 'status');
|
|
$status = $this->redis()->get($statusKey);
|
|
|
|
return $status === 'online';
|
|
}
|
|
|
|
/**
|
|
* 更新设备状态
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @param bool $online 是否在线
|
|
* @return void
|
|
*/
|
|
protected function updateDeviceStatus(string $deviceId, bool $online): void
|
|
{
|
|
$this->redis()->set(
|
|
$this->getDeviceKey($deviceId, 'status'),
|
|
$online ? 'online' : 'offline'
|
|
);
|
|
|
|
if ($online) {
|
|
$this->updateDeviceHeartbeat($deviceId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 更新设备心跳时间
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @return void
|
|
*/
|
|
protected function updateDeviceHeartbeat(string $deviceId): void
|
|
{
|
|
$this->redis()->set(
|
|
$this->getDeviceKey($deviceId, 'heartbeat'),
|
|
time()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 验证Token
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @param string $token Token
|
|
* @param string $type 类型 device: 设备 token: 客户端
|
|
* @return bool
|
|
*/
|
|
protected function verifyToken(string $deviceId, string $token, string $type = 'device'): bool
|
|
{
|
|
|
|
if ($type === 'device') {
|
|
$tokenKey = $this->getDeviceKey($deviceId, 'token');
|
|
$tokenValue = $this->redis()->get($tokenKey);
|
|
} else {
|
|
$tokenKey = $this->getClientKey($deviceId, 'token');
|
|
$tokenValue = $this->redis()->get(trim($tokenKey));
|
|
}
|
|
|
|
|
|
$this->withChannel('wechat_socket')->withLevel('info')->withTitle('verifyToken')->withContext([
|
|
'type' => $type,
|
|
'device' => $deviceId,
|
|
'exists' => $this->redis()->exists($tokenKey),
|
|
'tokenKey' => $tokenKey,
|
|
'Token' => $token,
|
|
'tokenValue' => $tokenValue
|
|
])->log();
|
|
|
|
return $token === $tokenValue;
|
|
}
|
|
|
|
/**
|
|
* 设置Token
|
|
*
|
|
* @param string $deviceId 设备ID
|
|
* @param string $token Token
|
|
* @param string $type 类型 device: 设备 token: 客户端
|
|
* @return string
|
|
*/
|
|
protected function setToken(string $deviceId, string $type = 'device'): string
|
|
{
|
|
if ($type === 'device') {
|
|
$tokenKey = $this->getDeviceKey($deviceId, 'token');
|
|
} else {
|
|
$tokenKey = $this->getClientKey($deviceId, 'token');
|
|
}
|
|
|
|
// 生成并缓存Token
|
|
$token = hash('sha256', $deviceId . $type . time() . uniqid());
|
|
$this->redis()->setex($tokenKey, $type === 'device' ? self::$DEVICE_TOKEN_TTL : self::$CLIENT_TOKEN_TTL, $token);
|
|
|
|
return $token;
|
|
}
|
|
}
|