kvm/jiggler.go

130 lines
2.7 KiB
Go

package kvm
import (
"github.com/go-co-op/gocron/v2"
"math/rand"
"time"
)
type JigglerConfig struct {
ActiveAfterSeconds int `json:"active_after_seconds"`
JitterEnabled bool `json:"jitter_enabled"`
JitterPercentage float64 `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
func rpcSetJigglerState(enabled bool) {
jigglerEnabled = enabled
}
func rpcGetJigglerState() bool {
return jigglerEnabled
}
func rpcGetJigglerConfig() (JigglerConfig, error) {
return *config.JigglerConfig, nil
}
func rpcSetJigglerConfig(jigglerConfig JigglerConfig) {
config.JigglerConfig = &jigglerConfig
err := removeExistingCrobJobs(scheduler)
if err != nil {
logger.Errorf("Error removing cron jobs from scheduler %v", err)
return
}
err = runJigglerCronTab()
if err != nil {
logger.Errorf("Error scheduling jiggler crontab: %v", err)
return
}
}
func removeExistingCrobJobs(s gocron.Scheduler) error {
for _, j := range s.Jobs() {
err := s.RemoveJob(j.ID())
if err != nil {
return err
}
}
return nil
}
func init() {
ensureConfigLoaded()
err := runJigglerCronTab()
if err != nil {
logger.Errorf("Error scheduling jiggler crontab: %v", err)
return
}
}
func runJigglerCronTab() error {
cronTab := config.JigglerConfig.ScheduleCronTab
s, err := gocron.NewScheduler()
if err != nil {
return err
}
scheduler = s
_, err = s.NewJob(
gocron.CronJob(
cronTab,
true,
),
gocron.NewTask(
func() {
runJiggler()
},
),
)
if err != nil {
return err
}
s.Start()
delta, err := calculateJobDelta(s)
jobDelta = delta
if err != nil {
return err
}
return nil
}
func runJiggler() {
if jigglerEnabled {
if config.JigglerConfig.JitterEnabled {
jitter := calculateJitterDuration(jobDelta)
logger.Infof("Jitter enabled, Sleeping for %v", jitter)
time.Sleep(jitter)
}
activeAfterSeconds := config.JigglerConfig.ActiveAfterSeconds
if time.Since(lastUserInput) > time.Duration(activeAfterSeconds)*time.Second {
//TODO: change to rel mouse
err := rpcAbsMouseReport(1, 1, 0)
if err != nil {
logger.Warnf("Failed to jiggle mouse: %v", err)
}
err = rpcAbsMouseReport(0, 0, 0)
if err != nil {
logger.Warnf("Failed to reset mouse position: %v", err)
}
}
}
}
func calculateJobDelta(s gocron.Scheduler) (time.Duration, error) {
j := s.Jobs()[0]
runs, err := j.NextRuns(2)
if err != nil {
return 0.0, err
}
return runs[1].Sub(runs[0]), nil
}
func calculateJitterDuration(delta time.Duration) time.Duration {
jitter := rand.Float64() * config.JigglerConfig.JitterPercentage * delta.Seconds()
return time.Duration(jitter * float64(time.Second))
}