diff --git a/cmd/main.go b/cmd/main.go index f49bbee..b843258 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -37,7 +37,7 @@ func main() { }() // Create service layer - svc := service.NewService(mainLogger) + svc := service.NewService(rootLogger) mainLogger.Info("service initialized") diff --git a/internal/app/app.go b/internal/app/app.go index 1dc9505..7e00107 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -60,7 +60,8 @@ func (app *App) Pause() error { switch app.state { case StatePaused: - return fmt.Errorf("application is already paused") + app.logger.Warn("application is already paused") + return nil case StateRunning: // valid state to pause from, do nothing default: @@ -96,13 +97,15 @@ func (app *App) Pause() error { } // Resume connects to the server and initiates background tasks +// This function does not block permanently, it will return very quickly with an error if anything goes wrong. func (app *App) Resume() error { app.mu.Lock() defer app.mu.Unlock() switch app.state { case StateRunning: - return fmt.Errorf("application is already running") + app.logger.Warn("application is already running") + return nil case StatePaused: // valid state to resume from, do nothing default: @@ -128,8 +131,13 @@ func (app *App) Resume() error { app.config = DefaultConfig() + if err := app.config.Validate(); err != nil { + app.logger.Error("invalid configuration", "error", err) + return err + } + app.ha, err = ga.NewApp(ga.NewAppRequest{ - URL: app.config.Server, + URL: *app.config.Server, HAAuthToken: app.config.APIKey, }) if err != nil { diff --git a/internal/app/tray.go b/internal/app/tray.go index 3f124fc..b5ba011 100644 --- a/internal/app/tray.go +++ b/internal/app/tray.go @@ -60,7 +60,8 @@ func (t *Tray) SetIcon(icon IconReference) error { func (t *Tray) Start(title string) error { if t.active { - return fmt.Errorf("tray is already active") + t.logger.Warn("tray is already active") + return nil } t.logger.Info("attempting to start systray", "title", title) diff --git a/internal/service/windows.go b/internal/service/windows.go index 716002a..2f97947 100644 --- a/internal/service/windows.go +++ b/internal/service/windows.go @@ -15,8 +15,9 @@ import ( "golang.org/x/sys/windows/registry" ) -// WindowsTrayService implements the Service interface for Windows as a user application -type WindowsTrayService struct { +// windowsService implements the Service interface for Windows +// Note that this is a user application, not a true SCM service +type windowsService struct { app *app.App logger *slog.Logger restartCount int @@ -28,7 +29,7 @@ type WindowsTrayService struct { // NewService creates a new Windows tray service instance func NewService(logger *slog.Logger) Service { - return &WindowsTrayService{ + return &windowsService{ logger: logger.With("type", "service", "variant", "windows"), app: app.NewApp(logger), maxRestarts: 3, @@ -39,7 +40,7 @@ func NewService(logger *slog.Logger) Service { } // Run implements the Service interface for Windows -func (svc *WindowsTrayService) Run() error { +func (svc *windowsService) Run() error { svc.logger.Info("starting Windows tray service") // Setup auto-start if not already configured @@ -79,11 +80,12 @@ func (svc *WindowsTrayService) Run() error { } // runServiceLoop runs the main service loop -func (svc *WindowsTrayService) runServiceLoop(sigs chan os.Signal) error { +func (svc *windowsService) runServiceLoop(sigs chan os.Signal) error { // Start the application in background go func() { if err := svc.app.Resume(); err != nil { svc.logger.Error("failed to start app layer", "error", err) + } }() @@ -128,7 +130,7 @@ func (svc *WindowsTrayService) runServiceLoop(sigs chan os.Signal) error { } // setupAutoStart configures the application to start automatically on login -func (svc *WindowsTrayService) setupAutoStart() error { +func (svc *windowsService) setupAutoStart() error { exePath, err := os.Executable() if err != nil { return fmt.Errorf("failed to get executable path: %v", err) @@ -152,7 +154,7 @@ func (svc *WindowsTrayService) setupAutoStart() error { } // removeAutoStart removes the auto-start configuration -func (svc *WindowsTrayService) removeAutoStart() error { +func (svc *windowsService) removeAutoStart() error { key, err := registry.OpenKey(registry.CURRENT_USER, `Software\Microsoft\Windows\CurrentVersion\Run`, registry.SET_VALUE) if err != nil { return fmt.Errorf("failed to open registry key: %v", err) @@ -168,7 +170,7 @@ func (svc *WindowsTrayService) removeAutoStart() error { } // setupPowerManagement handles sleep/wake events -func (svc *WindowsTrayService) setupPowerManagement() { +func (svc *windowsService) setupPowerManagement() { // TODO: Implement Windows power management // - Listen for WM_POWERBROADCAST messages // - Handle system sleep/wake events @@ -177,7 +179,7 @@ func (svc *WindowsTrayService) setupPowerManagement() { } // isAppHealthy checks if the application is running properly -func (svc *WindowsTrayService) isAppHealthy() bool { +func (svc *windowsService) isAppHealthy() bool { // TODO: Implement health checks // - Check if Home Assistant connection is alive // - Check if systray is responsive