package device import ( "errors" "fmt" "sync" "time" ) type SensorManager struct { SampleRate int `mapstructure:"sample_rate"` // in (ms) // sampling sampleMu sync.RWMutex LatestSample float32 SampleTimestamp int64 *DeviceManager `mapstructure:",squash"` // gRPC server pb.UnimplementedSensorServer } func NewSensorManager() *SensorManager { s := &SensorManager{} return s } func (s *SensorManager) SetDeviceManager(d *DeviceManager) { s.DeviceManager = d } type takeReading func(int, int) (float64, error) func (s *SensorManager) Start(f takeReading) error { // loading config if err := s.LoadConfig(); err != nil { return err } // starting if err := s.DeviceManager.Start(); err != nil { return err } // starting monitoring go s.Monitor(f) return nil } func (s *SensorManager) LoadConfig() error { // setting keys mainKey := fmt.Sprintf("devices.%d", s.Address) sampleKey := fmt.Sprintf("%s.sample_rate", mainKey) if !s.Config.IsSet(sampleKey) { // no sample rate, default to 10s s.Config.Set(sampleKey, 10000) } // loading lower s.DeviceManager.LoadConfig() s.Config.UnmarshalKey(mainKey, s) return nil } func (s *SensorManager) Monitor(f takeReading) { ch := make(chan struct{}) // hb chan go s.HeartBeat(ch, s.SampleRate, 2000, time.Millisecond) var reading float64 var err error for range ch { if reading, err = f(s.Bus, s.Address); err != nil { if !errors.Is(err, ErrReadFail) { // unknown error, panic panic(err) } fmt.Printf("Reading failed, skipping!\n") } // update sample if !errors.Is(err, ErrReadFail) { fmt.Printf("Got %f\n", reading) s.sampleMu.Lock() s.LatestSample = float32(reading) s.SampleTimestamp = time.Now.Unix() s.sampleMu.Unlock() } } }