fix: cli temperature read

changes:
- fix: read temperature values without daemon
  Add subcommand to read temperature values without starting the daemon

- fix: implement measured value types
  Replace measured value types with constants

- fix: add sensor pipelines
  Add functions which returns a channel with measured values

- fix: filter measured values from a channel
  Add functions to filter measured values by sensor id or measured
  value types.
This commit is contained in:
2020-09-21 19:36:42 +02:00
parent 7cbd80c726
commit 3a090d190e
17 changed files with 481 additions and 77 deletions

View File

@ -66,21 +66,21 @@ func (bme280 *BME280) Read() ([]*types.MeasuredValue, error) {
{
ID: uuid.NewV4().String(),
Value: float64(humidityValue),
ValueType: "humidity",
ValueType: types.Humidity,
Date: format.FormatedTime(),
SensorID: bme280.ID,
},
{
ID: uuid.NewV4().String(),
Value: float64(pressureValue),
ValueType: "pressure",
ValueType: types.Pressure,
Date: format.FormatedTime(),
SensorID: bme280.ID,
},
{
ID: uuid.NewV4().String(),
Value: float64(temperatureValue),
ValueType: "temperature",
ValueType: types.Temperature,
Date: format.FormatedTime(),
SensorID: bme280.ID,
},

View File

@ -42,14 +42,14 @@ func (dht11 *DHT11) Read() ([]*types.MeasuredValue, error) {
{
ID: uuid.NewV4().String(),
Value: float64(humidityValue),
ValueType: "humidity",
ValueType: types.Humidity,
Date: format.FormatedTime(),
SensorID: dht11.ID,
},
{
ID: uuid.NewV4().String(),
Value: float64(temperatureValue),
ValueType: "temperature",
ValueType: types.Temperature,
Date: format.FormatedTime(),
SensorID: dht11.ID,
},

View File

@ -42,14 +42,14 @@ func (dht22 *DHT22) Read() ([]*types.MeasuredValue, error) {
{
ID: uuid.NewV4().String(),
Value: float64(humidityValue),
ValueType: "humidity",
ValueType: types.Humidity,
Date: format.FormatedTime(),
SensorID: dht22.ID,
},
{
ID: uuid.NewV4().String(),
Value: float64(temperatureValue),
ValueType: "temperature",
ValueType: types.Temperature,
Date: format.FormatedTime(),
SensorID: dht22.ID,
},

View File

@ -59,7 +59,7 @@ func (ds18b20 *DS18B20) Read() ([]*types.MeasuredValue, error) {
{
ID: uuid.NewV4().String(),
Value: float64(temperatureValue),
ValueType: "temperature",
ValueType: types.Temperature,
Date: format.FormatedTime(),
SensorID: ds18b20.ID,
},

View File

@ -7,7 +7,8 @@ import (
)
type Sensor interface {
GetID() string
GetTicker() *time.Ticker
// Read single measured values from sensor
Read() ([]*types.MeasuredValue, error)
}

View File

@ -1,6 +1,7 @@
package sensor
import (
"context"
"errors"
"sync"
@ -11,6 +12,124 @@ var (
ErrSensorModelNotMatched = errors.New("Sensor model not matched")
)
// FilterMeasuredValuesByTypes filters measured values by type
func FilterMeasuredValuesByTypes(ctx context.Context, inChannel <-chan *types.MeasuredValue, measuredValueTypes ...types.MeasuredValueType) <-chan *types.MeasuredValue {
outChannel := make(chan *types.MeasuredValue, 0)
go func() {
LOOP:
for {
select {
case <-ctx.Done():
return
case measuredValue, open := <-inChannel:
if !open {
return
}
for i := range measuredValueTypes {
if measuredValueTypes[i] == measuredValue.ValueType {
outChannel <- measuredValue
continue LOOP
}
}
}
}
}()
return outChannel
}
// FilterMeasuredValuesBySensorIDs filters measured values by sensor id
func FilterMeasuredValuesBySensorIDs(ctx context.Context, inChannel <-chan *types.MeasuredValue, sensorIDs ...string) <-chan *types.MeasuredValue {
outChannel := make(chan *types.MeasuredValue, 0)
go func() {
LOOP:
for {
select {
case <-ctx.Done():
return
case measuredValue, open := <-inChannel:
if !open {
return
}
for i := range sensorIDs {
if sensorIDs[i] == measuredValue.SensorID {
outChannel <- measuredValue
continue LOOP
}
}
}
}
}()
return outChannel
}
// ReadPipeline pipes for each sensor measured values until the context has been
// closed. The returned channels will be closed
func ReadPipeline(ctx context.Context, sensors ...Sensor) (<-chan *types.MeasuredValue, <-chan error) {
var (
errorChannel = make(chan error, 0)
measuredValueChannel = make(chan *types.MeasuredValue, 0)
)
go func() {
wg := new(sync.WaitGroup)
for i := range sensors {
wg.Add(1)
go func(s Sensor) {
defer wg.Done()
measuredValues, err := s.Read()
if err != nil {
errorChannel <- err
return
}
for i := range measuredValues {
measuredValueChannel <- measuredValues[i]
}
}(sensors[i])
}
wg.Wait()
close(errorChannel)
close(measuredValueChannel)
}()
return measuredValueChannel, errorChannel
}
// ReadTickingPipeline pipes for every tick on each sensor measured values until
// the context has been closed
func ReadTickingPipeline(ctx context.Context, sensors ...Sensor) (<-chan *types.MeasuredValue, <-chan error) {
var (
errorChannel = make(chan error, 0)
measuredValueChannel = make(chan *types.MeasuredValue, 0)
)
for i := range sensors {
go func(s Sensor) {
for {
select {
case <-ctx.Done():
return
case <-s.GetTicker().C:
measuredValues, err := s.Read()
if err != nil {
errorChannel <- err
break
}
for i := range measuredValues {
measuredValueChannel <- measuredValues[i]
}
}
}
}(sensors[i])
}
return measuredValueChannel, errorChannel
}
// New returns a new sensor
func New(sensor *types.Sensor) (Sensor, error) {
switch sensor.Model {