package sensor import ( "context" "fmt" "log" "sync" "time" "github.com/d2r2/go-bsbmp" "github.com/d2r2/go-i2c" "github.com/d2r2/go-logger" "github.com/go-flucky/flucky/pkg/types" uuid "github.com/satori/go.uuid" ) // BME280 is a sensor to measure humidity and temperature. type BME280 struct { *types.Sensor } // GetSensorModel returns the sensor model func (s *BME280) GetSensorModel() types.SensorModel { return s.Sensor.SensorModel } // Read measured values func (s *BME280) Read() ([]*types.MeasuredValue, error) { // Create new connection to i2c-bus on 1 line with address 0x76. // Use i2cdetect utility to find device address over the i2c-bus i2c, err := i2c.NewI2C(*s.I2CAddress, *s.I2CBus) if err != nil { log.Fatal(err) } defer i2c.Close() logger.ChangePackageLogLevel("i2c", logger.InfoLevel) sensor, err := bsbmp.NewBMP(bsbmp.BME280, i2c) if err != nil { log.Fatal(err) } logger.ChangePackageLogLevel("bsbmp", logger.InfoLevel) temperatureValue, err := sensor.ReadTemperatureC(bsbmp.ACCURACY_STANDARD) if err != nil { log.Fatal(err) } pressureValue, err := sensor.ReadPressurePa(bsbmp.ACCURACY_STANDARD) if err != nil { log.Fatal(err) } // pressureValueRound := math.Round(float64(pressureValue)/10*0.25) * 10 / 0.25 _, humidityValue, err := sensor.ReadHumidityRH(bsbmp.ACCURACY_STANDARD) if err != nil { log.Fatal(err) } measuredValues := []*types.MeasuredValue{ &types.MeasuredValue{ ID: uuid.NewV4().String(), Value: float64(humidityValue), ValueType: types.MeasuredValueTypeHumidity, FromDate: time.Now(), TillDate: time.Now(), SensorID: s.SensorID, }, &types.MeasuredValue{ ID: uuid.NewV4().String(), Value: float64(pressureValue), ValueType: types.MeasuredValueTypePressure, FromDate: time.Now(), TillDate: time.Now(), SensorID: s.SensorID, }, &types.MeasuredValue{ ID: uuid.NewV4().String(), Value: float64(temperatureValue), ValueType: types.MeasuredValueTypeTemperature, FromDate: time.Now(), TillDate: time.Now(), SensorID: s.SensorID, }, } return measuredValues, nil } // ReadChannel reads the measured values from the sensor and writes them to a // channel. func (s *BME280) ReadChannel(measuredValuesChannel chan<- []*types.MeasuredValue, errorChannel chan<- error, wg *sync.WaitGroup) { if wg != nil { defer wg.Done() } measuredValues, err := s.Read() if err != nil { errorChannel <- err return } measuredValuesChannel <- measuredValues } // ReadContinously reads the measured values continously from the sensor and // writes them to a channel. func (s *BME280) ReadContinously(ctx context.Context, measuredValuesChannel chan<- []*types.MeasuredValue, errorChannel chan<- error) { for { select { case <-ctx.Done(): errorChannel <- fmt.Errorf("%v: Context closed: %v", s.SensorName, ctx.Err()) return default: s.ReadChannel(measuredValuesChannel, errorChannel, nil) } } }