package main import ( "os" "os/exec" "time" ) // deviceManager handles periodic maintenance of the Meshtastic device func deviceManager(shutdown chan struct{}, dryRun bool) { logInfo("device", "Starting device manager", map[string]interface{}{ "rebootInterval": DEVICE_REBOOT_INTERVAL.String(), "dryRun": dryRun, }) // Wait some time before first reboot to allow system startup initialDelay := 5 * time.Minute logInfo("device", "Waiting before first device reboot", map[string]interface{}{ "initialDelay": initialDelay.String(), }) select { case <-time.After(initialDelay): // Continue after delay case <-shutdown: logInfo("device", "Shutdown signal received during initial delay", nil) return } // Reboot immediately after startup delay rebootDevice(dryRun) // Then run on interval ticker := time.NewTicker(DEVICE_REBOOT_INTERVAL) defer ticker.Stop() for { select { case <-ticker.C: rebootDevice(dryRun) case <-shutdown: logInfo("device", "Shutting down device manager", nil) return } } } // rebootDevice executes the meshtastic --reboot command func rebootDevice(dryRun bool) { cmdStr := "meshtastic --reboot" logInfo("device", "Rebooting Meshtastic device", map[string]interface{}{ "command": cmdStr, "dryRun": dryRun, "time": time.Now().Format("15:04:05 MST"), }) if dryRun { logInfo("device", "DRY RUN - would execute device reboot", nil) return } // Execute the reboot command cmd := exec.Command("meshtastic", "--reboot") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { logInfo("device", "Device reboot failed", map[string]interface{}{ "error": err.Error(), }) } else { logInfo("device", "Device reboot successful", nil) } }