homeos/app/Livewire/Modals/AssignDevice.php

83 lines
2.6 KiB
PHP

<?php
namespace App\Livewire\Modals;
use App\Models\Device;
use App\Models\DiscoveryFinding;
use App\Models\Room;
use Livewire\Attributes\Computed;
use LivewireUI\Modal\ModalComponent;
class AssignDevice extends ModalComponent
{
public string $findingUuid = '';
public string $name = '';
public ?int $roomId = null;
public static function modalMaxWidth(): string
{
return 'lg';
}
public function mount(string $finding): void
{
$model = DiscoveryFinding::where('uuid', $finding)->firstOrFail();
$this->findingUuid = $model->uuid;
$this->name = $model->name ?? $model->identifier;
}
#[Computed]
public function finding(): DiscoveryFinding
{
return DiscoveryFinding::where('uuid', $this->findingUuid)->firstOrFail();
}
public function assign()
{
$this->validate([
'name' => 'required|string|max:100',
'roomId' => 'nullable|integer|exists:rooms,id',
]);
$finding = $this->finding();
$isShelly = $finding->vendor === 'Shelly';
// The Shelly MQTT topic prefix is its device id — the mDNS service INSTANCE name
// (finding->name), not the slugified topic identifier which carries the _shelly._tcp suffix.
$prefix = $isShelly ? ($finding->name ?: $finding->identifier) : null;
// The device may already have auto-onboarded from its MQTT traffic — reuse that row by
// prefix so assigning just names it and puts it in a room (no duplicate). Devices sign in
// with the shared `shelly` account, so no per-device credential is provisioned here.
$device = ($prefix ? Device::where('config->mqtt_prefix', $prefix)->first() : null)
?? new Device;
$device->fill([
'name' => $this->name,
'vendor' => $finding->vendor,
'model' => $finding->model ?: $device->model,
'protocol' => $isShelly ? 'mqtt' : $device->protocol,
'room_id' => $this->roomId ?: null,
'status' => 'active',
]);
$device->config = array_merge($device->config ?? [], $prefix ? ['mqtt_prefix' => $prefix] : []);
$device->save();
$finding->update(['status' => 'assigned', 'device_id' => $device->id]);
$this->closeModal();
return redirect()->route('devices.show', $device);
}
public function render()
{
return view('livewire.modals.assign-device', [
'finding' => $this->finding(),
'rooms' => Room::orderBy('sort')->orderBy('name')->get(),
]);
}
}