186 lines
6.1 KiB
PHP
186 lines
6.1 KiB
PHP
<?php
|
|
|
|
namespace classes;
|
|
|
|
require_once WD . '/interfaces/shelly_transport_i.php';
|
|
|
|
use Exception;
|
|
use interfaces\shelly_transport_i;
|
|
|
|
class gateway_shelly_transport implements shelly_transport_i
|
|
{
|
|
public function __construct(
|
|
private readonly ?edge_gateway_manager $manager = null,
|
|
private readonly bool $localOnly = false
|
|
)
|
|
{
|
|
}
|
|
|
|
public function requireModuleEnabled(): void
|
|
{
|
|
// Gateway mode is department-scoped and does not depend on the Shelly cloud module flag.
|
|
}
|
|
|
|
public function requireValidSecretKey(): void
|
|
{
|
|
// Gateway mode does not use the Shelly cloud auth key.
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function sendPostRequest(string $endpoint, array $data, ?int $department_id = null): array|object|null
|
|
{
|
|
if ($department_id === null || $department_id <= 0) {
|
|
throw new Exception('A department_id is required for gateway Shelly transport');
|
|
}
|
|
|
|
return match ($endpoint) {
|
|
'/v2/devices/api/get' => $this->handleGetStates($department_id, $data),
|
|
'/v2/devices/api/set/switch' => $this->handleSetSwitch($department_id, $data),
|
|
'/v2/devices/api/batch/get' => $this->handleBatchGetStates($department_id, $data),
|
|
'/v2/devices/api/batch/set/switch' => $this->handleBatchSetSwitch($department_id, $data),
|
|
default => throw new Exception('Unsupported gateway Shelly transport endpoint: ' . $endpoint),
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @return array<int,array<string,mixed>>
|
|
* @throws Exception
|
|
*/
|
|
private function handleGetStates(int $departmentId, array $data): array
|
|
{
|
|
$ids = array_values(array_filter(
|
|
array_map(static fn(mixed $value): string => trim((string)$value), (array)($data['ids'] ?? [])),
|
|
static fn(string $value): bool => $value !== ''
|
|
));
|
|
|
|
$result = [];
|
|
foreach ($ids as $logicalRelayId) {
|
|
$status = $this->localOnly
|
|
? $this->manager()->dispatchRelayStatusLocalOnly($departmentId, $logicalRelayId)
|
|
: $this->manager()->dispatchRelayStatus($departmentId, $logicalRelayId);
|
|
$result[] = $this->normalizeRelayPayload($logicalRelayId, $status);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function handleSetSwitch(int $departmentId, array $data): array
|
|
{
|
|
$logicalRelayId = trim((string)($data['id'] ?? ''));
|
|
if ($logicalRelayId === '') {
|
|
throw new Exception('Shelly gateway switch requests require an id');
|
|
}
|
|
|
|
$toggleAfter = $this->normalizeToggleAfter(
|
|
$data['toggle_after'] ?? $data['toggleAfter'] ?? $data['timer'] ?? null
|
|
);
|
|
|
|
$status = $this->localOnly
|
|
? $this->manager()->dispatchRelaySwitchLocalOnlyWithTimer(
|
|
$departmentId,
|
|
$logicalRelayId,
|
|
(bool)($data['on'] ?? false),
|
|
$toggleAfter
|
|
)
|
|
: $this->manager()->dispatchRelaySwitchWithTimer(
|
|
$departmentId,
|
|
$logicalRelayId,
|
|
(bool)($data['on'] ?? false),
|
|
$toggleAfter
|
|
);
|
|
|
|
return [$this->normalizeRelayPayload($logicalRelayId, $status)];
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function handleBatchGetStates(int $departmentId, array $data): array
|
|
{
|
|
$requests = [];
|
|
foreach ((array)($data['commands'] ?? $data['targets'] ?? []) as $entry) {
|
|
$command = is_array($entry) ? $entry : ['relay_id' => $entry];
|
|
$relayId = trim((string)($command['relay_id'] ?? $command['relayId'] ?? $command['id'] ?? ''));
|
|
if ($relayId === '') {
|
|
continue;
|
|
}
|
|
$requests[] = [
|
|
'target' => strtoupper(trim((string)($command['target'] ?? $relayId))),
|
|
'relay_id' => $relayId,
|
|
];
|
|
}
|
|
|
|
return $this->manager()->queueRelayStatusBatch($departmentId, $requests, null, $this->localOnly);
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
private function handleBatchSetSwitch(int $departmentId, array $data): array
|
|
{
|
|
$requests = [];
|
|
foreach ((array)($data['commands'] ?? []) as $entry) {
|
|
if (!is_array($entry)) {
|
|
continue;
|
|
}
|
|
$relayId = trim((string)($entry['relay_id'] ?? $entry['relayId'] ?? $entry['id'] ?? ''));
|
|
if ($relayId === '') {
|
|
continue;
|
|
}
|
|
$requests[] = [
|
|
'target' => strtoupper(trim((string)($entry['target'] ?? $relayId))),
|
|
'relay_id' => $relayId,
|
|
'on' => (bool)($entry['on'] ?? false),
|
|
'toggle_after' => $entry['toggle_after'] ?? $entry['toggleAfter'] ?? $entry['timer'] ?? null,
|
|
];
|
|
}
|
|
|
|
return $this->manager()->queueRelaySwitchBatch($departmentId, $requests, null, $this->localOnly);
|
|
}
|
|
|
|
/**
|
|
* @param array<string,mixed> $status
|
|
* @return array<string,mixed>
|
|
*/
|
|
private function normalizeRelayPayload(string $logicalRelayId, array $status): array
|
|
{
|
|
$on = (bool)($status['on'] ?? $status['output'] ?? false);
|
|
$online = (bool)($status['online'] ?? true);
|
|
|
|
return [
|
|
'id' => $logicalRelayId,
|
|
'relay_id' => $logicalRelayId,
|
|
'online' => $online,
|
|
'on' => $on,
|
|
'status' => [
|
|
'switch:0' => [
|
|
'output' => $on,
|
|
],
|
|
],
|
|
'binding' => (array)($status['binding'] ?? []),
|
|
'execution' => (array)($status['execution'] ?? []),
|
|
'raw' => (array)($status['raw'] ?? []),
|
|
];
|
|
}
|
|
|
|
private function manager(): edge_gateway_manager
|
|
{
|
|
return $this->manager ?? new edge_gateway_manager();
|
|
}
|
|
|
|
private function normalizeToggleAfter(mixed $toggleAfter): ?int
|
|
{
|
|
if ($toggleAfter === null || $toggleAfter === '') {
|
|
return null;
|
|
}
|
|
|
|
$seconds = (int)$toggleAfter;
|
|
return $seconds > 0 ? $seconds : null;
|
|
}
|
|
}
|