Files
UpSnap/backend/networking/wake.go
2023-12-14 16:35:46 +01:00

97 lines
2.0 KiB
Go

package networking
import (
"bytes"
"context"
"fmt"
"os/exec"
"runtime"
"time"
"github.com/pocketbase/pocketbase/models"
"github.com/seriousm4x/upsnap/logger"
)
func WakeDevice(device *models.Record) error {
logger.Info.Println("Wake triggered for", device.GetString("name"))
wake_cmd := device.GetString("wake_cmd")
if wake_cmd != "" {
var shell string
var shell_arg string
if runtime.GOOS == "windows" {
shell = "cmd"
shell_arg = "/C"
} else {
shell = "/bin/sh"
shell_arg = "-c"
}
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
cmd := exec.CommandContext(ctx, shell, shell_arg, wake_cmd)
SetProcessAttributes(cmd)
var stderr bytes.Buffer
cmd.Stderr = &stderr
if err := cmd.Start(); err != nil {
logger.Error.Println(err)
}
done := make(chan error, 1)
go func() {
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 err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
return fmt.Errorf("%s not online after 2 minutes", device.GetString("name"))
}
isOnline := PingDevice(device)
if isOnline {
if err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
return nil
}
case err := <-done:
if err != nil {
if err := KillProcess(cmd.Process); err != nil {
logger.Error.Println(err)
}
return fmt.Errorf("%s", stderr.String())
}
}
}
} else {
err := SendMagicPacket(device)
if err != nil {
return err
}
// check state every seconds for 2 min
start := time.Now()
for {
time.Sleep(1 * time.Second)
isOnline := PingDevice(device)
if isOnline {
return nil
}
if time.Since(start) >= 2*time.Minute {
break
}
}
return fmt.Errorf(device.GetString("name"), "not online after 2 min")
}
}