refactor: temperature

This commit is contained in:
2019-02-24 22:46:36 +01:00
parent d6f41b8105
commit 1a3a31c5f2
24 changed files with 605 additions and 292 deletions

73
pkg/cli/cli.go Normal file
View File

@ -0,0 +1,73 @@
package cli
import (
"fmt"
"io"
"text/tabwriter"
"git.cryptic.systems/fh-trier/go-flucky/pkg/config"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
func PrintTemperatures(temperatures []*types.Temperature, cnf *config.FluckyConfig, w io.Writer) {
sensors := []*types.Sensor{}
// Search after sensors
for _, temperature := range temperatures {
found := false
// Search for the sensor that has acquired the measured value
for _, sensor := range cnf.Sensors {
if sensor.SensorID == temperature.SensorID {
sensors = append(sensors, sensor)
found = true
break
}
}
// If it was not found, pass only the sensor with the UUID on
if !found {
sensor := &types.Sensor{
SensorID: temperature.SensorID,
}
sensors = append(sensors, sensor)
}
}
// sort temperature values for every sensor
orderedTemperatures := make(map[string][]*types.Temperature)
for _, temperature := range temperatures {
orderedTemperatures[temperature.SensorID] = append(orderedTemperatures[temperature.SensorID], temperature)
}
// declare tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
// headlines
for _, sensor := range sensors {
fmt.Fprintf(tw, "%v\t", sensor.Name())
}
fmt.Fprintf(tw, "\n")
// find sensor with maximum temperature values
maxLength := 0
for _, orderedTemperature := range orderedTemperatures {
if len(orderedTemperature) > maxLength {
maxLength = len(orderedTemperature)
}
}
// body
for i := 0; i < maxLength; i++ {
for _, sensor := range sensors {
if len(orderedTemperatures[sensor.SensorID]) > i {
fmt.Fprintf(tw, "%3.3f\t", orderedTemperatures[sensor.SensorID][i].TemperatureValue)
} else {
fmt.Fprint(tw, "\t")
}
fmt.Fprint(tw, "\n")
}
}
tw.Flush()
}

View File

@ -6,10 +6,12 @@ import (
"fmt"
"io"
"text/tabwriter"
"time"
"git.cryptic.systems/fh-trier/go-flucky/pkg/sensor"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
"github.com/satori/go.uuid"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
)
// FluckyConfig dasd
@ -37,12 +39,23 @@ func (fc *FluckyConfig) AddSensor(sensor *types.Sensor) error {
return fmt.Errorf("Sensor %v with UUID %v already exists", s.SensorName, s.SensorID)
}
if sensor.WireID != nil &&
s.WireID == sensor.WireID {
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", s.WireID, s.SensorName)
if *sensor.WireID != "" &&
*s.WireID == *sensor.WireID {
return fmt.Errorf("Sensor with 1wire-id %v already exists as %v", *s.WireID, s.SensorName)
}
}
// check if sensor has a valid device id
if sensor.DeviceID != fc.Device.DeviceID {
sensor.DeviceID = fc.Device.DeviceID
}
// overwrite creation date
sensor.CreationDate = time.Now()
//TODO: check if wire sensor exists in /dev/bus/w1/devices
// check
fc.Sensors = append(fc.Sensors, sensor)
return nil
@ -110,8 +123,8 @@ func (fc *FluckyConfig) DisableSensor(nameOrUUID string) error {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
*sensor.SensorName == nameOrUUID {
*sensor.SensorEnabled = false
sensor.SensorName == nameOrUUID {
sensor.SensorEnabled = false
found = true
break
}
@ -119,7 +132,7 @@ func (fc *FluckyConfig) DisableSensor(nameOrUUID string) error {
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
sensor.SensorID == nameOrUUID {
*sensor.SensorEnabled = false
sensor.SensorEnabled = false
found = true
break
}
@ -170,8 +183,8 @@ func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
*sensor.SensorName == nameOrUUID {
*sensor.SensorEnabled = true
sensor.SensorName == nameOrUUID {
sensor.SensorEnabled = true
found = true
break
}
@ -179,7 +192,7 @@ func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error {
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
sensor.SensorID == nameOrUUID {
*sensor.SensorEnabled = true
sensor.SensorEnabled = true
found = true
break
}
@ -192,6 +205,45 @@ func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error {
return nil
}
func (fc *FluckyConfig) GetHumiditySensors() []sensor.HumiditySensor {
hs := []sensor.HumiditySensor{}
// for _, s := range fc.Sensors {
// switch s.SensorType {
// case "DHT11":
// hs = append(hs, sensor.DHT11Sensor{
// Sensor: s,
// })
// case "DHT22":
// hs = append(hs, sensor.DHT22Sensor{
// Sensor: s,
// })
// }
// }
return hs
}
func (fc *FluckyConfig) GetTemperatureSensors() []sensor.TemperatureSensor {
ts := []sensor.TemperatureSensor{}
for _, s := range fc.Sensors {
switch s.SensorType {
case "DHT11":
ts = append(ts, &sensor.DHT11Sensor{
Sensor: s,
})
case "DHT22":
ts = append(ts, &sensor.DHT22Sensor{
Sensor: s,
})
case "DS18B20":
ts = append(ts, &sensor.DS18B20{
Sensor: s,
})
}
}
return ts
}
// JSONDecoder decode a JSON string from a reader into a struct
func (fc *FluckyConfig) JSONDecoder(r io.Reader) error {
jsonDecoder := json.NewDecoder(r)
@ -234,10 +286,10 @@ func (fc *FluckyConfig) PrintSensors(w io.Writer) error {
// declar tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
fmt.Fprint(tw, "id\tname\tlocation\ttype\twire-id\tgpio\tenabled\n")
fmt.Fprint(tw, "name\tlocation\ttype\twire-id\tgpio\tenabled\n")
for _, sensor := range fc.Sensors {
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\t%v\n", sensor.SensorID, *sensor.SensorName, *sensor.SensorLocation, *sensor.SensorType, *sensor.WireID, *sensor.GPIONumber, *sensor.SensorEnabled)
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%v\n", sensor.SensorName, sensor.SensorLocation, sensor.SensorType, *sensor.WireID, *sensor.GPIONumber, sensor.SensorEnabled)
}
tw.Flush()
@ -253,10 +305,9 @@ func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error {
// remove machted name
if !validUUID.MatchString(nameOrUUID) &&
*sensor.SensorName == nameOrUUID {
sensor.SensorName == nameOrUUID {
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
found = true
break
}
// remove machted uuid
@ -264,12 +315,11 @@ func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error {
sensor.SensorID == nameOrUUID {
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
found = true
break
}
}
if !found {
return fmt.Errorf("Can not find remote %v", nameOrUUID)
return fmt.Errorf("Can not find sensor %v", nameOrUUID)
}
return nil

View File

@ -1,6 +1,6 @@
package config
import "git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
import "git.cryptic.systems/fh-trier/go-flucky/pkg/types"
// Remote ...
type Remote struct {

View File

@ -0,0 +1,31 @@
package errutils
import (
"fmt"
)
func CollectErrors(errChan <-chan error) []error {
errorList := make([]error, 0)
for {
select {
case err, more := <-errChan:
if more {
errorList = append(errorList, err)
continue
}
default:
return errorList
}
}
}
func FormatErrors(errorList []error) error {
if len(errorList) > 0 {
errMsg := ""
for _, err := range errorList {
errMsg = fmt.Sprintf("%v\n%v", errMsg, err.Error())
}
return fmt.Errorf(errMsg)
}
return nil
}

View File

@ -3,14 +3,19 @@ package sensor
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
type DHT11Sensor struct {
*types.Sensor
}
func (s *DHT11Sensor) Read() (interface{}, error) {
func (s *DHT11Sensor) ReadHumidity() (*types.Humidity, error) {
log.Println("DHT11 Read Method not yet implemented")
return nil, nil
}
func (s *DHT11Sensor) ReadTemperature() (*types.Temperature, error) {
log.Println("DHT11 Read Method not yet implemented")
return nil, nil
}

View File

@ -3,14 +3,19 @@ package sensor
import (
"log"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
type DHT22Sensor struct {
*types.Sensor
}
func (s *DHT22Sensor) Read() (interface{}, error) {
func (s *DHT22Sensor) ReadHumidity() (*types.Humidity, error) {
log.Println("DHT11 Read Method not yet implemented")
return nil, nil
}
func (s *DHT22Sensor) ReadTemperature() (*types.Temperature, error) {
log.Println("DHT22 Read Method not yet implemented")
return nil, nil
}

View File

@ -4,7 +4,7 @@ import (
"fmt"
"time"
"git.cryptic.systems/fh-trier/go-flucky-server/pkg/types"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
uuid "github.com/satori/go.uuid"
"github.com/yryz/ds18b20"
)
@ -13,7 +13,7 @@ type DS18B20 struct {
*types.Sensor
}
func (s *DS18B20) Read() (interface{}, error) {
func (s *DS18B20) ReadTemperature() (*types.Temperature, error) {
t, err := ds18b20.Temperature(*s.WireID)
if err != nil {

View File

@ -1,7 +1,115 @@
package sensor
type Sensor interface {
Read() (interface{}, error)
import (
"sync"
"git.cryptic.systems/fh-trier/go-flucky/pkg/internal/errutils"
"git.cryptic.systems/fh-trier/go-flucky/pkg/types"
)
type HumiditySensor interface {
ReadHumidity() (*types.Humidity, error)
}
// func ReadTemperatures
type TemperatureSensor interface {
ReadTemperature() (*types.Temperature, error)
}
func ReadHumidities(humiditySensors []HumiditySensor) ([]*types.Humidity, error) {
wg := new(sync.WaitGroup)
wg.Add(len(humiditySensors))
errChannel := make(chan error, len(humiditySensors))
humidityChannel := make(chan *types.Humidity, len(humiditySensors))
for _, humiditySensor := range humiditySensors {
go func(hs HumiditySensor) {
defer wg.Done()
humidity, err := hs.ReadHumidity()
if err != nil {
errChannel <- err
humidityChannel <- nil
}
errChannel <- nil
humidityChannel <- humidity
}(humiditySensor)
}
wg.Wait()
errorList := errutils.CollectErrors(errChannel)
if err := errutils.FormatErrors(errorList); err != nil {
return nil, err
}
humidityList := collectHumidities(humidityChannel)
return humidityList, nil
}
func ReadTemperatures(temperatureSensors []TemperatureSensor) ([]*types.Temperature, error) {
wg := new(sync.WaitGroup)
wg.Add(len(temperatureSensors))
errChannel := make(chan error, len(temperatureSensors))
temperatureChannel := make(chan *types.Temperature, len(temperatureSensors))
for _, temperatureSensor := range temperatureSensors {
go func(ts TemperatureSensor) {
defer wg.Done()
temperature, err := ts.ReadTemperature()
if err != nil {
errChannel <- err
}
temperatureChannel <- temperature
}(temperatureSensor)
}
wg.Wait()
errorList := errutils.CollectErrors(errChannel)
if err := errutils.FormatErrors(errorList); err != nil {
return nil, err
}
temperatureList := collectTemperatures(temperatureChannel)
return temperatureList, nil
}
func collectHumidities(humChan <-chan *types.Humidity) []*types.Humidity {
humidityList := make([]*types.Humidity, 0)
for {
select {
case hum, more := <-humChan:
if more {
humidityList = append(humidityList, hum)
continue
}
return nil
default:
return humidityList
}
}
}
func collectTemperatures(tempChan <-chan *types.Temperature) []*types.Temperature {
temperatureList := make([]*types.Temperature, 0)
for {
select {
case temp, more := <-tempChan:
if more {
temperatureList = append(temperatureList, temp)
continue
}
return nil
default:
return temperatureList
}
}
}

29
pkg/types/sensor.go Normal file
View File

@ -0,0 +1,29 @@
package types
import (
"time"
)
// Sensor ...
type Sensor struct {
SensorID string `json:"sensor_id"`
SensorName string `json:"sensor_name"`
SensorLocation string `json:"sensor_location"`
WireID *string `json:"wire_id"`
GPIONumber *string `json:"gpio_number"`
SensorType string `json:"sensor_type"`
SensorEnabled bool `json:"sensor_enabled"`
SensorLastContact time.Time `json:"sensor_last_contact"`
DeviceID string `json:"device_id"`
CreationDate time.Time `json:"creation_date"`
}
func (s *Sensor) Name() string {
if s.SensorName != "" {
return s.SensorName
} else if *s.WireID != "" {
return *s.WireID
}
return s.SensorID
}

32
pkg/types/types.go Normal file
View File

@ -0,0 +1,32 @@
package types
import (
"time"
)
// Device ...
type Device struct {
DeviceID string `json:"device_id"`
DeviceName *string `json:"device_name"`
DeviceLocation *string `json:"device_location"`
DeviceLastContact time.Time `json:"device_last_contact"`
CreationDate time.Time `json:"creation_date"`
}
// Humidity ...
type Humidity struct {
HumidityID string `json:"humidity_id"`
HumidityValue float64 `json:"humidity_value,string"`
HumidityDate time.Time `json:"humidity_date"`
SensorID string `json:"sensor_id"`
CreationDate time.Time `json:"creation_date"`
}
// Temperature ...
type Temperature struct {
TemperatureID string `json:"temperature_id"`
TemperatureValue float64 `json:"temperature_value,string"`
TemperatureDate time.Time `json:"temperature_date"`
SensorID string `json:"sensor_id"`
CreationDate time.Time `json:"creation_date"`
}