fix: breaking changes

changes:
- remove remote operations
- add function to write measured values into a channel
- add get humidity sensors from config
- add get temperature sensors from config
- remove FileLogger
- exclude some functions from pkf into internal
This commit is contained in:
Markus Pesch 2019-06-13 21:25:32 +02:00
parent 98e5f3a536
commit 5220eac16b
Signed by: volker.raschek
GPG Key ID: 852BCC170D81A982
39 changed files with 481 additions and 1376 deletions

View File

@ -5,11 +5,8 @@ import (
"os" "os"
"time" "time"
lg "github.com/volker-raschek/flucky/cmd/logger"
"github.com/volker-raschek/flucky/cmd/remote"
"github.com/volker-raschek/flucky/cmd/sensor" "github.com/volker-raschek/flucky/cmd/sensor"
"github.com/volker-raschek/flucky/cmd/temperature" "github.com/volker-raschek/flucky/cmd/temperature"
"github.com/volker-raschek/flucky/pkg/logger"
"github.com/volker-raschek/flucky/pkg/types" "github.com/volker-raschek/flucky/pkg/types"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
@ -17,7 +14,7 @@ import (
"github.com/volker-raschek/flucky/pkg/config" "github.com/volker-raschek/flucky/pkg/config"
) )
var cfg string var configPath string
var rootCmd = &cobra.Command{ var rootCmd = &cobra.Command{
Use: "flucky", Use: "flucky",
@ -25,28 +22,21 @@ var rootCmd = &cobra.Command{
PersistentPreRunE: func(cmd *cobra.Command, args []string) error { PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// check if config file exists // check if config file exists
if _, err := os.Stat(cfg); os.IsNotExist(err) { if _, err := os.Stat(configPath); os.IsNotExist(err) {
hostname, err := os.Hostname() hostname, err := os.Hostname()
if err != nil { if err != nil {
return fmt.Errorf("Can not locate the hostname: %v", err) return fmt.Errorf("Can not locate the hostname: %v", err)
} }
logfiles := make(map[logger.LogValue][]string) cnf := config.Configuration{
logfiles[logger.LogHumidity] = []string{"/var/log/flucky/humidity.json"}
logfiles[logger.LogTemperature] = []string{"/var/log/flucky/temperature.json"}
fc := config.FluckyConfig{
Device: &types.Device{ Device: &types.Device{
DeviceID: uuid.NewV4().String(), DeviceID: uuid.NewV4().String(),
DeviceName: hostname, DeviceName: hostname,
CreationDate: time.Now(), CreationDate: time.Now(),
}, },
FileLogger: &logger.FileLogger{
LogFiles: logfiles,
},
} }
err = config.Write(&fc, cfg) err = config.Write(&cnf, configPath)
if err != nil { if err != nil {
return err return err
} }
@ -60,13 +50,9 @@ var rootCmd = &cobra.Command{
func Execute(version string) { func Execute(version string) {
rootCmd.Version = version rootCmd.Version = version
rootCmd.PersistentFlags().StringVar(&cfg, "config", "/etc/flucky/config.json", "Config file") rootCmd.PersistentFlags().StringVar(&configPath, "config", "/etc/flucky/config.json", "Config file")
lg.InitCmd(rootCmd, cfg)
// humidity.InitCmd(rootCmd, configDir) // humidity.InitCmd(rootCmd, configDir)
remote.InitCmd(rootCmd, cfg) sensor.InitCmd(rootCmd, configPath)
sensor.InitCmd(rootCmd, cfg) temperature.InitCmd(rootCmd, configPath)
temperature.InitCmd(rootCmd, cfg)
rootCmd.Execute() rootCmd.Execute()
} }

22
cmd/daemon/daemon.go Normal file
View File

@ -0,0 +1,22 @@
package daemon
import (
"github.com/spf13/cobra"
)
var configDir string
var daemonCmd = &cobra.Command{
Use: "daemon",
Short: "Read continuously data from all enabled sensors",
Run: func(cmd *cobra.Command, args []string) {
},
}
func InitCmd(cmd *cobra.Command, cnf string) {
configDir = cnf
cmd.AddCommand(daemonCmd)
}

View File

@ -1,54 +0,0 @@
package logger
import (
"log"
"github.com/volker-raschek/flucky/pkg/logger"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var enabled bool
var addLoggerCmd = &cobra.Command{
Use: "add",
Short: "Add internal logger",
Args: cobra.ExactArgs(2),
Aliases: []string{"append"},
Example: "flucky logger add temperature /var/log/flucky/temperature.log",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// loggertype, err := logger.StringToLoggerType(args[0])
// if err != nil {
// log.Fatalln(err)
// }
logvalue, err := logger.StringToLogValue(args[0])
if err != nil {
log.Fatalln(err)
}
err = fc.AddLogFile(args[1], logvalue)
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
loggerCmd.AddCommand(addLoggerCmd)
}

View File

@ -1,40 +0,0 @@
package logger
import (
"log"
"os"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/cli"
"github.com/volker-raschek/flucky/pkg/config"
)
var quiet bool
var listLoggerCmd = &cobra.Command{
Use: "ls",
Short: "List internal Loggers",
Aliases: []string{"list"},
Example: "flucky logger ls",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// print all configured remote addresses on stdout
cli.PrintLoggers(fc, os.Stdout)
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
loggerCmd.AddCommand(listLoggerCmd)
}

View File

@ -1,18 +0,0 @@
package logger
import (
"github.com/spf13/cobra"
)
var cfg string
var loggerCmd = &cobra.Command{
Use: "logger",
Short: "Manage internal logger",
}
func InitCmd(cmd *cobra.Command, config string) {
cfg = config
cmd.AddCommand(loggerCmd)
}

View File

@ -1,40 +0,0 @@
package logger
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var rmLoggerCmd = &cobra.Command{
Use: "rm",
Short: "Remove internal logger",
Args: cobra.ExactArgs(1),
Aliases: []string{"remove"},
Example: "flucky logger rm /var/log/flucky/temperature.log",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
err = fc.RemoveLogFile(args[0])
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
loggerCmd.AddCommand(rmLoggerCmd)
}

View File

@ -1,51 +0,0 @@
package remote
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var enabled bool
var addRemoteCmd = &cobra.Command{
Use: "add",
Short: "Add Remote Server",
Args: cobra.ExactArgs(2),
Aliases: []string{"append"},
Example: "flucky remote add origin https://example.local",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// create new remote struct
remote := config.Remote{
Name: args[0],
Address: args[1],
Enabled: enabled,
}
// // add remote entry to list
err = fc.AddRemote(&remote)
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(addRemoteCmd)
addRemoteCmd.Flags().BoolVarP(&enabled, "enable", "e", true, "Enable")
}

View File

@ -1,40 +0,0 @@
package remote
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var disableRemoteCmd = &cobra.Command{
Use: "disable",
Short: "Disable Remove Server",
Args: cobra.ExactArgs(1),
Example: "flucky remote disable origin",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// disnable remote address
err = fc.DisableRemote(args[0])
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(disableRemoteCmd)
}

View File

@ -1,39 +0,0 @@
package remote
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var enableRemoteCmd = &cobra.Command{
Use: "enable",
Short: "Enable Remove Server",
Args: cobra.ExactArgs(1),
Example: "flucky remote enable origin",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// enable remote address
err = fc.EnableRemote(args[0])
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(enableRemoteCmd)
}

View File

@ -1,43 +0,0 @@
package remote
import (
"log"
"os"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/cli"
"github.com/volker-raschek/flucky/pkg/config"
)
var quiet bool
var listRemoteCmd = &cobra.Command{
Use: "ls",
Short: "List Remove Servers",
Aliases: []string{"list"},
Example: "flucky remote ls",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// print all configured remote addresses on stdout
err = cli.PrintRemotes(fc, os.Stdout)
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(listRemoteCmd)
}

View File

@ -1,18 +0,0 @@
package remote
import (
"github.com/spf13/cobra"
)
var cfg string
var remoteCmd = &cobra.Command{
Use: "remote",
Short: "Manage Remote Server",
}
func InitCmd(cmd *cobra.Command, config string) {
cfg = config
cmd.AddCommand(remoteCmd)
}

View File

@ -1,40 +0,0 @@
package remote
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var rmRemoteCmd = &cobra.Command{
Use: "rm",
Short: "Remove Remote Server",
Aliases: []string{"remove"},
Args: cobra.ExactArgs(1),
Example: "flucky remote rm origin",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// add remote entry to list
err = fc.RemoveRemote(args[0])
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(rmRemoteCmd)
}

View File

@ -1,40 +0,0 @@
package remote
import (
"log"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/config"
)
var renameRemoteCmd = &cobra.Command{
Use: "rename",
Short: "Rename Remote Server",
Args: cobra.ExactArgs(2),
Example: "flucky remote rename origin slave",
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
// rename remote address
err = fc.RenameRemote(args[0], args[1])
if err != nil {
log.Fatalln(err)
}
// save new configuration
err = config.Write(fc, cfg)
if err != nil {
log.Fatalln(err)
}
},
}
func init() {
remoteCmd.AddCommand(renameRemoteCmd)
}

28
cmd/temperature/list.go Normal file
View File

@ -0,0 +1,28 @@
package temperature
import (
"fmt"
"github.com/spf13/cobra"
)
var listTemperatureCmd = &cobra.Command{
Use: "list",
Short: "print temperatures",
Example: fmt.Sprintf("flucky temperature logs"),
Run: func(cmd *cobra.Command, args []string) {
// read configuration
// fc, err := config.Read(cnfPath)
// if err != nil {
// list.Fatalln(err)
// }
//cli.PrintTemperatures(temperatures, fc, os.Stdout)
},
}
func init() {
temperatureCmd.AddCommand(listTemperatureCmd)
}

View File

@ -1,37 +0,0 @@
package temperature
import (
"fmt"
"log"
"os"
"github.com/spf13/cobra"
"github.com/volker-raschek/flucky/pkg/cli"
"github.com/volker-raschek/flucky/pkg/config"
)
var logTemperatureCmd = &cobra.Command{
Use: "log",
Short: "print temperature logs",
Example: fmt.Sprintf("flucky temperature logs"),
Run: func(cmd *cobra.Command, args []string) {
// read configuration
fc, err := config.Read(cfg)
if err != nil {
log.Fatalln(err)
}
temperatures, err := fc.FileLogger.GetTemperatures(nil, nil, args)
if err != nil {
log.Fatalln(err)
}
cli.PrintTemperatures(temperatures, fc, os.Stdout)
},
}
func init() {
temperatureCmd.AddCommand(logTemperatureCmd)
}

View File

@ -1,22 +0,0 @@
package temperature
// import (
// "log"
// "github.com/spf13/cobra"
// )
// var pushTemperatureCmd = &cobra.Command{
// Use: "push",
// Short: "push temperature from sensor to remote servers",
// Run: func(cmd *cobra.Command, args []string) {
// if err := temperature.Push(configDir); err != nil {
// log.Fatal(err)
// }
// },
// }
// func init() {
// temperatureCmd.AddCommand(pushTemperatureCmd)
// }

View File

@ -20,16 +20,13 @@ var readTemperatureCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
// read configuration // read configuration
fc, err := config.Read(cfg) cnf, err := config.Read(cnfPath)
if err != nil { if err != nil {
log.Fatalln(err) log.Fatalln(err)
} }
// fetch all temperature sensors // fetch all temperature sensors
temperatureSensors, err := fc.GetTemperatureSensors(args) temperatureSensors := cnf.GetTemperatureSensors()
if err != nil {
log.Fatalln(err)
}
// read temperature from sensors // read temperature from sensors
temperatures, err := sensor.ReadTemperatures(temperatureSensors) temperatures, err := sensor.ReadTemperatures(temperatureSensors)
@ -38,14 +35,7 @@ var readTemperatureCmd = &cobra.Command{
} }
// print temperatures on stdout // print temperatures on stdout
cli.PrintTemperatures(temperatures, fc, os.Stdout) cli.PrintTemperatures(temperatures, cnf, os.Stdout)
if logs {
err = fc.FileLogger.LogTemperatures(temperatures)
if err != nil {
log.Fatalln(err)
}
}
}, },
} }

View File

@ -6,7 +6,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
var cfg string var cnfPath string
var temperatureCmd = &cobra.Command{ var temperatureCmd = &cobra.Command{
Use: "temperature", Use: "temperature",
@ -15,8 +15,8 @@ var temperatureCmd = &cobra.Command{
} }
// Execute a // Execute a
func InitCmd(cmd *cobra.Command, config string) { func InitCmd(cmd *cobra.Command, configPath string) {
cfg = config cnfPath = configPath
cmd.AddCommand(temperatureCmd) cmd.AddCommand(temperatureCmd)

5
go.mod
View File

@ -9,7 +9,10 @@ require (
github.com/satori/go.uuid v1.2.0 github.com/satori/go.uuid v1.2.0
github.com/spf13/cobra v0.0.3 github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/pflag v1.0.3 // indirect
github.com/vishvananda/netlink v1.0.0
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc // indirect
github.com/volker-raschek/go-dht v0.1.0
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624 github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624
golang.org/x/sys v0.0.0-20190613124609-5ed2794edfdc // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
periph.io/x/periph v3.4.0+incompatible // indirect
) )

7
go.sum
View File

@ -13,8 +13,15 @@ github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM=
github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4=
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
github.com/volker-raschek/go-dht v0.1.0/go.mod h1:Fjv93K0m5sjdN/0ls8EeB4blawrEQVpda8HfSobPet4=
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624 h1:bePzgtpuLSl+F9aacwuaquuoOyKfMKuJORq2CvPPJK4= github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624 h1:bePzgtpuLSl+F9aacwuaquuoOyKfMKuJORq2CvPPJK4=
github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0= github.com/yryz/ds18b20 v0.0.0-20180211073435-3cf383a40624/go.mod h1:MqFju5qeLDFh+S9PqxYT7TEla8xeW7bgGr/69q3oki0=
golang.org/x/sys v0.0.0-20190613124609-5ed2794edfdc h1:x+/QxSNkVFAC+v4pL1f6mZr1z+qgi+FoR8ccXZPVC10=
golang.org/x/sys v0.0.0-20190613124609-5ed2794edfdc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
periph.io/x/periph v3.4.0+incompatible h1:5gzxE4ryPq52cdqSw0mErR6pyJK8cBF2qdUAcOWh0bo= periph.io/x/periph v3.4.0+incompatible h1:5gzxE4ryPq52cdqSw0mErR6pyJK8cBF2qdUAcOWh0bo=

View File

@ -5,16 +5,13 @@ import (
"io" "io"
"text/tabwriter" "text/tabwriter"
"github.com/volker-raschek/flucky/pkg/logger"
"github.com/volker-raschek/flucky/pkg/internal/temperature"
"github.com/volker-raschek/flucky/pkg/config" "github.com/volker-raschek/flucky/pkg/config"
"github.com/volker-raschek/flucky/pkg/internal/temperature"
"github.com/volker-raschek/flucky/pkg/types" "github.com/volker-raschek/flucky/pkg/types"
) )
// PrintHumidities displays a list of humidities // PrintHumidities displays a list of humidities
func PrintHumidities(humidities []*types.Humidity, cnf *config.FluckyConfig, w io.Writer) { func PrintHumidities(humidities []*types.Humidity, cnf *config.Configuration, w io.Writer) {
// determine all humidity sensors based on the humidiy values // determine all humidity sensors based on the humidiy values
sensors := []*types.Sensor{} sensors := []*types.Sensor{}
for _, humidity := range humidities { for _, humidity := range humidities {
@ -71,37 +68,8 @@ func PrintHumidities(humidities []*types.Humidity, cnf *config.FluckyConfig, w i
tw.Flush() tw.Flush()
} }
func PrintLoggers(cnf *config.FluckyConfig, w io.Writer) {
// declare tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
fmt.Fprintf(w, "type\tvalue\t\tlocation\n")
for _, logfile := range cnf.LogFiles[logger.LogTemperature] {
fmt.Fprintf(w, "file\t%v\t%v\n", logger.LogTemperature, logfile)
}
tw.Flush()
}
// PrintRemotes displays a list with all configured remote addresses
func PrintRemotes(cnf *config.FluckyConfig, w io.Writer) error {
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
fmt.Fprint(tw, "name\taddress\tenabled\tregistered\n")
for _, remote := range cnf.Remotes {
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\n", remote.Name, remote.Address, remote.Enabled, remote.Registered)
}
tw.Flush()
return nil
}
// PrintSensors displays a list with all configured sensors // PrintSensors displays a list with all configured sensors
func PrintSensors(cnf *config.FluckyConfig, w io.Writer) error { func PrintSensors(cnf *config.Configuration, w io.Writer) error {
// declar tabwriter // declar tabwriter
tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0) tw := tabwriter.NewWriter(w, 0, 0, 3, ' ', 0)
@ -118,7 +86,7 @@ func PrintSensors(cnf *config.FluckyConfig, w io.Writer) error {
} }
// PrintTemperatures displays a list of temperatures // PrintTemperatures displays a list of temperatures
func PrintTemperatures(temperatures []*types.Temperature, cnf *config.FluckyConfig, w io.Writer) { func PrintTemperatures(temperatures []*types.Temperature, cnf *config.Configuration, w io.Writer) {
sensors := temperature.GetSensorsByTemperatures(temperatures, cnf) sensors := temperature.GetSensorsByTemperatures(temperatures, cnf)

View File

@ -1,6 +1,7 @@
package config package config
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
@ -10,9 +11,9 @@ import (
var validUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$") var validUUID = regexp.MustCompile("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
// Read the configuration file // Read the configuration file
func Read(configFile string) (*FluckyConfig, error) { func Read(configFile string) (*Configuration, error) {
fc := &FluckyConfig{} fc := &Configuration{}
f, err := os.Open(configFile) f, err := os.Open(configFile)
if err != nil { if err != nil {
@ -20,9 +21,9 @@ func Read(configFile string) (*FluckyConfig, error) {
} }
defer f.Close() defer f.Close()
err = fc.JSONDecoder(f) jsonDecoder := json.NewDecoder(f)
if err != nil { if err := jsonDecoder.Decode(&fc); err != nil {
return nil, fmt.Errorf("Can not decode json file %v: %v", configFile, err) return nil, fmt.Errorf("Can not unmarshal JSON: %v", err)
} }
return fc, nil return fc, nil
@ -30,7 +31,7 @@ func Read(configFile string) (*FluckyConfig, error) {
} }
// Write the configuration into a file, specified by the configuration filepath // Write the configuration into a file, specified by the configuration filepath
func Write(cfg *FluckyConfig, configFile string) error { func Write(cfg *Configuration, configFile string) error {
if _, err := os.Stat(configFile); os.IsNotExist(err) { if _, err := os.Stat(configFile); os.IsNotExist(err) {
configDir := filepath.Dir(configFile) configDir := filepath.Dir(configFile)
@ -46,9 +47,11 @@ func Write(cfg *FluckyConfig, configFile string) error {
} }
defer f.Close() defer f.Close()
err = cfg.JSONWriter(f) encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
err = encoder.Encode(cfg)
if err != nil { if err != nil {
return err return fmt.Errorf("Error in encoding struct to json: %v", err)
} }
return nil return nil

191
pkg/config/flucky.go Normal file
View File

@ -0,0 +1,191 @@
package config
import (
"fmt"
"time"
"github.com/volker-raschek/flucky/pkg/sensor"
uuid "github.com/satori/go.uuid"
"github.com/volker-raschek/flucky/pkg/types"
)
// Configuration of flucky
type Configuration struct {
Device *types.Device `json:"device"`
Sensors []*types.Sensor `json:"sensors"`
}
// AddSensor add a new sensor
func (c *Configuration) AddSensor(sensor *types.Sensor) error {
// check if sensorID is a valid UUID string
if !validUUID.MatchString(sensor.SensorID) {
sensor.SensorID = uuid.NewV4().String()
}
// check if sensor name and sensor uuid already exists
for _, s := range c.Sensors {
if s.SensorName == sensor.SensorName {
return fmt.Errorf("Sensor %v already exists", s.SensorName)
}
if s.SensorID == sensor.SensorID {
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)
}
}
// check if sensor has a valid device id
if sensor.DeviceID != c.Device.DeviceID {
sensor.DeviceID = c.Device.DeviceID
}
// overwrite creation date
sensor.CreationDate = time.Now()
//TODO: check if wire sensor exists in /dev/bus/w1/devices
// check
c.Sensors = append(c.Sensors, sensor)
return nil
}
// DisableSensor disables a sensor by its name or its unique UUID
func (c *Configuration) DisableSensor(name string) error {
found := false
for _, sensor := range c.Sensors {
// disable sensor matched after name
if !validUUID.MatchString(name) &&
sensor.SensorName == name {
sensor.SensorEnabled = false
found = true
break
}
// remove machted uuid
if validUUID.MatchString(name) &&
sensor.SensorID == name {
sensor.SensorEnabled = false
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found sensor %v", name)
}
return nil
}
// EnableSensor enables a sensor by its name or its unique UUID
func (c *Configuration) EnableSensor(name string) error {
found := false
for _, sensor := range c.Sensors {
// disable sensor matched after name
if !validUUID.MatchString(name) &&
sensor.SensorName == name {
sensor.SensorEnabled = true
found = true
break
}
// remove machted uuid
if validUUID.MatchString(name) &&
sensor.SensorID == name {
sensor.SensorEnabled = true
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found sensor %v", name)
}
return nil
}
// GetHumiditySensors returns a list of humidity sensors
func (c *Configuration) GetHumiditySensors() []sensor.HumiditySensor{
humiditySensors, _ := c.splitSensors()
return humiditySensors
}
// GetTemperatureSensors returns a list of humidity sensors
func (c *Configuration) GetTemperatureSensors() []sensor.TemperatureSensor{
_, temperatureSensors := c.splitSensors()
return temperatureSensors
}
// RemoveSensor deletes a sensor by its name or its unique UUID
func (c *Configuration) RemoveSensor(name string) error {
for i, sensor := range c.Sensors {
// remove machted name
if !validUUID.MatchString(name) &&
sensor.SensorName == name {
c.Sensors = append(c.Sensors[:i], c.Sensors[i+1:]...)
return nil
}
// remove machted uuid
if validUUID.MatchString(name) &&
sensor.SensorID == name {
c.Sensors = append(c.Sensors[:i], c.Sensors[i+1:]...)
return nil
}
}
return fmt.Errorf("Can not find sensor %v", name)
}
// RenameSensor renames a sensor identified by the name or the UUID
func (c *Configuration) RenameSensor(oldName, newName string) error {
for _, sensor := range c.Sensors {
if sensor.SensorName == oldName ||
sensor.SensorID == oldName {
sensor.SensorName = newName
return nil
}
}
return fmt.Errorf("Could not find remote %v to replace into with %v", oldName, newName)
}
func (c *Configuration) splitSensors() ([]sensor.HumiditySensor, []sensor.TemperatureSensor) {
humiditySensors := make([]sensor.HumiditySensor, 0)
temperatureSensors := make([]sensor.TemperatureSensor, 0)
for _, s := range c.Sensors {
switch s.SensorModel {
case types.DHT11:
humiditySensors = append(humiditySensors, &sensor.DHT11{
Sensor: s,
})
temperatureSensors = append(temperatureSensors, &sensor.DHT11{
Sensor: s,
})
case types.DHT22:
humiditySensors = append(humiditySensors, &sensor.DHT22{
Sensor: s,
})
temperatureSensors = append(temperatureSensors, &sensor.DHT22{
Sensor: s,
})
case types.DS18B20:
temperatureSensors = append(temperatureSensors, &sensor.DS18B20{
Sensor: s,
})
}
}
return humiditySensors, temperatureSensors
}

View File

@ -1,384 +0,0 @@
package config
import (
"bytes"
"encoding/json"
"fmt"
"io"
"time"
"github.com/volker-raschek/flucky/pkg/logger"
"github.com/volker-raschek/flucky/pkg/sensor"
uuid "github.com/satori/go.uuid"
"github.com/volker-raschek/flucky/pkg/types"
)
// FluckyConfig dasd
type FluckyConfig struct {
Device *types.Device `json:"device"`
*logger.FileLogger
Remotes []*Remote `json:"remotes"`
Sensors []*types.Sensor `json:"sensors"`
}
// AddSensor add a new sensor
func (fc *FluckyConfig) AddSensor(sensor *types.Sensor) error {
// check if sensorID is a valid UUID string
if !validUUID.MatchString(sensor.SensorID) {
sensor.SensorID = uuid.NewV4().String()
}
// check if sensor name and sensor uuid already exists
for _, s := range fc.Sensors {
if s.SensorName == sensor.SensorName {
return fmt.Errorf("Sensor %v already exists", s.SensorName)
}
if s.SensorID == sensor.SensorID {
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)
}
}
// 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
}
// AddRemote add a new remote address
func (fc *FluckyConfig) AddRemote(remote *Remote) error {
// check if remoteID is a valid UUID string
if !validUUID.MatchString(remote.RemoteID) {
remote.RemoteID = uuid.NewV4().String()
}
// check if remote name or remiteid already exists
for _, r := range fc.Remotes {
if r.Name == remote.Name {
return fmt.Errorf("Remote %v -> %v already exists", r.Name, r.Address)
}
if r.RemoteID == remote.RemoteID {
return fmt.Errorf("Remote %v with UUID %v already exists", r.Name, r.RemoteID)
}
}
fc.Remotes = append(fc.Remotes, remote)
return nil
}
// DisableRemote disables a remote address by its name or its unique UUID
func (fc *FluckyConfig) DisableRemote(nameOrUUID string) error {
found := false
for _, remote := range fc.Remotes {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
remote.Name == nameOrUUID {
remote.Enabled = false
found = true
break
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
remote.RemoteID == nameOrUUID {
remote.Enabled = false
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found remote name %v", nameOrUUID)
}
return nil
}
// DisableSensor disables a sensor by its name or its unique UUID
func (fc *FluckyConfig) DisableSensor(nameOrUUID string) error {
found := false
for _, sensor := range fc.Sensors {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
sensor.SensorName == nameOrUUID {
sensor.SensorEnabled = false
found = true
break
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
sensor.SensorID == nameOrUUID {
sensor.SensorEnabled = false
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found sensor %v", nameOrUUID)
}
return nil
}
// EnableRemote enable a remote address by its name or its unique UUID
func (fc *FluckyConfig) EnableRemote(nameOrUUID string) error {
found := false
for _, remote := range fc.Remotes {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
remote.Name == nameOrUUID {
remote.Enabled = true
found = true
break
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
remote.RemoteID == nameOrUUID {
remote.Enabled = true
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found sensor %v", nameOrUUID)
}
return nil
}
// EnableSensor enables a sensor by its name or its unique UUID
func (fc *FluckyConfig) EnableSensor(nameOrUUID string) error {
found := false
for _, sensor := range fc.Sensors {
// disable sensor matched after name
if !validUUID.MatchString(nameOrUUID) &&
sensor.SensorName == nameOrUUID {
sensor.SensorEnabled = true
found = true
break
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
sensor.SensorID == nameOrUUID {
sensor.SensorEnabled = true
found = true
break
}
}
if !found {
return fmt.Errorf("Can not found sensor %v", nameOrUUID)
}
return nil
}
func (fc *FluckyConfig) GetHumiditySensors(namesOrUUIDs []string) []sensor.HumiditySensor {
hs := []sensor.HumiditySensor{}
for _, s := range fc.Sensors {
// select only named sensors
if len(namesOrUUIDs) > 0 {
found := false
for _, nameOrUUID := range namesOrUUIDs {
if nameOrUUID == s.SensorID || nameOrUUID == s.SensorName {
found = true
break
}
}
if !found {
continue
}
}
// skip disabled sensors
if !s.SensorEnabled {
continue
}
switch s.SensorModel {
case types.DHT11:
hs = append(hs, &sensor.DHT11Sensor{
Sensor: s,
})
case types.DHT22:
hs = append(hs, &sensor.DHT22Sensor{
Sensor: s,
})
}
}
return hs
}
func (fc *FluckyConfig) GetTemperatureSensors(namesOrUUIDs []string) ([]sensor.TemperatureSensor, error) {
ts := []sensor.TemperatureSensor{}
for _, s := range fc.Sensors {
// select only named sensors
if len(namesOrUUIDs) > 0 {
found := false
for _, nameOrUUID := range namesOrUUIDs {
if nameOrUUID == s.SensorID || nameOrUUID == s.SensorName {
found = true
break
}
}
if !found {
continue
}
}
// skip disabled sensors
if !s.SensorEnabled {
continue
}
switch s.SensorModel {
case types.DHT11:
ts = append(ts, &sensor.DHT11Sensor{
Sensor: s,
})
case types.DHT22:
ts = append(ts, &sensor.DHT22Sensor{
Sensor: s,
})
case types.DS18B20:
ts = append(ts, &sensor.DS18B20{
Sensor: s,
})
default:
return nil, fmt.Errorf("Sensor Model %v is not a valid sensor model. Please remove the sensor named %v", s.SensorModel, s.Name())
}
}
return ts, nil
}
// JSONDecoder decode a JSON string from a reader into a struct
func (fc *FluckyConfig) JSONDecoder(r io.Reader) error {
jsonDecoder := json.NewDecoder(r)
if err := jsonDecoder.Decode(&fc); err != nil {
return fmt.Errorf("Can not unmarshal JSON: %v", err)
}
return nil
}
// JSONWriter needs a writer to write the struct into JSON string
func (fc *FluckyConfig) JSONWriter(w io.Writer) error {
encoder := json.NewEncoder(w)
encoder.SetIndent("", " ")
err := encoder.Encode(&fc)
if err != nil {
return fmt.Errorf("Error in encoding struct to json: %v", err)
}
return nil
}
// RemoveSensor deletes a sensor by its name or its unique UUID
func (fc *FluckyConfig) RemoveSensor(nameOrUUID string) error {
for i, sensor := range fc.Sensors {
// remove machted name
if !validUUID.MatchString(nameOrUUID) &&
sensor.SensorName == nameOrUUID {
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
return nil
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
sensor.SensorID == nameOrUUID {
fc.Sensors = append(fc.Sensors[:i], fc.Sensors[i+1:]...)
return nil
}
}
return fmt.Errorf("Can not find sensor %v", nameOrUUID)
}
// RemoveRemote deletes a remote address by its name or its unique UUID
func (fc *FluckyConfig) RemoveRemote(nameOrUUID string) error {
found := false
for i, remote := range fc.Remotes {
// remove machted name
if !validUUID.MatchString(nameOrUUID) &&
remote.Name == nameOrUUID {
fc.Remotes = append(fc.Remotes[:i], fc.Remotes[i+1:]...)
found = true
}
// remove machted uuid
if validUUID.MatchString(nameOrUUID) &&
remote.RemoteID == nameOrUUID {
fc.Remotes = append(fc.Remotes[:i], fc.Remotes[i+1:]...)
found = true
}
}
if !found {
return fmt.Errorf("Can not find remote %v", nameOrUUID)
}
return nil
}
// RenameSensor renames a sensor identified by the name or the UUID
func (fc *FluckyConfig) RenameSensor(oldName, newName string) error {
for _, sensor := range fc.Sensors {
if sensor.SensorName == oldName ||
sensor.SensorID == oldName {
sensor.SensorName = newName
return nil
}
}
return fmt.Errorf("Could not find sensor %v to replace into ", oldName)
}
// RenameRemote renames a remote address identified by the name or the UUID
func (fc *FluckyConfig) RenameRemote(oldName, newName string) error {
for _, remote := range fc.Remotes {
if remote.Name == oldName ||
remote.RemoteID == oldName {
remote.Name = newName
return nil
}
}
return fmt.Errorf("Could not find remote name %v to replace into %v", oldName, newName)
}
// ToJSON returns the struct as JSON string
func (fc *FluckyConfig) ToJSON() (string, error) {
var b bytes.Buffer
err := fc.JSONWriter(&b)
if err != nil {
return "", err
}
return b.String(), nil
}

View File

@ -1,28 +0,0 @@
package config
import "github.com/volker-raschek/flucky/pkg/types"
// Remote ...
type Remote struct {
RemoteID string `json:"remote_id"`
Name string `json:"remote_name"`
Address string `json:"remote_address"`
Registered bool `json:"remote_registered"`
Enabled bool `json:"remote_enabled"`
}
func (r *Remote) AddSensor(s *types.Sensor) error {
return nil
}
func (r *Remote) RegisterDevice(d *types.Device) error {
return nil
}
func (r *Remote) RemoveSensor(s *types.Sensor) error {
return nil
}
func (r *Remote) UnregisterDevice(d *types.Device) error {
return nil
}

33
pkg/daemon/daemon.go Normal file
View File

@ -0,0 +1,33 @@
package daemon
import (
"fmt"
"os"
"os/signal"
"syscall"
"github.com/volker-raschek/flucky/pkg/config"
"github.com/volker-raschek/flucky/pkg/sensor"
"github.com/volker-raschek/flucky/pkg/types"
)
// Start the daemon
func Start(cnf *config.FluckyConfig) error {
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt, os.Kill, syscall.SIGTERM)
humidityChannel := make(chan *types.Humidity)
temperatureChannel := make(chan *types.Temperature)
go sensor.ReadHumiditiesContinuously(humiditySensors, humidityChannel)
go sensor.ReadTemperaturesContinuously(temperatureSensors, temperatureChannel)
for {
select {
case killSignal := <-interrupt:
return fmt.Errorf("Daemon was interruped by system signal %v", killSignal)
}
}
}

View File

@ -0,0 +1,16 @@
package collect
func Errors(errorChannel <-chan error) []error {
errorList := make([]error, 0)
for {
select {
case err, more := <-errorChannel:
if more {
errorList = append(errorList, err)
continue
}
default:
return errorList
}
}
}

View File

@ -0,0 +1,20 @@
package collect
import "github.com/volker-raschek/flucky/pkg/types"
func Humidities(humidityChannel <-chan *types.Humidity) []*types.Humidity {
humidityList := make([]*types.Humidity, 0)
for {
select {
case hum, more := <-humidityChannel:
if more {
humidityList = append(humidityList, hum)
continue
}
return nil
default:
return humidityList
}
}
}

View File

@ -0,0 +1,20 @@
package collect
import (
"github.com/volker-raschek/flucky/pkg/types"
)
func Temperatures(temperatureChannel <-chan *types.Temperature) []*types.Temperature {
temperatureList := make([]*types.Temperature, 0)
for {
select {
case temperature, more := <-temperatureChannel:
if more {
temperatureList = append(temperatureList, temperature)
continue
}
default:
return temperatureList
}
}
}

View File

@ -1,31 +0,0 @@
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

@ -0,0 +1,14 @@
package prittyprint
import "fmt"
func FormatErrors(errors []error) error {
if len(errors) > 0 {
errMsg := ""
for _, err := range errors {
errMsg = fmt.Sprintf("%v\n%v", errMsg, err.Error())
}
return fmt.Errorf(errMsg)
}
return nil
}

View File

@ -9,7 +9,7 @@ import (
) )
// GetSensorsByTemperatures returns commulated list of sensors by temperature values // GetSensorsByTemperatures returns commulated list of sensors by temperature values
func GetSensorsByTemperatures(temperatures []*types.Temperature, cnf *config.FluckyConfig) []*types.Sensor { func GetSensorsByTemperatures(temperatures []*types.Temperature, cnf *config.Configuration) []*types.Sensor {
sensors := []*types.Sensor{} sensors := []*types.Sensor{}
for _, temperature := range temperatures { for _, temperature := range temperatures {
duplicated := false duplicated := false
@ -66,7 +66,7 @@ func GetTemperaturesBetweenTimeRange(from time.Time, till *time.Time, temperatur
// GetTemperaturesBySensors returns a list of temperatures given by the sensor id. // GetTemperaturesBySensors returns a list of temperatures given by the sensor id.
// If the sensor name, wire-id or id can not found in configured sensors, it would be skiped! // If the sensor name, wire-id or id can not found in configured sensors, it would be skiped!
func GetTemperaturesBySensors(sensorNamesOrIDs []string, temperatures []*types.Temperature, cnf *config.FluckyConfig) []*types.Temperature { func GetTemperaturesBySensors(sensorNamesOrIDs []string, temperatures []*types.Temperature, cnf *config.Configuration) []*types.Temperature {
cachedSensors := []*types.Sensor{} cachedSensors := []*types.Sensor{}
cachedTemperatures := []*types.Temperature{} cachedTemperatures := []*types.Temperature{}

View File

@ -1,222 +0,0 @@
package logger
import (
"encoding/json"
"fmt"
"io"
"os"
"time"
"github.com/volker-raschek/flucky/pkg/types"
)
type FileLogger struct {
LogFiles map[LogValue][]string `json:"logfiles"`
writer io.Writer
}
func (fl *FileLogger) AddLogFile(logfile string, logValue LogValue) error {
for _, logfiles := range fl.LogFiles {
for _, lf := range logfiles {
if lf == logfile {
return fmt.Errorf("Logfile %v already configured", logfile)
}
}
}
fl.LogFiles[logValue] = append(fl.LogFiles[logValue], logfile)
return nil
}
func (fl *FileLogger) GetHumidities(fromDate *time.Time, tillDate *time.Time, sensorNameOrUUID *[]string) ([]*types.Humidity, error) {
return nil, nil
}
func (fl *FileLogger) GetTemperatures(from *time.Time, till *time.Time, sensorIDs []string) ([]*types.Temperature, error) {
cachedTemperatures := []*types.Temperature{}
// iterate over all configured temperature logfiles
for _, logfile := range fl.LogFiles[LogTemperature] {
// skip logfile if not exists
if _, err := os.Stat(logfile); os.IsNotExist(err) {
return nil, fmt.Errorf("Logfile %v not exists", logfile)
}
loggedTemperatures := []*types.Temperature{}
f, err := os.Open(logfile)
if err != nil {
return nil, fmt.Errorf("Can not open %v: %v", logfile, err)
}
defer f.Close()
decoder := json.NewDecoder(f)
err = decoder.Decode(&loggedTemperatures)
if err != nil {
return nil, fmt.Errorf("Can not decode temperatures from logfile %v: %v", logfile, err)
}
cachedTemperatures = append(cachedTemperatures, loggedTemperatures...)
// // sort all redundant values out
// for _, loggedTemperature := range loggedTemperatures {
// found := false
// for _, cachedTemperature := range cachedTemperatures {
// if cachedTemperature.TemperatureID == loggedTemperature.TemperatureID {
// found = true
// break
// }
// }
// if !found {
// cachedTemperatures = append(cachedTemperatures, loggedTemperature)
// }
// }
}
// // sort out all temperatures which are not mesured by sensor id
// for i, cachedTemperature := range cachedTemperatures {
// found := false
// for _, sensorID := range sensorIDs {
// if cachedTemperature.SensorID == sensorID {
// found = true
// break
// }
// }
// if !found {
// cachedTemperatures = append(cachedTemperatures[:i], cachedTemperatures[i+1:]...)
// }
// }
// // sort out all temperatures which are before from date
// if from != nil {
// for i, cachedTemperature := range cachedTemperatures {
// if cachedTemperature.TemperatureDate.Before(*from) {
// cachedTemperatures = append(cachedTemperatures[:i], cachedTemperatures[i+1:]...)
// }
// }
// }
// // sort out all temperatures which are after till date
// if till != nil {
// for i, cachedTemperature := range cachedTemperatures {
// if cachedTemperature.TemperatureDate.After(*till) {
// cachedTemperatures = append(cachedTemperatures[:i], cachedTemperatures[i+1:]...)
// }
// }
// }
return cachedTemperatures, nil
}
// LogHumidities write humidities to all configured humidity logfiles
func (fl *FileLogger) LogHumidities(humidities []*types.Humidity) error {
for _, logfile := range fl.LogFiles[LogHumidity] {
logHumidities := []*types.Humidity{}
// if logfile already exists, read humidities from logfile
if _, err := os.Stat(logfile); err == nil {
f, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Can not open file %v: %v", logfile, err)
}
decoder := json.NewDecoder(f)
err = decoder.Decode(&logHumidities)
if err != nil {
return fmt.Errorf("Can not decode humidities from reader")
}
f.Close()
}
// append new humidities with existing humidities from logfile
logHumidities = append(logHumidities, humidities...)
// overwrite lofgile with new entries
f, err := os.Create(logfile)
if err != nil {
return fmt.Errorf("Can not open file %v: %v", logfile, err)
}
defer f.Close()
// encode humidities
encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
err = encoder.Encode(logHumidities)
if err != nil {
return fmt.Errorf("Can not encode humidities for the writer")
}
}
return nil
}
// LogTemperatures write temperatures to all configured temperature logfiles
func (fl *FileLogger) LogTemperatures(temperatures []*types.Temperature) error {
for _, logfile := range fl.LogFiles[LogTemperature] {
logTemperatures := []*types.Temperature{}
// if logfile already exists, read temperatures from logfile
if _, err := os.Stat(logfile); err == nil {
f, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Can not open file %v: %v", logfile, err)
}
decoder := json.NewDecoder(f)
err = decoder.Decode(&logTemperatures)
if err != nil {
return fmt.Errorf("Can not decode temperatures from reader")
}
f.Close()
}
// append new temperatures with existing temperatures from logfile
logTemperatures = append(logTemperatures, temperatures...)
// overwrite lofgile with new entries
f, err := os.Create(logfile)
if err != nil {
return fmt.Errorf("Can not open file %v: %v", logfile, err)
}
defer f.Close()
// encode temperatures
encoder := json.NewEncoder(f)
encoder.SetIndent("", " ")
err = encoder.Encode(logTemperatures)
if err != nil {
return fmt.Errorf("Can not encode temperatures for the writer")
}
}
return nil
}
func (fl *FileLogger) RemoveLogFile(logfile string) error {
for i, logfiles := range fl.LogFiles {
cachedLogfiles := []string{}
for _, lf := range logfiles {
if lf == logfile {
continue
}
cachedLogfiles = append(cachedLogfiles, lf)
}
fl.LogFiles[i] = cachedLogfiles
}
if _, err := os.Stat(logfile); err == nil {
err := os.Remove(logfile)
if err != nil {
return fmt.Errorf("Can not remote file %v: %v", logfile, err)
}
}
return nil
}
func NewFileLogger(w io.Writer) *FileLogger {
return &FileLogger{
writer: w,
}
}

View File

@ -1,73 +0,0 @@
package logger
import (
"fmt"
"time"
"github.com/volker-raschek/flucky/pkg/types"
)
type Logger interface {
GetHumidities(fromDate *time.Time, tillDate *time.Time, sensorNameOrUUID *[]string) ([]*types.Humidity, error)
GetTemperatures(from *time.Time, till *time.Time, sensorIDs []string) ([]*types.Temperature, error)
LogHumidities(humidities []*types.Humidity) error
LogTemperatures(temperatures []*types.Temperature) error
}
type LoggerType string
const (
LogFile LoggerType = "file"
LogRemote = "remote"
)
type LogValue string
const (
LogHumidity LogValue = "humidity"
LogTemperature = "temperature"
)
// LogTypeToString converts a logtype into a string
func LogTypeToString(loggertype LoggerType) (string, error) {
switch loggertype {
case LogFile:
return "file", nil
default:
return "", fmt.Errorf("Can not determine loggertype %v", loggertype)
}
}
// LogValueToString converts a logvalue into a string
func LogValueToString(logvalue LogValue) (string, error) {
switch logvalue {
case LogHumidity:
return "humidity", nil
case LogTemperature:
return "temperature", nil
default:
return "", fmt.Errorf("Can not determine logvalue %v", logvalue)
}
}
// StringToLoggerType converts a string into loggertype
func StringToLoggerType(loggertype string) (LoggerType, error) {
switch loggertype {
case "file":
return LogFile, nil
default:
return "", fmt.Errorf("Can not determine loggertype %v", loggertype)
}
}
// StringToLogValue converts a string into logvalue
func StringToLogValue(logvalue string) (LogValue, error) {
switch logvalue {
case "humidity":
return LogHumidity, nil
case "temperature":
return LogTemperature, nil
default:
return "", fmt.Errorf("Can not determine logvalue %v", logvalue)
}
}

View File

@ -9,11 +9,18 @@ import (
"github.com/volker-raschek/flucky/pkg/types" "github.com/volker-raschek/flucky/pkg/types"
) )
type DHT11Sensor struct { // DHT11 is a sensor to measure humidity and temperature.
type DHT11 struct {
*types.Sensor *types.Sensor
} }
func (s *DHT11Sensor) ReadHumidity() (*types.Humidity, error) { // GetSensorModel returns the sensor model
func (s *DHT11) GetSensorModel() types.SensorModel {
return s.Sensor.SensorModel
}
// ReadHumidity measure the humidity
func (s *DHT11) ReadHumidity() (*types.Humidity, error) {
err := dht.HostInit() err := dht.HostInit()
if err != nil { if err != nil {
return nil, fmt.Errorf("HostInit error: %v", err) return nil, fmt.Errorf("HostInit error: %v", err)
@ -44,7 +51,8 @@ func (s *DHT11Sensor) ReadHumidity() (*types.Humidity, error) {
return humidity, nil return humidity, nil
} }
func (s *DHT11Sensor) ReadTemperature() (*types.Temperature, error) { // ReadTemperature measure the temperature
func (s *DHT11) ReadTemperature() (*types.Temperature, error) {
err := dht.HostInit() err := dht.HostInit()
if err != nil { if err != nil {
return nil, fmt.Errorf("HostInit error: %v", err) return nil, fmt.Errorf("HostInit error: %v", err)

View File

@ -9,11 +9,18 @@ import (
"github.com/volker-raschek/flucky/pkg/types" "github.com/volker-raschek/flucky/pkg/types"
) )
type DHT22Sensor struct { // DHT22 is a sensor to measure humidity and temperature.
type DHT22 struct {
*types.Sensor *types.Sensor
} }
func (s *DHT22Sensor) ReadHumidity() (*types.Humidity, error) { // GetSensorModel returns the sensor model
func (s *DHT22) GetSensorModel() types.SensorModel {
return s.Sensor.SensorModel
}
// ReadHumidity measure the humidity
func (s *DHT22) ReadHumidity() (*types.Humidity, error) {
err := dht.HostInit() err := dht.HostInit()
if err != nil { if err != nil {
return nil, fmt.Errorf("HostInit error: %v", err) return nil, fmt.Errorf("HostInit error: %v", err)
@ -44,7 +51,8 @@ func (s *DHT22Sensor) ReadHumidity() (*types.Humidity, error) {
return humidity, nil return humidity, nil
} }
func (s *DHT22Sensor) ReadTemperature() (*types.Temperature, error) { // ReadTemperature measure the temperature
func (s *DHT22) ReadTemperature() (*types.Temperature, error) {
err := dht.HostInit() err := dht.HostInit()
if err != nil { if err != nil {
return nil, fmt.Errorf("HostInit error: %v", err) return nil, fmt.Errorf("HostInit error: %v", err)

View File

@ -9,10 +9,22 @@ import (
"github.com/yryz/ds18b20" "github.com/yryz/ds18b20"
) )
// DS18B20 is a sensor to measure humidity and temperature.
type DS18B20 struct { type DS18B20 struct {
*types.Sensor *types.Sensor
} }
// GetSensorModel returns the sensor model
func (s *DS18B20) GetSensorModel() types.SensorModel {
return s.Sensor.SensorModel
}
// GetSensor return the sensor struct
func (s *DS18B20) GetSensor() *types.Sensor {
return s.Sensor
}
// ReadTemperature measure the temperature
func (s *DS18B20) ReadTemperature() (*types.Temperature, error) { func (s *DS18B20) ReadTemperature() (*types.Temperature, error) {
t, err := ds18b20.Temperature(*s.WireID) t, err := ds18b20.Temperature(*s.WireID)

15
pkg/sensor/interfaces.go Normal file
View File

@ -0,0 +1,15 @@
package sensor
import "github.com/volker-raschek/flucky/pkg/types"
// HumiditySensor is a interface to describe required functions to measure humidities
type HumiditySensor interface {
GetSensorModel() types.SensorModel
ReadHumidity() (*types.Humidity, error)
}
// TemperatureSensor is a interface to describe required functions to measure temperatures
type TemperatureSensor interface {
GetSensorModel() types.SensorModel
ReadTemperature() (*types.Temperature, error)
}

View File

@ -3,106 +3,87 @@ package sensor
import ( import (
"sync" "sync"
"github.com/volker-raschek/flucky/pkg/internal/errutils" "github.com/volker-raschek/flucky/pkg/internal/collect"
"github.com/volker-raschek/flucky/pkg/internal/prittyprint"
"github.com/volker-raschek/flucky/pkg/types" "github.com/volker-raschek/flucky/pkg/types"
) )
type HumiditySensor interface { // ReadHumidities returns a list of measured humidities by humidity sensors
ReadHumidity() (*types.Humidity, error)
}
type TemperatureSensor interface {
ReadTemperature() (*types.Temperature, error)
}
func ReadHumidities(humiditySensors []HumiditySensor) ([]*types.Humidity, error) { func ReadHumidities(humiditySensors []HumiditySensor) ([]*types.Humidity, error) {
errorChannel := make(chan error, len(humiditySensors))
humidityChannel := make(chan *types.Humidity, len(humiditySensors))
ReadHumiditiesIntoChannel(humiditySensors, humidityChannel, errorChannel)
errorList := collect.Errors(errorChannel)
if len(errorList) != 0 {
return nil, prittyprint.FormatErrors(errorList)
}
humidityList := collect.Humidities(humidityChannel)
return humidityList, nil
}
// ReadHumiditiesIntoChannel reads the humidity values of humidity sensors and writes them into a channel
func ReadHumiditiesIntoChannel(humiditySensors []HumiditySensor, humidityChannel chan<- *types.Humidity, errorChannel chan<- error) {
wg := new(sync.WaitGroup) wg := new(sync.WaitGroup)
wg.Add(len(humiditySensors)) wg.Add(len(humiditySensors))
errChannel := make(chan error, len(humiditySensors))
humidityChannel := make(chan *types.Humidity, len(humiditySensors))
for _, humiditySensor := range humiditySensors { for _, humiditySensor := range humiditySensors {
go func(hs HumiditySensor) { go func(hs HumiditySensor) {
defer wg.Done() defer wg.Done()
humidity, err := hs.ReadHumidity() humidity, err := hs.ReadHumidity()
if err != nil { if err != nil {
errChannel <- err errorChannel <- err
humidityChannel <- nil return
} }
errChannel <- nil
humidityChannel <- humidity humidityChannel <- humidity
}(humiditySensor) }(humiditySensor)
} }
wg.Wait() wg.Wait()
errorList := errutils.CollectErrors(errChannel)
if err := errutils.FormatErrors(errorList); err != nil {
return nil, err
}
humidityList := collectHumidities(humidityChannel)
return humidityList, nil
} }
// ReadHumiditiesContinuously reads the humidity values of humidity sensors continuously and writes them into a channel
func ReadHumiditiesContinuously(humiditySensors []HumiditySensor, humidityChannel chan<- *types.Humidity, errorChannel chan<- error) {
for {
ReadHumiditiesIntoChannel(humiditySensors, humidityChannel, errorChannel)
}
}
// ReadTemperatures returns a list of measured temperatures by temperature sensors
func ReadTemperatures(temperatureSensors []TemperatureSensor) ([]*types.Temperature, error) { func ReadTemperatures(temperatureSensors []TemperatureSensor) ([]*types.Temperature, error) {
errorChannel := make(chan error, len(temperatureSensors))
temperatureChannel := make(chan *types.Temperature, len(temperatureSensors))
ReadTemperaturesIntoChannel(temperatureSensors, temperatureChannel, errorChannel)
errorList := collect.Errors(errorChannel)
if len(errorList) != 0 {
return nil, prittyprint.FormatErrors(errorList)
}
temperatureList := collect.Temperatures(temperatureChannel)
return temperatureList, nil
}
// ReadTemperaturesIntoChannel reads the temperature values of temperature sensors and writes them into a channel
func ReadTemperaturesIntoChannel(temperatureSensors []TemperatureSensor, temperatureChannel chan<- *types.Temperature, errorChannel chan<- error) {
wg := new(sync.WaitGroup) wg := new(sync.WaitGroup)
wg.Add(len(temperatureSensors)) wg.Add(len(temperatureSensors))
errChannel := make(chan error, len(temperatureSensors))
temperatureChannel := make(chan *types.Temperature, len(temperatureSensors))
for _, temperatureSensor := range temperatureSensors { for _, temperatureSensor := range temperatureSensors {
go func(ts TemperatureSensor) { go func(ts TemperatureSensor) {
defer wg.Done() defer wg.Done()
temperature, err := ts.ReadTemperature() temperature, err := ts.ReadTemperature()
if err != nil { if err != nil {
errChannel <- err errorChannel <- err
return
} }
temperatureChannel <- temperature temperatureChannel <- temperature
}(temperatureSensor) }(temperatureSensor)
} }
wg.Wait() 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 { // ReadTemperaturesContinuously reads the temperature values of temperature sensors continuously and writes them into a chann
humidityList := make([]*types.Humidity, 0) func ReadTemperaturesContinuously(temperatureSensors []TemperatureSensor, temperatureChannel chan<- *types.Temperature, errorChannel chan<- error) {
for { for {
select { ReadTemperaturesIntoChannel(temperatureSensors, temperatureChannel, errorChannel)
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
}
} }
} }