state?->state, 'on', false); return $this->setOn($entity, ! $current, $source); } public function setOn(Entity $entity, bool $on, string $source = 'user'): Command { return $this->run( $entity->device, $entity, $on ? 'turn_on' : 'turn_off', ['on' => $on], $source, fn (DeviceDriver $driver) => $on ? $driver->turnOn($entity) : $driver->turnOff($entity), ); } public function reboot(Device $device, string $source = 'user'): Command { return $this->run($device, null, 'reboot', [], $source, fn (DeviceDriver $driver) => $driver->reboot($device)); } public function setLight(Entity $entity, array $params, string $source = 'user'): Command { return $this->run($entity->device, $entity, 'set_light', $params, $source, fn (DeviceDriver $driver) => $driver->setLight($entity, $params)); } private function run(Device $device, ?Entity $entity, string $command, array $payload, string $source, callable $action): Command { $result = 'ok'; try { $action($this->driverFor($device)); } catch (\Throwable $e) { report($e); $result = 'error: '.$e->getMessage(); } return Command::create([ 'device_id' => $device->id, 'entity_id' => $entity?->id, 'source' => $source, 'user_id' => Auth::id(), 'command' => $command, 'payload' => $payload, 'result' => $result, ]); } private function driverFor(Device $device): DeviceDriver { return match (true) { $device->vendor === 'Shelly' && $device->protocol === 'mqtt' => app(ShellyMqttDriver::class), default => throw new \RuntimeException("No driver for {$device->vendor}/{$device->protocol}."), }; } }