62 lines
1.4 KiB
Go
62 lines
1.4 KiB
Go
// Package monitor provides a persistent monitor-only mode toggle.
|
|
// When active, the EMS continues polling and showing the status page
|
|
// but suppresses all actuator calls (Shelly switches, Viessmann API).
|
|
// State is stored as a flag file: presence = active, absence = normal.
|
|
package monitor
|
|
|
|
import (
|
|
"os"
|
|
"sync"
|
|
)
|
|
|
|
// Mode is a thread-safe, file-backed monitor-only flag.
|
|
type Mode struct {
|
|
mu sync.RWMutex
|
|
active bool
|
|
filePath string
|
|
}
|
|
|
|
// New creates a Mode and loads the current state from the flag file.
|
|
// If filePath is empty, the mode is in-memory only (not persistent).
|
|
func New(filePath string) *Mode {
|
|
m := &Mode{filePath: filePath}
|
|
if filePath != "" {
|
|
_, err := os.Stat(filePath)
|
|
m.active = err == nil // file exists → monitor-only
|
|
}
|
|
return m
|
|
}
|
|
|
|
// IsActive reports whether monitor-only mode is currently enabled.
|
|
func (m *Mode) IsActive() bool {
|
|
m.mu.RLock()
|
|
defer m.mu.RUnlock()
|
|
return m.active
|
|
}
|
|
|
|
// Set enables or disables monitor-only mode and persists the change to disk.
|
|
func (m *Mode) Set(active bool) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
m.active = active
|
|
|
|
if m.filePath == "" {
|
|
return nil // in-memory only
|
|
}
|
|
|
|
if active {
|
|
f, err := os.OpenFile(m.filePath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0600)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return f.Close()
|
|
}
|
|
|
|
err := os.Remove(m.filePath)
|
|
if os.IsNotExist(err) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|