From c338533029d5caa8e2e4e5c619a0018aaf20f260 Mon Sep 17 00:00:00 2001 From: JackTheRooster Date: Wed, 26 Mar 2025 23:51:45 -0500 Subject: [PATCH] now using gadget last input time to determine if jiggler can be activated added UI elements to set jiggler config --- config.go | 4 +- jiggler.go | 26 ++++---- ui/src/components/JigglerSetting.tsx | 65 +++++++++++--------- ui/src/routes/devices.$id.settings.mouse.tsx | 5 +- 4 files changed, 56 insertions(+), 44 deletions(-) diff --git a/config.go b/config.go index cb1d35e..a88c492 100644 --- a/config.go +++ b/config.go @@ -49,8 +49,8 @@ var defaultConfig = &Config{ DisplayOffAfterSec: 1800, // 30 minutes JigglerConfig: &JigglerConfig{ InactivityLimitSeconds: 20, - JitterPercentage: 0.0, - ScheduleCronTab: "*/5 * * * * *", + JitterPercentage: 0, + ScheduleCronTab: "*/20 * * * * *", }, TLSMode: "", UsbConfig: &usbgadget.Config{ diff --git a/jiggler.go b/jiggler.go index 39b6e93..ceff0dd 100644 --- a/jiggler.go +++ b/jiggler.go @@ -1,18 +1,18 @@ package kvm import ( + "fmt" "github.com/go-co-op/gocron/v2" "math/rand" "time" ) type JigglerConfig struct { - InactivityLimitSeconds float64 `json:"inactivity_limit_seconds"` - JitterPercentage float64 `json:"jitter_percentage"` - ScheduleCronTab string `json:"schedule_cron_tab"` + InactivityLimitSeconds int `json:"inactivity_limit_seconds"` + JitterPercentage int `json:"jitter_percentage"` + ScheduleCronTab string `json:"schedule_cron_tab"` } -var lastUserInput = time.Now() var jigglerEnabled = false var jobDelta time.Duration = 0 var scheduler gocron.Scheduler = nil @@ -28,18 +28,22 @@ func rpcGetJigglerConfig() (JigglerConfig, error) { return *config.JigglerConfig, nil } -func rpcSetJigglerConfig(jigglerConfig JigglerConfig) { +func rpcSetJigglerConfig(jigglerConfig JigglerConfig) error { + logger.Infof("[jsonrpc.go:rpcSetJigglerConfig] jigglerConfig: %v, %v, %v", jigglerConfig.InactivityLimitSeconds, jigglerConfig.JitterPercentage, jigglerConfig.ScheduleCronTab) config.JigglerConfig = &jigglerConfig err := removeExistingCrobJobs(scheduler) if err != nil { - logger.Errorf("Error removing cron jobs from scheduler %v", err) - return + return fmt.Errorf("error removing cron jobs from scheduler %v", err) } err = runJigglerCronTab() if err != nil { - logger.Errorf("Error scheduling jiggler crontab: %v", err) - return + return fmt.Errorf("error scheduling jiggler crontab: %v", err) } + err = SaveConfig() + if err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + return nil } func removeExistingCrobJobs(s gocron.Scheduler) error { @@ -100,7 +104,7 @@ func runJiggler() { time.Sleep(jitter) } inactivitySeconds := config.JigglerConfig.InactivityLimitSeconds - if time.Since(lastUserInput) > time.Duration(inactivitySeconds)*time.Second { + if time.Since(gadget.GetLastUserInputTime()) > time.Duration(inactivitySeconds)*time.Second { //TODO: change to rel mouse err := rpcAbsMouseReport(1, 1, 0) if err != nil { @@ -124,6 +128,6 @@ func calculateJobDelta(s gocron.Scheduler) (time.Duration, error) { } func calculateJitterDuration(delta time.Duration) time.Duration { - jitter := rand.Float64() * config.JigglerConfig.JitterPercentage * delta.Seconds() + jitter := rand.Float64() * float64(config.JigglerConfig.JitterPercentage) / 100 * delta.Seconds() return time.Duration(jitter * float64(time.Second)) } diff --git a/ui/src/components/JigglerSetting.tsx b/ui/src/components/JigglerSetting.tsx index 97104a8..dbb0293 100644 --- a/ui/src/components/JigglerSetting.tsx +++ b/ui/src/components/JigglerSetting.tsx @@ -37,19 +37,19 @@ const jigglerCrontabConfigs = [ const jigglerJitterConfigs = [ { label: "No Jitter", - value: "0.0", + value: "0", }, { label: "10%", - value: ".1", + value: "20", }, { label: "25%", - value: ".25", + value: "25", }, { label: "50%", - value: ".5", + value: "50", }, ]; @@ -75,13 +75,12 @@ const jigglerInactivityConfigs = [ export function JigglerSetting() { const [send] = useJsonRpc(); const [loading, setLoading] = useState(false); - const [inactivityLimitSeconds, setInactivityLimitSeconds] = useState(""); const [jitterPercentage, setJitterPercentage] = useState(""); const [scheduleCronTab, setScheduleCronTab] = useState(""); const [jigglerConfigState, setJigglerConfigState] = useState({ - inactivity_limit_seconds: 20.0, - jitter_percentage: 0.0, + inactivity_limit_seconds: 20, + jitter_percentage: 0, schedule_cron_tab: "*/20 * * * * *" }); @@ -90,28 +89,32 @@ export function JigglerSetting() { if ("error" in resp) return; const result = resp.result as JigglerConfig; setJigglerConfigState(result); - setInactivityLimitSeconds(String(result.inactivity_limit_seconds)) - setJitterPercentage(String(result.jitter_percentage)) - setScheduleCronTab(result.schedule_cron_tab) + + const jitterPercentage = jigglerJitterConfigs.map(u => u.value).includes(result.jitter_percentage.toString()) + ? result.jitter_percentage.toString() + : "custom"; + setJitterPercentage(jitterPercentage) + + const scheduleCronTab = jigglerCrontabConfigs.map(u => u.value).includes(result.schedule_cron_tab) + ? result.schedule_cron_tab + : "custom"; + setScheduleCronTab(scheduleCronTab) }); - }, [send, setInactivityLimitSeconds]); + }, [send]); useEffect(() => { syncJigglerConfig() }, [send, syncJigglerConfig]); const handleJigglerInactivityLimitSecondsChange = (value: string) => { - setInactivityLimitSeconds(value) setJigglerConfigState({ ...jigglerConfigState, inactivity_limit_seconds: Number(value) }); }; const handleJigglerJitterPercentageChange = (value: string) => { - setJitterPercentage(value) setJigglerConfigState({ ...jigglerConfigState, jitter_percentage: Number(value) }); }; const handleJigglerScheduleCronTabChange = (value: string) => { - setScheduleCronTab(value) setJigglerConfigState({ ...jigglerConfigState, schedule_cron_tab: value }); }; @@ -121,7 +124,7 @@ export function JigglerSetting() { send("setJigglerConfig", { jigglerConfig }, async resp => { if ("error" in resp) { notifications.error( - `Failed to set jiggler config: ${resp.error.data || "Unknown error"}`, + `Failed to set jiggler config: ${resp.error.data || "Unknown error"}`, ); setLoading(false); return; @@ -146,23 +149,23 @@ export function JigglerSetting() { value={scheduleCronTab} fullWidth onChange={e => { - if (e.target.value === "custom") { - setScheduleCronTab(e.target.value); - } else { - handleJigglerScheduleCronTabChange(e.target.value) + setScheduleCronTab(e.target.value); + if (e.target.value != "custom") { + handleJigglerScheduleCronTabChange(e.target.value); } }} - options={[...jigglerCrontabConfigs, { value: "custom", label: "Custom" }]} + options={[...jigglerCrontabConfigs, {value: "custom", label: "Custom"}]} /> - {jitterPercentage === "custom" && ( + {scheduleCronTab === "custom" && ( handleJigglerScheduleCronTabChange(e.target.value)} /> )} + +
{ - if (e.target.value === "custom") { - setJitterPercentage(e.target.value); - } else { + setJitterPercentage(e.target.value); + if (e.target.value != "custom") { handleJigglerJitterPercentageChange(e.target.value) } }} - options={[...jigglerJitterConfigs, { value: "custom", label: "Custom" }]} + options={[...jigglerJitterConfigs, {value: "custom", label: "Custom"}]} /> {jitterPercentage === "custom" && ( handleJigglerJitterPercentageChange(e.target.value)} /> )} +
+
{ handleJigglerInactivityLimitSecondsChange(e.target.value); diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx index 15d25a8..0a6d639 100644 --- a/ui/src/routes/devices.$id.settings.mouse.tsx +++ b/ui/src/routes/devices.$id.settings.mouse.tsx @@ -9,14 +9,15 @@ import { useDeviceSettingsStore, useSettingsStore } from "@/hooks/stores"; import { useJsonRpc } from "@/hooks/useJsonRpc"; import notifications from "@/notifications"; import { SettingsPageHeader } from "@components/SettingsPageheader"; +import { JigglerSetting } from "@components/JigglerSetting"; +import { SettingsSectionHeader } from "@components/SettingsSectionHeader"; import { FeatureFlag } from "../components/FeatureFlag"; import { SelectMenuBasic } from "../components/SelectMenuBasic"; import { useFeatureFlag } from "../hooks/useFeatureFlag"; import { SettingsItem } from "./devices.$id.settings"; -import { JigglerSetting } from "@components/JigglerSetting"; -import { SettingsSectionHeader } from "@components/SettingsSectionHeader"; + type ScrollSensitivity = "low" | "default" | "high";