where('trigger_type', 'state_change')->get() ->each(function (Automation $automation) use ($deviceUuid, $entityKey, $state) { if ($this->matchesStateTrigger($automation, $deviceUuid, $entityKey, $state)) { $this->maybeRun($automation); } }); } /** Evaluate time-based automations (called every minute by the scheduler). */ public function tick(): void { $hhmm = now()->format('H:i'); Automation::where('enabled', true)->where('trigger_type', 'time')->get() ->each(function (Automation $automation) use ($hhmm) { if (data_get($automation->trigger_config, 'at') === $hhmm) { $this->maybeRun($automation); } }); } private function matchesStateTrigger(Automation $automation, string $deviceUuid, string $entityKey, array $state): bool { $cfg = $automation->trigger_config ?? []; if (($cfg['device'] ?? null) !== $deviceUuid || ($cfg['entity_key'] ?? null) !== $entityKey) { return false; } $field = $cfg['field'] ?? 'on'; return array_key_exists($field, $state) && $state[$field] == ($cfg['equals'] ?? true); } private function maybeRun(Automation $automation): void { if ($automation->cooldown_seconds > 0 && $automation->last_triggered_at !== null && $automation->last_triggered_at->gt(now()->subSeconds($automation->cooldown_seconds))) { return; } foreach ($automation->actions ?? [] as $action) { $this->runAction($automation, $action); } $automation->forceFill(['last_triggered_at' => now()])->save(); } private function runAction(Automation $automation, array $action): void { $type = $action['type'] ?? null; if ($type === 'switch') { $entity = Entity::query() ->whereHas('device', fn ($q) => $q->where('uuid', $action['device'] ?? null)) ->where('key', $action['entity_key'] ?? null) ->with('device', 'state')->first(); if ($entity === null) { return; } if ($automation->dry_run) { Log::info("[automation dry-run] {$automation->name}: switch {$entity->key}", $action); return; } $this->commands->setOn($entity, (bool) ($action['on'] ?? true), 'automation'); } elseif ($type === 'notify') { Log::info("[automation".($automation->dry_run ? ' dry-run' : '')."] {$automation->name}: ".($action['message'] ?? '')); } } }