diff --git a/.env.example b/.env.example index 73869d2..7df5690 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,6 @@ APP_NAME=HomeOS +# Development defaults. For production set APP_ENV=production and APP_DEBUG=false +# (otherwise exceptions are exposed and the demo household is seeded). APP_ENV=local APP_KEY= APP_DEBUG=true diff --git a/README.md b/README.md index cd88a8c..1e98bd1 100644 --- a/README.md +++ b/README.md @@ -22,8 +22,17 @@ Then open **http://localhost** and sign in with the seeded dev admin: - **admin@homeos.local** / **homeos-dev** ← change this for anything but local dev. -For production, set strong values in `.env` for `DB_PASSWORD`, the `REVERB_APP_*` -keys and `HOMEOS_ADMIN_PASSWORD`, and run `php artisan key:generate`. +### Production + +`.env.example` ships **development** defaults. For a real deployment you **must**: + +- set `APP_ENV=production` and `APP_DEBUG=false` (otherwise exceptions are exposed + and the demo household is seeded into your real database); +- set strong values for `DB_PASSWORD`, the `REVERB_APP_*` keys and + `HOMEOS_ADMIN_PASSWORD` (seeding aborts if the admin password is unset outside + local/testing), and run `php artisan key:generate`. + +The demo seeder (`DemoHomeSeeder`) only runs in local/testing. ## Everyday commands (in-container, R8) diff --git a/app/Services/HomeStatus.php b/app/Services/HomeStatus.php index f9c4682..048b1f7 100644 --- a/app/Services/HomeStatus.php +++ b/app/Services/HomeStatus.php @@ -40,33 +40,35 @@ class HomeStatus /** @return array */ public function warnings(Collection $devices): array { - $entities = $devices->flatMap->entities; $warnings = []; - foreach ($devices->reject->isOnline() as $device) { - $warnings[] = [ - 'level' => 'offline', 'icon' => 'devices', - 'title' => $device->name, 'meta' => __('devices.offline'), 'link' => null, - ]; - } - - foreach ($entities as $entity) { - if ($entity->type === 'contact' && data_get($entity->state, 'state.open') === true) { + // Iterate devices (already loaded) → entities so we never lazy-load $entity->device (no N+1). + foreach ($devices as $device) { + if (! $device->isOnline()) { $warnings[] = [ - 'level' => 'warning', 'icon' => 'window', - 'title' => $entity->device->name, 'meta' => __('devices.open'), 'link' => null, + 'level' => 'offline', 'icon' => 'devices', + 'title' => $device->name, 'meta' => __('devices.offline'), 'link' => null, ]; } - if ($entity->type === 'battery') { - $percent = (int) data_get($entity->state, 'state.percent', 100); - if ($percent < self::LOW_BATTERY) { + foreach ($device->entities as $entity) { + if ($entity->type === 'contact' && data_get($entity->state, 'state.open') === true) { $warnings[] = [ - 'level' => 'warning', 'icon' => 'alert', - 'title' => $entity->device->name, - 'meta' => __('devices.battery').': '.$percent.'%', 'link' => null, + 'level' => 'warning', 'icon' => 'window', + 'title' => $device->name, 'meta' => __('devices.open'), 'link' => null, ]; } + + if ($entity->type === 'battery') { + $percent = (int) data_get($entity->state, 'state.percent', 100); + if ($percent < self::LOW_BATTERY) { + $warnings[] = [ + 'level' => 'warning', 'icon' => 'alert', + 'title' => $device->name, + 'meta' => __('devices.battery').': '.$percent.'%', 'link' => null, + ]; + } + } } }