diff --git a/automation/ModesRegistry.php b/automation/ModesRegistry.php index 0f35028..dc908ef 100644 --- a/automation/ModesRegistry.php +++ b/automation/ModesRegistry.php @@ -35,6 +35,10 @@ 'label' => 'Кино', 'description' => 'Приглушённый свет в гостиной, отключены звуковые уведомления.', ], + 'guest' => [ + 'label' => 'Гости', + 'description' => 'В доме гости. Основное освещение и уведомления активны, тихие режимы отключены.', + ], ]; } } diff --git a/automation/Scopes/SleepScope.php b/automation/Scopes/SleepScope.php deleted file mode 100644 index 2801e28..0000000 --- a/automation/Scopes/SleepScope.php +++ /dev/null @@ -1,222 +0,0 @@ - register_global_device_sync_map(); - } - - public function register_events_handlers(): void { - // No per-button event handlers needed; we mute channels in activate_sleep. - } - - public function register_actions_scripts(): void { - $this -> add_action_script([ - "alias" => "activate_sleep", - "name" => "Режим сна", - "description" => "Включить режим сна: выключить всё indoor-освещение и заблокировать кнопки", - "author" => "Eugene Sukhodolskiy", - "icon" => '', - "danger_level" => "cautious", - "state_callback" => function() { - $isSleep = $this -> mode() -> is('sleep'); - return [ - ["label" => $isSleep ? "On" : "Off", "variant" => $isSleep ? "success" : "secondary"] - ]; - }, - ], function($params) { - $this -> mode() -> enable('sleep'); - - // 1. Turn everything off immediately - $results = $this -> helper() -> group_set_state(self::INDOOR_RELAYS, false, $this -> sync_map()); - - // 2. Mute indoor button channels so physical presses are ignored - $this -> set_indoor_buttons_mute(true); - - return [ - "mode_enabled" => true, - "lights_turned_off" => $results, - ]; - }); - - $this -> add_action_script([ - "alias" => "deactivate_sleep", - "name" => "Выход из сна", - "description" => "Отключить режим сна и разблокировать кнопки", - "author" => "Eugene Sukhodolskiy", - "icon" => '', - "danger_level" => "safe", - "state_callback" => function() { - $isSleep = $this -> mode() -> is('sleep'); - return [ - ["label" => $isSleep ? "On" : "Off", "variant" => $isSleep ? "success" : "secondary"] - ]; - }, - ], function($params) { - $this -> mode() -> disable('sleep'); - - // Unmute buttons and sync their indicators back to relay states - $this -> set_indoor_buttons_mute(false); - - return [ - "mode_disabled" => true, - ]; - }); - } - - public function register_regular_scripts(): void { - // Guard script: if sleep mode is active and someone turned a light on via - // web client (or any other way), turn it back off immediately. - $this -> add_regular_script([ - "alias" => "sleep_guard", - "name" => "Sleep guard", - "description" => "Принудительно гасит indoor-свет, пока активен режим сна", - "author" => "Eugene Sukhodolskiy", - ], function() { - if (!$this -> mode() -> is('sleep')) { - return; - } - - foreach (self::INDOOR_RELAYS as $target) { - $parts = explode(":", $target, 2); - $alias = $parts[0]; - $channel = isset($parts[1]) ? intval($parts[1]) : null; - - $relay = $this -> devices() -> by_alias($alias); - if (!$relay) { - continue; - } - - $relay_api = $relay -> device_api(); - if (!($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay)) { - continue; - } - - $status = $relay_api -> get_status(); - $ch = $channel ?? 0; - $state = $status["channels"][$ch]["state"] ?? "off"; - - if ($state === "on") { - if ($channel === null) { - $relay_api -> set_state(false); - } else { - $relay_api -> set_channel_state(false, $channel); - } - $this -> helper() -> sync_relay_to_btns($this -> sync_map(), $alias); - } - } - }); - } - - /** - * Mute or unmute button channels that are wired to INDOOR relays. - * When muted, physical button presses on the device are ignored. - * When unmuted, we restore enabled/disabled state from the linked relay. - */ - protected function set_indoor_buttons_mute(bool $mute): void { - $indoor_map = []; - foreach (self::INDOOR_RELAYS as $target) { - $parts = explode(":", $target, 2); - $indoor_map[$parts[0]] = isset($parts[1]) ? intval($parts[1]) : null; - } - - $sync_map = $this -> sync_map(); - if (!isset($sync_map["connections"])) { - return; - } - - foreach ($sync_map["connections"] as $connection) { - $has_indoor = false; - $btn_entries = []; - - foreach ($connection as $entry) { - $type = $entry["type"] ?? ""; - $alias = $entry["alias"] ?? ""; - $channel = $entry["channel"] ?? 0; - - if ($type === "relay" && isset($indoor_map[$alias])) { - $expected = $indoor_map[$alias]; - if ($expected === null || $expected === $channel) { - $has_indoor = true; - } - } elseif ($type === "button") { - $btn_entries[] = $entry; - } - } - - if (!$has_indoor || empty($btn_entries)) { - continue; - } - - foreach ($btn_entries as $btn) { - $btn_device = $this -> devices() -> by_alias($btn["alias"]); - if (!$btn_device) { - continue; - } - - $btn_api = $btn_device -> device_api(); - if (!($btn_api instanceof \SHServ\Tools\DeviceAPI\Button)) { - continue; - } - - $btn_channel = $btn["channel"] ?? 0; - - if ($mute) { - $btn_api -> set_channel_state("mute", $btn_channel); - } else { - // Unmute: figure out whether the linked relay is on or off - $sync_state = "disabled"; - foreach ($connection as $e) { - if (($e["type"] ?? "") === "relay" && isset($indoor_map[$e["alias"]])) { - $expected = $indoor_map[$e["alias"]]; - $relay_ch = $e["channel"] ?? 0; - if ($expected === null || $expected === $relay_ch) { - $relay = $this -> devices() -> by_alias($e["alias"]); - if ($relay) { - $relay_api = $relay -> device_api(); - if ($relay_api instanceof \SHServ\Tools\DeviceAPI\Relay) { - $status = $relay_api -> get_status(); - $st = $status["channels"][$relay_ch]["state"] ?? "off"; - $sync_state = ($st === "on") ? "enabled" : "disabled"; - } - } - break; - } - } - } - $btn_api -> set_channel_state($sync_state, $btn_channel); - } - } - } - } -}