feat(pkg/sensor): new support for sensor bme280

This commit is contained in:
2019-06-30 14:34:13 +02:00
parent 96eb1f4036
commit 289aaf2093
20 changed files with 309 additions and 87 deletions

View File

@ -13,14 +13,16 @@ import (
)
var humiditySensorModels = map[types.SensorModel]types.SensorModel{
types.DHT11: types.DHT11,
types.DHT22: types.DHT22,
types.DHT11: types.DHT11,
types.DHT22: types.DHT22,
types.BME280: types.BME280,
}
var temperatureSensorModels = map[types.SensorModel]types.SensorModel{
types.DHT11: types.DHT11,
types.DHT22: types.DHT22,
types.DS18B20: types.DS18B20,
types.BME280: types.BME280,
}
// Configuration of flucky
@ -82,9 +84,10 @@ func (c *Configuration) AddSensor(sensor *types.Sensor) error {
return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID)
}
if *sensor.WireID != "" &&
*s.WireID == *sensor.WireID {
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName)
if sensor.WireID != nil {
if *s.WireID == *sensor.WireID {
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName)
}
}
}
@ -260,8 +263,6 @@ func (c *Configuration) GetHumiditySensorsByName(names []string) []sensor.Sensor
switch name {
case s.SensorID:
configHumiditySensors[s.SensorID] = s
case *s.WireID:
configHumiditySensors[s.SensorID] = s
case s.SensorName:
configHumiditySensors[s.SensorID] = s
}
@ -381,8 +382,6 @@ func (c *Configuration) GetTemperatureSensorsByName(names []string) []sensor.Sen
switch name {
case s.SensorID:
configTemperatureSensors[s.SensorID] = s
case *s.WireID:
configTemperatureSensors[s.SensorID] = s
case s.SensorName:
configTemperatureSensors[s.SensorID] = s
}
@ -464,6 +463,10 @@ func (c *Configuration) convertSensors(sensors []*types.Sensor) []sensor.Sensor
for _, s := range sensors {
switch s.SensorModel {
case types.BME280:
cachedSensors = append(cachedSensors, &sensor.BME280{
Sensor: s,
})
case types.DHT11:
cachedSensors = append(cachedSensors, &sensor.DHT11{
Sensor: s,

View File

@ -16,7 +16,7 @@ import (
)
// Start the daemon
func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compression bool, logger logger.Logger) {
func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compression bool, round float64, logger logger.Logger) {
// Info
logger.Info("Use clean-cache-interval: %v", cleanCacheInterval.String())
@ -33,7 +33,7 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
ctx := context.Background()
childContext, cancel := context.WithCancel(ctx)
logfile := logfile.New(cnf.Device.Logfile)
measuredValuesLogfile := logfile.New(cnf.Device.Logfile)
measuredValuesCache := make([]types.MeasuredValue, 0)
@ -66,7 +66,7 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
logger.Error("Can not turn on blue info light: %v", err)
}
err = logfile.Append(compression, measuredValuesCache)
err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache)
if err != nil {
err = rgbled.Error(rgbLEDs)
@ -92,8 +92,8 @@ func Start(cnf *config.Configuration, cleanCacheInterval time.Duration, compress
logger.Error("Can not turn on red info light: %v", err)
}
logger.Warn("Save remaining data from the cache: %v", len(measuredValuesCache))
err = logfile.Append(compression, measuredValuesCache)
logger.Warn("Save remaining data from the cache")
err = logfile.Append(measuredValuesLogfile, compression, round, measuredValuesCache)
if err != nil {
logger.Fatal("%v", err)
}

View File

@ -14,28 +14,6 @@ type csvLogfile struct {
logfile string
}
func (cl *csvLogfile) Append(compression bool, measuredValues []types.MeasuredValue) error {
allMeasuredValues, err := cl.Read()
if err != nil {
return err
}
allMeasuredValues = append(allMeasuredValues, measuredValues...)
if compression {
allMeasuredValues = Compression(allMeasuredValues)
}
err = cl.Write(allMeasuredValues)
if err != nil {
return err
}
return nil
}
func (cl *csvLogfile) Read() ([]types.MeasuredValue, error) {
if _, err := os.Stat(cl.logfile); os.IsNotExist(err) {
return nil, fmt.Errorf("%v: %v", errorLogfileNotFound, cl.logfile)

View File

@ -5,7 +5,6 @@ import (
)
type Logfile interface {
Append(compression bool, measuredValues []types.MeasuredValue) error
Read() ([]types.MeasuredValue, error)
Write(measuredValues []types.MeasuredValue) error
}

View File

@ -17,28 +17,6 @@ type jsonLogfile struct {
logfile string
}
func (jl *jsonLogfile) Append(compression bool, measuredValues []types.MeasuredValue) error {
allMeasuredValues, err := jl.Read()
if err != nil {
return err
}
allMeasuredValues = append(allMeasuredValues, measuredValues...)
if compression {
allMeasuredValues = Compression(allMeasuredValues)
}
err = jl.Write(allMeasuredValues)
if err != nil {
return err
}
return nil
}
func (jl *jsonLogfile) Read() ([]types.MeasuredValue, error) {
if _, err := os.Stat(jl.logfile); os.IsNotExist(err) {

View File

@ -1,6 +1,7 @@
package logfile
import (
"math"
"path/filepath"
"sort"
"time"
@ -9,7 +10,35 @@ import (
)
// var validUUID = regexp.MustCompile("^[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-4[a-fA-F0-9]{3}-[8|9|aA|bB][a-fA-F0-9]{3}-[a-fA-F0-9]{12}$")
var timeFormat = time.RFC3339
var timeFormat = "2006-01-02T15:04:05.999999Z07:00"
func Append(logfile Logfile, compression bool, round float64, measuredValues []types.MeasuredValue) error {
if round != 0 {
for _, measuredValue := range measuredValues {
measuredValue.SetValue(math.Round(measuredValue.GetValue()/round) * round)
}
}
allMeasuredValues, err := logfile.Read()
if err != nil {
return err
}
allMeasuredValues = append(allMeasuredValues, measuredValues...)
if compression {
allMeasuredValues = Compression(allMeasuredValues)
}
err = logfile.Write(allMeasuredValues)
if err != nil {
return err
}
return nil
}
// Compression the measured values. The system checks whether the measured values
// of the same type correspond to those of the predecessor. If this is the case,

112
pkg/sensor/bme280.go Normal file
View File

@ -0,0 +1,112 @@
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)
}
// p, err := sensor.ReadPressurePa(bsbmp.ACCURACY_STANDARD)
// if err != nil {
// log.Fatal(err)
// }
_, humidityValue, err := sensor.ReadHumidityRH(bsbmp.ACCURACY_STANDARD)
if err != nil {
log.Fatal(err)
}
measuredValues := []types.MeasuredValue{
&types.Humidity{
HumidityID: uuid.NewV4().String(),
HumidityValue: float64(humidityValue),
HumidityFromDate: time.Now(),
HumidityTillDate: time.Now(),
SensorID: s.SensorID,
},
&types.Temperature{
TemperatureID: uuid.NewV4().String(),
TemperatureValue: float64(temperatureValue),
TemperatureFromDate: time.Now(),
TemperatureTillDate: 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)
}
}
}

View File

@ -45,6 +45,10 @@ func (h *Humidity) GetMeasuredValueType() MeasuredValueType {
return MeasuredValueTypeHumidity
}
func (h *Humidity) SetValue(value float64) {
h.HumidityValue = value
}
func (h *Humidity) SetTillDate(date time.Time) {
h.HumidityTillDate = date
}

View File

@ -12,6 +12,7 @@ type MeasuredValue interface {
GetCreationDate() *time.Time
GetUpdateDate() *time.Time
SetValue(value float64)
SetTillDate(date time.Time)
SetCreationDate(date *time.Time)
SetUpdateDate(date *time.Time)

View File

@ -13,6 +13,8 @@ type Sensor struct {
SensorName string `json:"sensor_name" xml:"sensor_name"`
SensorLocation string `json:"sensor_location" xml:"sensor_location"`
WireID *string `json:"wire_id" xml:"wire_id"`
I2CBus *int `json:"i2c_bus" xml:"i2c_bus"`
I2CAddress *uint8 `json:"i2c_address" xml:"i2c_address"`
GPIONumber *GPIO `json:"gpio_number" xml:"gpio_number"`
SensorModel SensorModel `json:"sensor_model" xml:"sensor_model"`
SensorEnabled bool `json:"sensor_enabled" xml:"sensor_enabled"`
@ -46,6 +48,9 @@ func (s *Sensor) Name() string {
return s.SensorName
} else if s.WireID != nil {
return *s.WireID
} else if s.I2CAddress != nil &&
s.I2CBus != nil {
return fmt.Sprintf("%v/%v", *s.I2CBus, *s.I2CAddress)
}
return s.SensorID
}

View File

@ -5,7 +5,8 @@ import "fmt"
type SensorModel string
const (
DHT11 SensorModel = "DHT11"
BME280 SensorModel = "BME280"
DHT11 = "DHT11"
DHT22 = "DHT22"
DS18B20 = "DS18B20"
)
@ -13,6 +14,8 @@ const (
// SelectSensorModel converts a string into a constant
func SelectSensorModel(model string) (SensorModel, error) {
switch model {
case "BME280":
return BME280, nil
case "DHT11":
return DHT11, nil
case "DHT22":

View File

@ -47,6 +47,10 @@ func (t *Temperature) GetMeasuredValueType() MeasuredValueType {
return MeasuredValueTypeTemperature
}
func (t *Temperature) SetValue(value float64) {
t.TemperatureValue = value
}
func (t *Temperature) SetTillDate(date time.Time) {
t.TemperatureTillDate = date
}