package main import ( "context" "log" "os" "os/signal" "syscall" "time" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) func MonitorDevice(ctx context.Context, app *tview.Application, frame **tview.Frame, state *UIState, device *Device) { ticker := time.NewTicker(100 * time.Millisecond) // Check every 100ms defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: port, err := device.FindCardputer() if err != nil { if device.Connected { device.Close() state.Error = "Cardputer disconnected" UpdateDeviceStatus(app, *frame, state, "Waiting for cardputer...", tcell.ColorWhite) } else { UpdateDeviceStatus(app, *frame, state, "Waiting for cardputer...", tcell.ColorWhite) } } else { if !device.Connected { UpdateDeviceStatus(app, *frame, state, "Cardputer found: "+port, tcell.ColorWhite) err = device.Connect() if err != nil { UpdateDeviceStatus(app, *frame, state, "Error connecting to cardputer: "+err.Error(), tcell.ColorRed) SetError(state, err.Error()) } else { UpdateDeviceStatus(app, *frame, state, "Connected to cardputer: "+port, tcell.ColorGreen) if state.Error == "Cardputer disconnected" { state.Error = "" } } } else { UpdateDeviceStatus(app, *frame, state, "Connected to cardputer: "+port, tcell.ColorGreen) } } } } } func main() { // Initialize Device manager device := NewDevice() // Ensure cleanup happens no matter how we exit defer func() { log.Println("Cleanup: Disconnecting device...") if err := device.Close(); err != nil { log.Printf("Cleanup: Error disconnecting device: %v\n", err) } else { log.Println("Cleanup: Device disconnected successfully") } }() app := tview.NewApplication() var currentFrame *tview.Frame state := &UIState{ Page: "home", Error: "", } frame := AppUI(app, ¤tFrame, state, device) currentFrame = frame app.SetRoot(frame, true) ctx, cancel := context.WithCancel(context.Background()) defer cancel() // Set up signal handling for graceful shutdown sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) // Handle signals in a goroutine go func() { <-sigChan log.Println("Signal received, shutting down...") // Cancel context to stop monitoring cancel() // Stop the application app.Stop() }() go MonitorDevice(ctx, app, ¤tFrame, state, device) if err := app.Run(); err != nil { log.Fatal("Error running program:", err) } }