mirror of
https://github.com/seriousm4x/UpSnap.git
synced 2026-03-31 06:24:11 -04:00
feat: custom timeouts for wake and shutdown
This commit is contained in:
43
backend/migrations/1741216171_updated_devices.go
Normal file
43
backend/migrations/1741216171_updated_devices.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(app core.App) error {
|
||||
collection, err := app.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add field
|
||||
if err := collection.Fields.AddMarshaledJSONAt(11, []byte(`{
|
||||
"hidden": false,
|
||||
"id": "number361076486",
|
||||
"max": null,
|
||||
"min": 1,
|
||||
"name": "wake_timeout",
|
||||
"onlyInt": true,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
}`)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return app.Save(collection)
|
||||
}, func(app core.App) error {
|
||||
collection, err := app.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove field
|
||||
collection.Fields.RemoveById("number361076486")
|
||||
|
||||
return app.Save(collection)
|
||||
})
|
||||
}
|
||||
43
backend/migrations/1741216190_updated_devices.go
Normal file
43
backend/migrations/1741216190_updated_devices.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(app core.App) error {
|
||||
collection, err := app.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// add field
|
||||
if err := collection.Fields.AddMarshaledJSONAt(15, []byte(`{
|
||||
"hidden": false,
|
||||
"id": "number2068100152",
|
||||
"max": null,
|
||||
"min": 1,
|
||||
"name": "shutdown_timeout",
|
||||
"onlyInt": true,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
}`)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return app.Save(collection)
|
||||
}, func(app core.App) error {
|
||||
collection, err := app.FindCollectionByNameOrId("z5lghx2r3tm45n1")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// remove field
|
||||
collection.Fields.RemoveById("number2068100152")
|
||||
|
||||
return app.Save(collection)
|
||||
})
|
||||
}
|
||||
@@ -48,16 +48,21 @@ func ShutdownDevice(device *core.Record) error {
|
||||
done <- cmd.Wait()
|
||||
}()
|
||||
|
||||
// check state every seconds for 2 min
|
||||
shutdownTimeout := device.GetInt("shutdown_timeout")
|
||||
if shutdownTimeout <= 0 {
|
||||
shutdownTimeout = 120
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(1 * time.Second):
|
||||
if time.Since(start) >= 2*time.Minute {
|
||||
if time.Since(start) >= time.Duration(shutdownTimeout)*time.Second {
|
||||
if err := KillProcess(cmd.Process); err != nil {
|
||||
logger.Error.Println(err)
|
||||
}
|
||||
return fmt.Errorf("%s not offline after 2 minutes", device.GetString("name"))
|
||||
return fmt.Errorf("%s not offline after %d seconds", device.GetString("name"), shutdownTimeout)
|
||||
}
|
||||
isOnline, err := PingDevice(device)
|
||||
if err != nil {
|
||||
|
||||
@@ -18,7 +18,7 @@ func SetProcessAttributes(cmd *exec.Cmd) {
|
||||
|
||||
// Kills child processes on Linux. Windows doesn't provide a direct way to kill child processes, so we kill just the main process.
|
||||
func KillProcess(process *os.Process) error {
|
||||
logger.Warning.Println("Your shutdown cmd didn't finish in 2 minutes. It will be killed.")
|
||||
logger.Warning.Println("Your shutdown cmd didn't finish in time. It will be killed.")
|
||||
pgid, err := unix.Getpgid(process.Pid)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -15,6 +15,11 @@ import (
|
||||
func WakeDevice(device *core.Record) error {
|
||||
logger.Info.Println("Wake triggered for", device.GetString("name"))
|
||||
|
||||
wakeTimeout := device.GetInt("wake_timeout")
|
||||
if wakeTimeout <= 0 {
|
||||
wakeTimeout = 120
|
||||
}
|
||||
|
||||
wake_cmd := device.GetString("wake_cmd")
|
||||
if wake_cmd != "" {
|
||||
var shell string
|
||||
@@ -46,16 +51,16 @@ func WakeDevice(device *core.Record) error {
|
||||
done <- cmd.Wait()
|
||||
}()
|
||||
|
||||
// check state every seconds for 2 min
|
||||
start := time.Now()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(1 * time.Second):
|
||||
if time.Since(start) >= 2*time.Minute {
|
||||
if time.Since(start) >= time.Duration(wakeTimeout)*time.Second {
|
||||
if err := KillProcess(cmd.Process); err != nil {
|
||||
logger.Error.Println(err)
|
||||
}
|
||||
return fmt.Errorf("%s not online after 2 minutes", device.GetString("name"))
|
||||
return fmt.Errorf("%s not online after %d seconds", device.GetString("name"), wakeTimeout)
|
||||
}
|
||||
isOnline, err := PingDevice(device)
|
||||
if err != nil {
|
||||
@@ -83,10 +88,10 @@ func WakeDevice(device *core.Record) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// check state every seconds for 2 min
|
||||
start := time.Now()
|
||||
for {
|
||||
time.Sleep(1 * time.Second)
|
||||
fmt.Println("here")
|
||||
isOnline, err := PingDevice(device)
|
||||
if err != nil {
|
||||
logger.Error.Println(err)
|
||||
@@ -95,10 +100,11 @@ func WakeDevice(device *core.Record) error {
|
||||
if isOnline {
|
||||
return nil
|
||||
}
|
||||
if time.Since(start) >= 2*time.Minute {
|
||||
if time.Since(start) >= time.Duration(wakeTimeout)*time.Second {
|
||||
fmt.Println("over")
|
||||
break
|
||||
}
|
||||
}
|
||||
return fmt.Errorf(device.GetString("name"), "not online after 2 min")
|
||||
return fmt.Errorf(device.GetString("name"), "not online after %d seconds", wakeTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Entfernten Linux PC ausschalten:",
|
||||
"device_shutdown_examples_windows": "Entfernten Windows PC ausschalten:",
|
||||
"device_shutdown_examples": "Beispiele:",
|
||||
"device_shutdown_timeout": "Ausschalt-Timeout (Sekunden)",
|
||||
"device_shutdown": "Ausschalten",
|
||||
"device_sol_authorization": "Authorisierung",
|
||||
"device_sol_desc1": "Du kannst Computer mithilfe des Tools <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> in den Ruhezustand versetzen. Sleep-On-LAN (SOL) ist ein externes Tool/Daemon, das auf den PCs arbeitet, die du in den Ruhezustand versetzen möchtest, und stellt einen REST-Endpunkt bereit. Für Anweisungen zur Einrichtung von Sleep-On-LAN verweise bitte auf den Abschnitt <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a>.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Aktivieren",
|
||||
"device_wake_cron": "Cron",
|
||||
"device_wake_desc": "Du kannst das Gerät mit einem Cron-Job einschalten.",
|
||||
"device_wake_timeout": "Einschalt-Timeout (Sekunden)",
|
||||
"device_wake": "Einschalten",
|
||||
"home_add_first_device": "Füge dein erstes Gerät hinzu",
|
||||
"home_grant_permissions": "Bitte frag den Administrator, dir Berechtigungen für bestehende Geräte zu erteilen oder neue Geräte zu erstellen.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Shutdown remote linux machine:",
|
||||
"device_shutdown_examples_windows": "Shutdown remote windows machine:",
|
||||
"device_shutdown_examples": "Examples:",
|
||||
"device_shutdown_timeout": "Shutdown Timeout (seconds)",
|
||||
"device_shutdown": "Shutdown",
|
||||
"device_sol_authorization": "Authorization",
|
||||
"device_sol_desc1": "You can put computers to sleep using the <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> tool. Sleep-On-LAN (SOL) is an external tool/daemon that operates on the PCs you want to put to sleep, providing a REST endpoint. For instructions on setting up Sleep-On-LAN, please refer to the <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a> section.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Enable wake cron",
|
||||
"device_wake_cron": "Wake cron",
|
||||
"device_wake_desc": "You can power this device using a scheduled cron job.",
|
||||
"device_wake_timeout": "Wake Timeout (seconds)",
|
||||
"device_wake": "Wake",
|
||||
"home_add_first_device": "Add your first device",
|
||||
"home_grant_permissions": "Please ask the admin to grant you permissions to existing devices or to create new ones.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Apagar el dispositivo Linux remoto:",
|
||||
"device_shutdown_examples_windows": "Apagar el dispositivo Windows remoto:",
|
||||
"device_shutdown_examples": "Ejemplos:",
|
||||
"device_shutdown_timeout": "Tiempo de espera de apagado (segundos)",
|
||||
"device_shutdown": "Apagar",
|
||||
"device_sol_authorization": "Autorización",
|
||||
"device_sol_desc1": "Puedes poner las computadoras en modo de suspensión usando <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> herramienta. Sleep-On-LAN (SOL) es una herramienta/daemon externo que opera en las PC que desea poner en suspensión y proporciona un punto final REST. Para obtener instrucciones sobre cómo configurar Sleep-On-LAN, consulte <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Uso</a> sección.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Activar wake cron",
|
||||
"device_wake_cron": "Encender cron",
|
||||
"device_wake_desc": "Podrá encender este dispositivo utilizando un scheduled cron job.",
|
||||
"device_wake_timeout": "Tiempo de espera de encendido (segundos)",
|
||||
"device_wake": "Encender",
|
||||
"home_add_first_device": "Añade tu primer dispositivo",
|
||||
"home_grant_permissions": "Pídale al administrador que le otorgue permisos para los dispositivos existentes o que cree otros nuevos.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Arrêter une machine Linux distante :",
|
||||
"device_shutdown_examples_windows": "Arrêter une machine Windows distante :",
|
||||
"device_shutdown_examples": "Exemples :",
|
||||
"device_shutdown_timeout": "Délai d'arrêt (secondes)",
|
||||
"device_shutdown": "Arrêt",
|
||||
"device_sol_authorization": "Autorisation",
|
||||
"device_sol_desc1": "Vous pouvez mettre les ordinateurs en veille à l'aide de l'outil <a class='link' href='https://github.com/SR-G/sleep-on-lan' target='_blank'>Sleep-On-LAN</a>. Sleep-On-LAN (SOL) est un outil/daemon externe qui fonctionne sur les PC que vous souhaitez mettre en veille, fournissant un point de terminaison REST. Pour obtenir des instructions sur la configuration de Sleep-On-LAN, veuillez vous référer à la section <a href='https://github.com/SR-G/sleep-on-lan#usage' class='link' target='_blank'>Usage</a>.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Activer le réveil avec cron",
|
||||
"device_wake_cron": "Réveil avec cron",
|
||||
"device_wake_desc": "Vous pouvez allumer cet appareil en utilisant un job cron planifié.",
|
||||
"device_wake_timeout": "Délai de réveil (secondes)",
|
||||
"device_wake": "Réveil",
|
||||
"home_add_first_device": "Ajoutez votre premier appareil",
|
||||
"home_grant_permissions": "Veuillez demander à votre administrateur les permissions aux appareils existants ou créez-en de nouveaux.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Mematikan Linux jarak jauh:",
|
||||
"device_shutdown_examples_windows": "Mematikan Windows jarak jauh:",
|
||||
"device_shutdown_examples": "Contoh:",
|
||||
"device_shutdown_timeout": "Waktu tunggu mati (detik)",
|
||||
"device_shutdown": "Matikan",
|
||||
"device_sol_authorization": "Otorisasi",
|
||||
"device_sol_desc1": "Anda dapat membuat tidur komputer menggunakan alat <a class='link' href='https://github.com/SR-G/sleep-on-lan' target='_blank'>Sleep-On-LAN</a>. Sleep-On-LAN (SOL) merupakan alat/daemon eksternal yang berjalan di PC yang ingin Anda tidurkan, dengan menyediakan REST endpoint. Untuk instruksi pemasangan Sleep-On-LAN, silakan merujuk ke bagian <a href='https://github.com/SR-G/sleep-on-lan#usage' class='link' target='_blank'>Penggunaan</a>.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Aktifkan jadwal bangun",
|
||||
"device_wake_cron": "Jadwal Bangun",
|
||||
"device_wake_desc": "Anda dapat menyalakan perangkat ini menggunakan tugas penjadwalan.",
|
||||
"device_wake_timeout": "Waktu tunggu nyala (detik)",
|
||||
"device_wake": "Bangunkan",
|
||||
"home_add_first_device": "Tambahkan perangkat pertama Anda",
|
||||
"home_grant_permissions": "Mohon minta admin untuk memberikan izin ke perangkat yang sudah ada atau membuat perangkat baru.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Spegni macchina linux remota:",
|
||||
"device_shutdown_examples_windows": "Spegni macchina windows remota:",
|
||||
"device_shutdown_examples": "Esempi:",
|
||||
"device_shutdown_timeout": "Timeout di spegnimento (secondi)",
|
||||
"device_shutdown": "Spegni",
|
||||
"device_sol_authorization": "Autorizzazione",
|
||||
"device_sol_desc1": "Puoi spegnere il tuo dispositivo usando lo strumento <a class='link' href='https://github.com/SR-G/sleep-on-lan' target='_blank'>Sleep-On-LAN</a>. Sleep-On-LAN (SOL) è uno strumento esterno che opera sul dispositivo che vuoi spegnere, il quale rende disponibile un endpoint REST. Puoi riferirti al link <a href='https://github.com/SR-G/sleep-on-lan#usage' class='link' target='_blank'>Uso</a> (in inglese) per le istruzioni.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Abilita sveglia programmata",
|
||||
"device_wake_cron": "Sveglia programmata",
|
||||
"device_wake_desc": "Puoi accendere questo dispositivo con una sveglia programmata.",
|
||||
"device_wake_timeout": "Timeout di accensione (secondi)",
|
||||
"device_wake": "Accendi",
|
||||
"home_add_first_device": "Aggiungi il tuo primo dispositivo",
|
||||
"home_grant_permissions": "Per favore chiedi all'amministratore di darti i permessi necessari per aggiungere un nuovo dispositivo.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "リモート Linux マシンのシャットダウン:",
|
||||
"device_shutdown_examples_windows": "リモート Windows マシンのシャットダウン:",
|
||||
"device_shutdown_examples": "例:",
|
||||
"device_shutdown_timeout": "シャットダウンタイムアウト (秒)",
|
||||
"device_shutdown": "シャットダウン",
|
||||
"device_sol_authorization": "認証",
|
||||
"device_sol_desc1": "<a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> ツールを使用してコンピュータをスリープ状態にすることができます。Sleep-On-LAN(SOL)は、スリープ状態にしたい PC で動作する外部ツール/デーモンで、REST エンドポイントを提供します。Sleep-On-LAN のセットアップ方法については、<a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a> セクションを参照してください。",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "起動スケジュールを有効化",
|
||||
"device_wake_cron": "起動スケジュール",
|
||||
"device_wake_desc": "スケジュールされた cron ジョブを使用してこのデバイスを起動できます。",
|
||||
"device_wake_timeout": "ウェイクタイムアウト (秒)",
|
||||
"device_wake": "起動",
|
||||
"home_add_first_device": "最初のデバイスを追加してください",
|
||||
"home_grant_permissions": "既存のデバイスへの権限を付与するか、新しいデバイスを作成するために管理者に依頼してください。",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Afsluiten van een externe Linux-machine:",
|
||||
"device_shutdown_examples_windows": "Afsluiten van een externe Windows-machine:",
|
||||
"device_shutdown_examples": "Voorbeelden:",
|
||||
"device_shutdown_timeout": "Uitschakel-time-out (seconden)",
|
||||
"device_shutdown": "Afsluiten",
|
||||
"device_sol_authorization": "Autorisatie",
|
||||
"device_sol_desc1": "Je kunt computers in de slaapstand zetten met de <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> tool. Sleep-On-LAN (SOL) is een externe tool/daemon die op de PC's werkt die je in de slaapstand wilt zetten en biedt een REST-endpoint. Voor instructies over het instellen van Sleep-On-LAN, zie de <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Gebruik</a> sectie.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Wek cron inschakelen",
|
||||
"device_wake_cron": "Wek cron",
|
||||
"device_wake_desc": "Je kunt dit apparaat inschakelen met een geplande cron-taak.",
|
||||
"device_wake_timeout": "Inschakel-time-out (seconden)",
|
||||
"device_wake": "Wek",
|
||||
"home_add_first_device": "Voeg je eerste apparaat toe",
|
||||
"home_grant_permissions": "Vraag de admin om je toestemming te geven voor bestaande apparaten of om nieuwe te creëren.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Wyłącz zdalną maszynę Linux:",
|
||||
"device_shutdown_examples_windows": "Wyłącz zdalną maszynę Windows:",
|
||||
"device_shutdown_examples": "Przykłady:",
|
||||
"device_shutdown_timeout": "Limit czasu wyłączenia (sekundy)",
|
||||
"device_shutdown": "Wyłącz",
|
||||
"device_sol_authorization": "Autoryzacja",
|
||||
"device_sol_desc1": "Możesz wyłączać urządzenia za pomocą narzędzia <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a>. Sleep-On-LAN (SOL) jest zewnętrznym narzędziem/demonem, działającym na urządzeniach które chcesz wyłączać. Tworzy on endpoint REST. Aby dowiedzieć się jak skonfigurować SOL, zapoznaj się z <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">instrukcją użytkownika</a>.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Włącz cron do włączania",
|
||||
"device_wake_cron": "Cron do włączania",
|
||||
"device_wake_desc": "Możesz włączyć to urządzenie za pomocą zaplanowanego zadania cron.",
|
||||
"device_wake_timeout": "Limit czasu wybudzania (sekundy)",
|
||||
"device_wake": "Włączanie",
|
||||
"home_add_first_device": "Utwórz pierwsze urządzenie",
|
||||
"home_grant_permissions": "Poproś administratora o przyznanie uprawnień do istniejących urządzeń lub do tworzenia nowych.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "Desligar dispositivo linux remoto:",
|
||||
"device_shutdown_examples_windows": "Desligar dispositivo windows remoto:",
|
||||
"device_shutdown_examples": "Exemplos:",
|
||||
"device_shutdown_timeout": "Tempo limite de desligamento (segundos)",
|
||||
"device_shutdown": "Desligar",
|
||||
"device_sol_authorization": "Autenticação",
|
||||
"device_sol_desc1": "Poderá suspender o seu dispositivo usando a ferramenta <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a>. Sleep-On-LAN (SOL) é uma ferramenta externa que terá de ser executada no dispositivo que quer suspender, facilitando um REST endpoint. Para instruções em como configurar Sleep-On-LAN, veja a secção <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a>.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "Ativar wake cron",
|
||||
"device_wake_cron": "Wake cron",
|
||||
"device_wake_desc": "Poderá ligar este dispositivo através dum cron job agendado.",
|
||||
"device_wake_timeout": "Tempo limite de ativação (segundos)",
|
||||
"device_wake": "Ligar",
|
||||
"home_add_first_device": "Adicione o seu primeiro dispositivo",
|
||||
"home_grant_permissions": "Peça ao administrador para alterar as suas permissões para dispositivos existentes ou para criar novos.",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "關閉遠端 Linux 主機:",
|
||||
"device_shutdown_examples_windows": "關閉遠端 Windows 主機:",
|
||||
"device_shutdown_examples": "範例:",
|
||||
"device_shutdown_timeout": "關機超時(秒)",
|
||||
"device_shutdown": "關機",
|
||||
"device_sol_authorization": "認證",
|
||||
"device_sol_desc1": "你可以使用 <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> 工具讓電腦睡眠。 Sleep-On-LAN (SOL) 是一个外部的工具,它在你想要進入睡眠的PC上執行並有RestAPI端口. 有關 Sleep-On-LAN 設定的說明, 請見文檔 <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a>",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "啟用定時喚醒",
|
||||
"device_wake_cron": "唤醒排程",
|
||||
"device_wake_desc": "你可以透過排程来唤醒裝置。",
|
||||
"device_wake_timeout": "喚醒超時(秒)",
|
||||
"device_wake": "喚醒",
|
||||
"home_add_first_device": "添加你的第一台設備",
|
||||
"home_grant_permissions": "請聯絡系統管理員授權現有設備或創建新設備的權限",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"device_shutdown_examples_linux": "关闭远程 Linux 主机:",
|
||||
"device_shutdown_examples_windows": "关闭远程 Windows 主机:",
|
||||
"device_shutdown_examples": "示例:",
|
||||
"device_shutdown_timeout": "关机超时(秒)",
|
||||
"device_shutdown": "关机",
|
||||
"device_sol_authorization": "认证",
|
||||
"device_sol_desc1": "您可以使用 <a class=\"link\" href=\"https://github.com/SR-G/sleep-on-lan\" target=\"_blank\">Sleep-On-LAN</a> 工具让计算机进入睡眠状态. Sleep-On-LAN (SOL) 是一个外部的工具/守护程序, 它在您想要进入休眠状态的PC上运行并提供RestApi接口. 有关 Sleep-On-LAN 设置的说明, 请参阅文档 <a href=\"https://github.com/SR-G/sleep-on-lan#usage\" class=\"link\" target=\"_blank\">Usage</a> 部分.",
|
||||
@@ -104,6 +105,7 @@
|
||||
"device_wake_cron_enable": "启用定时唤醒",
|
||||
"device_wake_cron": "唤醒计划任务",
|
||||
"device_wake_desc": "您可以通过计划任务来唤醒设备.",
|
||||
"device_wake_timeout": "唤醒超时(秒)",
|
||||
"device_wake": "唤醒",
|
||||
"home_add_first_device": "添加您的第一台设备",
|
||||
"home_grant_permissions": "请联系管理员授予您相应权限.",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
let modalShutdown: HTMLDialogElement;
|
||||
|
||||
$: if (device.status === 'pending' && !interval) {
|
||||
countdown(Date.parse(device.updated));
|
||||
countdown(Date.parse(device.updated), 'wake');
|
||||
}
|
||||
$: minutes = Math.floor(timeout / 60);
|
||||
$: seconds = timeout % 60;
|
||||
@@ -53,7 +53,7 @@
|
||||
.then((resp) => resp.json())
|
||||
.then(async (data) => {
|
||||
device = data as Device;
|
||||
await countdown(Date.parse(device.updated));
|
||||
await countdown(Date.parse(device.updated), 'wake');
|
||||
if (device.status === 'online' && device.link && device.link_open !== '') {
|
||||
if (device.link_open === 'new_tab') {
|
||||
window.open(device.link, '_blank');
|
||||
@@ -76,18 +76,22 @@
|
||||
.then((resp) => resp.json())
|
||||
.then((data) => {
|
||||
device = data as Device;
|
||||
countdown(Date.parse(device.updated));
|
||||
countdown(Date.parse(device.updated), 'shutdown');
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.error(err.message);
|
||||
});
|
||||
}
|
||||
|
||||
function countdown(updated: number) {
|
||||
function countdown(updated: number, action: 'wake' | 'shutdown') {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
timeout = 120;
|
||||
const end = updated + 2 * 60 * 1000;
|
||||
timeout = action === 'wake' ? device.wake_timeout : device.shutdown_timeout;
|
||||
if (timeout <= 0) {
|
||||
timeout = 120;
|
||||
}
|
||||
|
||||
const end = updated + timeout * 1000;
|
||||
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
|
||||
@@ -323,12 +323,12 @@
|
||||
{@html m.device_ping_desc()}
|
||||
</p>
|
||||
<fieldset class="fieldset">
|
||||
<label class="floating-label mt-2">
|
||||
<span>{m.device_ping_cmd()}</span>
|
||||
<label class="input mt-2">
|
||||
<span>$:</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_ping_cmd()}
|
||||
class="input"
|
||||
class="grow"
|
||||
bind:value={device.ping_cmd}
|
||||
/>
|
||||
</label>
|
||||
@@ -343,17 +343,31 @@
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html m.settings_ping_interval_desc2()}
|
||||
</p>
|
||||
<fieldset class="fieldset">
|
||||
<label class="floating-label mt-2">
|
||||
<span>{m.device_wake_cmd()}</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_wake_cmd()}
|
||||
class="input"
|
||||
bind:value={device.wake_cmd}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<fieldset class="fieldset">
|
||||
<label class="floating-label mt-2">
|
||||
<span>{m.device_wake_timeout()}</span>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
placeholder={m.device_wake_timeout()}
|
||||
class="input"
|
||||
bind:value={device.wake_timeout}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
<fieldset class="fieldset">
|
||||
<label class="input mt-2">
|
||||
<span>$:</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_wake_cmd()}
|
||||
class="grow"
|
||||
bind:value={device.wake_cmd}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
||||
<legend class="fieldset-legend">{m.device_wake_cron_enable()}</legend>
|
||||
@@ -399,7 +413,100 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{m.device_shutdown()}</h2>
|
||||
<p>
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html m.device_shutdown_desc()}
|
||||
</p>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<fieldset class="fieldset">
|
||||
<label class="floating-label mt-2">
|
||||
<span>{m.device_shutdown_timeout()}</span>
|
||||
<input
|
||||
type="number"
|
||||
min="0"
|
||||
placeholder={m.device_shutdown_timeout()}
|
||||
class="input"
|
||||
bind:value={device.shutdown_timeout}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
<fieldset class="fieldset">
|
||||
<label class="input mt-2">
|
||||
<span>$:</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_shutdown_cmd()}
|
||||
class="grow"
|
||||
bind:value={device.shutdown_cmd}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
<p class="font-bold">{m.device_shutdown_examples()}</p>
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#" class="italic"><code>{m.device_shutdown_examples_windows()}</code
|
||||
></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>net rpc shutdown -I 192.168.1.13 -U "user%password"</code
|
||||
></pre>
|
||||
</div>
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#" class="italic"><code>{m.device_shutdown_examples_linux()}</code></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>sshpass -p password ssh -o "StrictHostKeyChecking=no" user@192.168.1.13 "sudo poweroff"</code
|
||||
></pre>
|
||||
</div>
|
||||
<p>
|
||||
{m.device_shutdown_cron_desc()}
|
||||
</p>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
||||
<legend class="fieldset-legend">{m.device_shutdown_cron_enable()}</legend>
|
||||
<label class="fieldset-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={device.shutdown_cron_enabled}
|
||||
class="toggle toggle-success"
|
||||
/>
|
||||
{m.device_shutdown_cron_enable()}
|
||||
</label>
|
||||
<label class="floating-label mt-2">
|
||||
<span
|
||||
>{m.device_shutdown_cron()}
|
||||
{#if device.shutdown_cron_enabled}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_shutdown_cron()}
|
||||
class="input validator"
|
||||
bind:value={device.shutdown_cron}
|
||||
disabled={!device.shutdown_cron_enabled}
|
||||
required={device.shutdown_cron_enabled}
|
||||
/>
|
||||
{#if device.shutdown_cron_enabled}
|
||||
<p class="fieldset-label">{parseCron(device.shutdown_cron, Date.now())}</p>
|
||||
{/if}
|
||||
</label>
|
||||
</fieldset>
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
||||
<legend class="fieldset-legend">{m.device_require_confirmation()}</legend>
|
||||
<label class="fieldset-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={device.shutdown_confirm}
|
||||
class="toggle toggle-success"
|
||||
/>
|
||||
{m.device_require_confirmation()}
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">Sleep-On-LAN</h2>
|
||||
@@ -488,88 +595,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{m.device_shutdown()}</h2>
|
||||
<p>
|
||||
<!-- eslint-disable svelte/no-at-html-tags -->
|
||||
{@html m.device_shutdown_desc()}
|
||||
</p>
|
||||
<fieldset class="fieldset">
|
||||
<label class="floating-label mt-2">
|
||||
<span>{m.device_shutdown_cmd()}</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_shutdown_cmd()}
|
||||
class="input"
|
||||
bind:value={device.shutdown_cmd}
|
||||
/>
|
||||
</label>
|
||||
</fieldset>
|
||||
<p class="font-bold">{m.device_shutdown_examples()}</p>
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#" class="italic"><code>{m.device_shutdown_examples_windows()}</code
|
||||
></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>net rpc shutdown -I 192.168.1.13 -U "user%password"</code
|
||||
></pre>
|
||||
</div>
|
||||
<div class="mockup-code max-w-fit min-w-0 text-sm">
|
||||
<pre data-prefix="#" class="italic"><code>{m.device_shutdown_examples_linux()}</code></pre>
|
||||
<pre data-prefix="$" class="text-warning"><code
|
||||
>sshpass -p password ssh -o "StrictHostKeyChecking=no" user@192.168.1.13 "sudo poweroff"</code
|
||||
></pre>
|
||||
</div>
|
||||
<p>
|
||||
{m.device_shutdown_cron_desc()}
|
||||
</p>
|
||||
<div class="flex flex-row flex-wrap gap-4">
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
||||
<legend class="fieldset-legend">{m.device_shutdown_cron_enable()}</legend>
|
||||
<label class="fieldset-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={device.shutdown_cron_enabled}
|
||||
class="toggle toggle-success"
|
||||
/>
|
||||
{m.device_shutdown_cron_enable()}
|
||||
</label>
|
||||
<label class="floating-label mt-2">
|
||||
<span
|
||||
>{m.device_shutdown_cron()}
|
||||
{#if device.shutdown_cron_enabled}
|
||||
<span class="text-error">*</span>
|
||||
{/if}
|
||||
</span>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={m.device_shutdown_cron()}
|
||||
class="input validator"
|
||||
bind:value={device.shutdown_cron}
|
||||
disabled={!device.shutdown_cron_enabled}
|
||||
required={device.shutdown_cron_enabled}
|
||||
/>
|
||||
{#if device.shutdown_cron_enabled}
|
||||
<p class="fieldset-label">{parseCron(device.shutdown_cron, Date.now())}</p>
|
||||
{/if}
|
||||
</label>
|
||||
</fieldset>
|
||||
<fieldset class="fieldset bg-base-100 border-base-300 rounded-box w-64 border p-4">
|
||||
<legend class="fieldset-legend">{m.device_require_confirmation()}</legend>
|
||||
<label class="fieldset-label">
|
||||
<input
|
||||
type="checkbox"
|
||||
bind:checked={device.shutdown_confirm}
|
||||
class="toggle toggle-success"
|
||||
/>
|
||||
{m.device_require_confirmation()}
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card bg-base-200 mt-6 w-full shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title">{m.device_password()}</h2>
|
||||
|
||||
@@ -15,10 +15,12 @@ export type Device = RecordModel & {
|
||||
wake_cron_enabled: boolean;
|
||||
wake_cmd: string;
|
||||
wake_confirm: boolean;
|
||||
wake_timeout: number;
|
||||
shutdown_cron: string;
|
||||
shutdown_cron_enabled: boolean;
|
||||
shutdown_cmd: string;
|
||||
shutdown_confirm: boolean;
|
||||
shutdown_timeout: number;
|
||||
password: string;
|
||||
groups: string[];
|
||||
expand: {
|
||||
|
||||
Reference in New Issue
Block a user