package sensor import ( _"fmt" "time" "sync" "strings" _ "FRMS/internal/pkg/I2C" "log" ) type Manager struct { *Dev I2CDevice *Active Hb time.Duration } type Active struct { sync.Mutex bool int } type Dev struct { // last known values Addr int Type string Status string // could be more efficient but to hell with it Data string } type I2CDevice interface { // basic device info GetAddr() int GetStatus() string GetType() string GetData() string } func NewDeviceManager(i2c I2CDevice) *Manager { m := &Manager{Hb:time.Duration(1*time.Second)} m.I2CDevice = i2c m.Active = &Active{} m.Dev = &Dev{Addr:i2c.GetAddr(),Type:i2c.GetType(),Status:i2c.GetStatus(),Data:i2c.GetData()} return m } func (m *Manager) Start() { // goal is to start a long running monitoring routine if !m.Activate() { log.Fatal("Manager already running!") } // atomically activated if this runs // go m.Monitor() } func (m *Manager) Exit() { if !m.Deactivate() { log.Fatal("Manager already exited!") } } func (m *Manager) GetType() string { return m.Type } func (m *Manager) GetStatus() string { m.Status = m.I2CDevice.GetStatus() if m.IsActive() && strings.Contains(m.Status,"KILLED") { m.Exit() } return m.Status } func (m *Manager) GetData() string { m.Data = m.I2CDevice.GetData() return m.Data } func (m *Manager) GetAddr() int { return m.Addr } // atomic activation and deactivation func (a *Active) Activate() bool { // returns true if success, false otherwise a.Lock() defer a.Unlock() if a.bool { // already active return false } else { a.bool = true a.int = 0 return a.bool } } func (a *Active) Deactivate() bool { // returns true if success false otherise a.Lock() defer a.Unlock() if a.bool { a.bool = false return true } else { // already deactivated return a.bool // false } } func (a *Active) IsActive() bool { a.Lock() defer a.Unlock() return a.bool }