homeos/app/Livewire/Dashboard.php

89 lines
3.1 KiB
PHP

<?php
namespace App\Livewire;
use App\Models\Room;
use App\Services\SystemHealth;
use Illuminate\Support\Collection;
use Livewire\Attributes\Layout;
use Livewire\Component;
#[Layout('layouts.app')]
class Dashboard extends Component
{
private const LOW_BATTERY = 20;
public function render()
{
$rooms = Room::query()
->with(['devices' => fn ($q) => $q->orderBy('name'), 'devices.entities.state'])
->orderBy('sort')->orderBy('name')
->get();
$devices = $rooms->flatMap->devices;
$entities = $devices->flatMap->entities;
$summary = [
'devices_online' => $devices->filter->isOnline()->count(),
'devices_total' => $devices->count(),
'lights_on' => $this->countWhere($entities, fn ($e) => in_array($e->type, ['light', 'switch']) && data_get($e->state, 'state.on') === true),
'contacts_open' => $this->countWhere($entities, fn ($e) => $e->type === 'contact' && data_get($e->state, 'state.open') === true),
'low_battery' => $this->countWhere($entities, fn ($e) => $e->type === 'battery' && (int) data_get($e->state, 'state.percent', 100) < self::LOW_BATTERY),
];
return view('livewire.dashboard', [
'rooms' => $rooms,
'summary' => $summary,
'warnings' => $this->warnings($devices, $entities),
]);
}
/** @return array<int, array{level:string,icon:string,title:string,meta:?string,link:?string}> */
protected function warnings(Collection $devices, Collection $entities): array
{
$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) {
$warnings[] = [
'level' => 'warning', 'icon' => 'window',
'title' => $entity->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' => $entity->device->name,
'meta' => __('devices.battery').': '.$percent.'%', 'link' => null,
];
}
}
}
if (! app(SystemHealth::class)->allOnline()) {
$warnings[] = [
'level' => 'warning', 'icon' => 'activity',
'title' => __('dashboard.warn_host'), 'meta' => __('dashboard.warn_host_meta'),
'link' => route('host'),
];
}
return $warnings;
}
protected function countWhere(Collection $entities, callable $fn): int
{
return $entities->filter($fn)->count();
}
}