$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> * @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 $status * @return array */ 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; } }