Files
iot-api/inc/lib/YandexIoT.php
2025-07-31 17:00:53 +03:00

199 lines
5.8 KiB
PHP

<?php
class YandexIoT
{
private string $clientId;
private string $clientSecret;
private ?string $accessToken = null;
private ?string $refreshToken = null;
public function __construct(
string $clientId,
string $clientSecret,
?string $accessToken = null,
?string $refreshToken = null
) {
$this->clientId = $clientId;
$this->clientSecret = $clientSecret;
$this->accessToken = $accessToken;
$this->refreshToken = $refreshToken;
}
/**
* @throws JsonException
*/
public function initFromFile(string $file): self
{
if (!file_exists($file)) {
throw new RuntimeException('Файл для инициализации не найден');
}
$data = json_decode(file_get_contents($file), true, 512, JSON_THROW_ON_ERROR);
$this->accessToken = $data['access_token'] ?? null;
$this->refreshToken = $data['access_token'] ?? null;
return $this;
}
/**
* Отправка запроса
*
* @param string $url
* @param array $headers
* @param array|null $data
* @param string|null $method
* @return array
* @throws JsonException
*/
public static function sendRequest(string $url, array $headers = [], ?array $data = null, ?string $method = null): array
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if (!empty($method)) {
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
}
if (!empty($data)) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
}
curl_setopt($ch, CURLOPT_FAILONERROR, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_VERBOSE, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$result = curl_exec($ch);
$result = json_decode($result, true, 512, JSON_THROW_ON_ERROR);
curl_close($ch);
return $result;
}
/**
* @throws JsonException
*/
public function sendYandexRequest(
string $function,
array $additionalHeaders = [],
?array $data = null,
?string $method = null
): array {
$apiUrl = 'https://api.iot.yandex.net';
$url = $apiUrl . $function;
$headers = array_merge(['Authorization: Bearer ' . $this->getAccessToken()], $additionalHeaders);
return (self::sendRequest($url, $headers, $data, $method));
}
/**
* @throws JsonException
*/
public function getPowerState(string $deviceId): bool
{
$function = '/v1.0/devices/' . $deviceId;
$result = $this->sendYandexRequest($function);
if (isset($result['capabilities'])) {
foreach ($result['capabilities'] as $capability) {
if ($capability['type'] === 'devices.capabilities.on_off') {
return (int)$capability['state']['value'] === 1;
}
}
}
return false;
}
/**
* @throws JsonException
*/
public function getProps(string $deviceId): array
{
$res = [];
$function = '/v1.0/devices/' . $deviceId;
$result = $this->sendYandexRequest($function);
// состояние по умолчанию
$res['state'] = false;
if (isset($result['capabilities'])) {
foreach ($result['capabilities'] as $capability) {
if ($capability['type'] === 'devices.capabilities.on_off' && (int)$capability['state']['value'] === 1) {
$res['state'] = true;
break;
}
}
}
if (isset($result['properties'])) {
foreach ($result['properties'] as $prop) {
$res[$prop['state']['instance']] = $prop['state']['value'];
}
}
return $res;
}
/**
* @throws JsonException
*/
public function getInfo(): array
{
$function = '/v1.0/user/info';
return $this->sendYandexRequest($function);
}
/**
* @throws JsonException
*/
public function setPowerState(string $deviceId, bool $state): bool
{
$function = '/v1.0/devices/actions';
$headers = ['Content-Type: application/json'];
$data = [
'devices' => [
'actions' => [
'state' => [
'instance' => 'on',
'value' => $state ? 'true' : 'false',
],
'type' => 'devices.capabilities.on_off',
],
'id' => $deviceId,
],
];
$result = $this->sendYandexRequest($function, $headers, $data);
return isset($result['status']) && $result['status'] === 'ok';
}
public function getAccessToken(): ?string
{
return $this->accessToken;
}
public function getRefreshToken(): ?string
{
return $this->refreshToken;
}
/**
* @throws JsonException
*/
public function updateToken(): bool
{
$url = 'https://oauth.yandex.ru/token';
$auth = base64_encode($this->clientId . ':' . $this->clientSecret);
$headers = [
'Authorization: Basic ' . $auth,
'application/x-www-form-urlencoded'
];
$data = [
'grant_type' => 'refresh_token',
'refresh_token' => $this->getRefreshToken(),
];
$response = self::sendRequest($url, $headers, $data);
if (isset($response['access_token'])) {
$this->accessToken = '';
$this->refreshToken = '';
return true;
}
return false;
}
}