Fix R15: Shelly prefix from mDNS instance, discovery broadcast once, targeted confirm
- AssignDevice derives the Shelly MQTT prefix from the mDNS service instance name (the device id) instead of the slugified topic identifier (which carries the _shelly._tcp suffix); non-Shelly devices get no prefix. - IngestDiscoveryMessage broadcasts DeviceDiscovered only on first creation, not on every retained/periodic re-publish. - The generic Confirm modal can target its event at the opening component (->to), so a shared event name can't be caught by an unrelated component. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>feat/phase-1-bootstrap
parent
b85d2f60fe
commit
7d4c9c024e
|
|
@ -46,7 +46,9 @@ class IngestDiscoveryMessage implements ShouldQueue
|
|||
],
|
||||
);
|
||||
|
||||
if (($existing?->status ?? 'new') === 'new') {
|
||||
// Announce only on FIRST discovery — the sidecar re-publishes retained/periodic
|
||||
// messages, so broadcasting on every message would spam the "Neue Geräte" panel.
|
||||
if ($existing === null) {
|
||||
DeviceDiscovered::dispatch($finding->uuid);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,13 +42,18 @@ class AssignDevice extends ModalComponent
|
|||
]);
|
||||
|
||||
$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;
|
||||
|
||||
$device = Device::create([
|
||||
'name' => $this->name,
|
||||
'vendor' => $finding->vendor,
|
||||
'model' => $finding->model,
|
||||
'protocol' => $finding->vendor === 'Shelly' ? 'mqtt' : null,
|
||||
'config' => ['mqtt_prefix' => $finding->identifier],
|
||||
'protocol' => $isShelly ? 'mqtt' : null,
|
||||
'config' => $prefix ? ['mqtt_prefix' => $prefix] : null,
|
||||
'room_id' => $this->roomId ?: null,
|
||||
'status' => 'active',
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ class Confirm extends ModalComponent
|
|||
public string $body = '';
|
||||
public string $confirmLabel = '';
|
||||
public string $event = '';
|
||||
public string $to = '';
|
||||
public bool $danger = false;
|
||||
|
||||
public static function modalMaxWidth(): string
|
||||
|
|
@ -24,18 +25,23 @@ class Confirm extends ModalComponent
|
|||
return 'md';
|
||||
}
|
||||
|
||||
public function mount(string $title, string $body, string $confirmLabel, string $event, bool $danger = false): void
|
||||
public function mount(string $title, string $body, string $confirmLabel, string $event, string $to = '', bool $danger = false): void
|
||||
{
|
||||
$this->title = $title;
|
||||
$this->body = $body;
|
||||
$this->confirmLabel = $confirmLabel;
|
||||
$this->event = $event;
|
||||
$this->to = $to;
|
||||
$this->danger = $danger;
|
||||
}
|
||||
|
||||
public function confirm(): void
|
||||
{
|
||||
$this->dispatch($this->event);
|
||||
// Target the opener (if given) so an event name can't collide with another component.
|
||||
$this->to !== ''
|
||||
? $this->dispatch($this->event)->to($this->to)
|
||||
: $this->dispatch($this->event);
|
||||
|
||||
$this->closeModal();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@
|
|||
<x-panel :title="__('devices.actions')">
|
||||
<div class="flex flex-col gap-2">
|
||||
<button type="button"
|
||||
wire:click="$dispatch('openModal', { component: 'modals.confirm', arguments: { title: @js(__('devices.restart_confirm_title')), body: @js(__('devices.restart_confirm_body', ['name' => $device->name])), confirmLabel: @js(__('devices.restart')), event: 'restartDevice', danger: true } })"
|
||||
wire:click="$dispatch('openModal', { component: 'modals.confirm', arguments: { title: @js(__('devices.restart_confirm_title')), body: @js(__('devices.restart_confirm_body', ['name' => $device->name])), confirmLabel: @js(__('devices.restart')), event: 'restartDevice', to: 'devices.show', danger: true } })"
|
||||
class="flex items-center gap-2.5 rounded-lg border border-line-soft bg-raised px-3 py-2.5 text-[13px] font-semibold text-ink hover:border-line transition-colors">
|
||||
<x-icon name="activity" :size="16" class="text-ink-2" /> {{ __('devices.restart') }}
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in New Issue