diff --git a/cmd/daemon/daemon.go b/cmd/daemon/daemon.go index 803887b..10c01ce 100644 --- a/cmd/daemon/daemon.go +++ b/cmd/daemon/daemon.go @@ -2,12 +2,11 @@ package daemon import ( "fmt" - "log" + "github.com/go-flucky/flucky/cmd/internal" "github.com/go-flucky/flucky/pkg/config" "github.com/go-flucky/flucky/pkg/daemon" "github.com/spf13/cobra" - "github.com/volker-raschek/go-logger/pkg/logger" ) var ( @@ -40,14 +39,13 @@ func run(cmd *cobra.Command, args []string) error { return fmt.Errorf("No config file defined: %v", err) } - // WARNING: Must set logger for daemon package - // logLevel, err := cmd.Flags().GetString("loglevel") - // if err != nil { - // return fmt.Errorf("No loglevel defined: %v", err) - // } + logLevel, err := cmd.Flags().GetString("loglevel") + if err != nil { + return fmt.Errorf("No loglevel defined: %v", err) + } - //flogger := initializeLogger(logLevel) - // daemon.SetLogLevel(flogger) + flogger := internal.InitializeLogger(logLevel) + daemon.SetLogger(flogger) cnf, err := config.Read(configFile) if err != nil { @@ -56,21 +54,3 @@ func run(cmd *cobra.Command, args []string) error { return daemon.Start(cnf, cachedMeasuredValues, compression, round) } - -func initializeLogger(logLevel string) logger.Logger { - log.Println(logLevel) - switch logLevel { - case "debug", "DEBUG": - return logger.NewDefaultLogger(logger.LogLevelDebug) - case "info", "INFO": - return logger.NewDefaultLogger(logger.LogLevelInfo) - case "warn", "WARN": - return logger.NewDefaultLogger(logger.LogLevelWarn) - case "error", "ERROR": - return logger.NewDefaultLogger(logger.LogLevelError) - case "fatal", "FATAL": - return logger.NewDefaultLogger(logger.LogLevelFatal) - default: - return nil - } -} diff --git a/cmd/db/db.go b/cmd/db/db.go new file mode 100644 index 0000000..cec9937 --- /dev/null +++ b/cmd/db/db.go @@ -0,0 +1,106 @@ +package db + +import ( + "context" + "fmt" + "net/url" + + "github.com/Masterminds/semver" + "github.com/go-flucky/flucky/cmd/internal" + "github.com/go-flucky/flucky/pkg/config" + "github.com/go-flucky/flucky/pkg/storage/db" + "github.com/go-flucky/flucky/pkg/types" + "github.com/spf13/cobra" +) + +var ( + semanticVersion *semver.Version +) + +// InitCmd initialize all convert subcommands +func InitCmd(cmd *cobra.Command, semver *semver.Version) error { + + semanticVersion = semver + + databaseCmd := &cobra.Command{ + Use: "db", + Short: "Interagte with the database configured as storage endpoint", + } + + updateDatabaseCmd := &cobra.Command{ + Use: "init", + Short: "Initialize the database scheme for the version of the flucky binary", + Args: cobra.NoArgs, + Example: "flucky db update", + RunE: initializeDatabase, + } + + databaseCmd.AddCommand(updateDatabaseCmd) + cmd.AddCommand(databaseCmd) + + return nil +} + +func initializeDatabase(cmd *cobra.Command, args []string) error { + + configFile, err := cmd.Flags().GetString("config") + if err != nil { + return fmt.Errorf("No config file defined") + } + + cnf, err := config.Read(configFile) + if err != nil { + return err + } + + storageEndpointURL, err := url.Parse(cnf.StorageEndpoint) + if err != nil { + return fmt.Errorf("Failed to parse storage endpoint: %v", err) + } + + logLevel, err := cmd.Flags().GetString("loglevel") + if err != nil { + return fmt.Errorf("No loglevel defined: %v", err) + } + + flogger := internal.InitializeLogger(logLevel) + + database, err := db.New(storageEndpointURL) + if err != nil { + return err + } + defer database.Close() + + ctx := context.Background() + flogger.Debug("Initialize database scheme") + err = database.Schema(ctx, semanticVersion) + if err != nil { + return err + } + + _, err = database.SelectDeviceByID(ctx, cnf.Device.ID) + if err != nil { + flogger.Debug("Add device into database") + devices := []*types.Device{cnf.Device} + if err := database.InsertDevices(ctx, devices); err != nil { + return err + } + } else { + flogger.Debug("Device already availabe in the database") + } + + for _, sensor := range cnf.Sensors { + _, err = database.SelectSensorByID(ctx, sensor.ID) + if err != nil { + flogger.Debug("Add sensor %v into the database", sensor.FullName()) + sensors := []*types.Sensor{sensor} + if err := database.InsertSensors(ctx, sensors); err != nil { + return err + } + } else { + flogger.Debug("Sensor %v already available in the database", sensor.FullName()) + } + } + + return nil +} diff --git a/cmd/internal/internal.go b/cmd/internal/internal.go new file mode 100644 index 0000000..84da841 --- /dev/null +++ b/cmd/internal/internal.go @@ -0,0 +1,20 @@ +package internal + +import "github.com/volker-raschek/go-logger/pkg/logger" + +func InitializeLogger(logLevel string) logger.Logger { + switch logLevel { + case "debug", "DEBUG": + return logger.NewDefaultLogger(logger.LogLevelDebug) + case "info", "INFO": + return logger.NewDefaultLogger(logger.LogLevelInfo) + case "warn", "WARN": + return logger.NewDefaultLogger(logger.LogLevelWarn) + case "error", "ERROR": + return logger.NewDefaultLogger(logger.LogLevelError) + case "fatal", "FATAL": + return logger.NewDefaultLogger(logger.LogLevelFatal) + default: + return nil + } +} diff --git a/cmd/root.go b/cmd/root.go index 07559e7..14d2d20 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -12,6 +12,7 @@ import ( "github.com/go-flucky/flucky/cmd/compression" "github.com/go-flucky/flucky/cmd/convert" "github.com/go-flucky/flucky/cmd/daemon" + "github.com/go-flucky/flucky/cmd/db" "github.com/go-flucky/flucky/cmd/humidity" "github.com/go-flucky/flucky/cmd/pressure" "github.com/go-flucky/flucky/cmd/rgbled" @@ -61,7 +62,12 @@ func Execute(version *semver.Version) error { } } - err := rootCmd.Execute() + err := db.InitCmd(rootCmd, version) + if err != nil { + return err + } + + err = rootCmd.Execute() if err != nil { return err } diff --git a/cmd/sensor/sensor.go b/cmd/sensor/sensor.go index ab6ebe5..7b30bb9 100644 --- a/cmd/sensor/sensor.go +++ b/cmd/sensor/sensor.go @@ -74,7 +74,7 @@ flucky sensor add --i2c-bus 1 --i2c-address 0x76 wetter-station BME280`, Aliases: []string{"rm"}, Example: "flucky sensor remove outdoor", Args: cobra.ExactArgs(1), - RunE: enableSensor, + RunE: removeSensor, } renameSensorCmd := &cobra.Command{ diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index 3386a9a..a5d3d9a 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -86,7 +86,7 @@ func PrintSensors(cnf *config.Configuration, w io.Writer) error { } if sensor.I2CAddress != nil { - fmt.Fprintf(tw, "%v\t", string(*sensor.I2CAddress)) + fmt.Fprintf(tw, "%#v\t", *sensor.I2CAddress) } else { fmt.Fprintf(tw, "\t") } diff --git a/pkg/daemon/cache.go b/pkg/daemon/cache.go index eba6749..429e74d 100644 --- a/pkg/daemon/cache.go +++ b/pkg/daemon/cache.go @@ -1,7 +1,7 @@ package daemon import ( - "fmt" + "context" "net/url" "sync" @@ -56,7 +56,7 @@ func (cs *cacheStore) WriteToEndpoint() error { case "file": return cs.logfile() case "postgres": - return fmt.Errorf("Not yet implemented to store values into a postgres database") + return cs.postgres() } return nil } @@ -91,3 +91,8 @@ func (cs *cacheStore) logfile() error { return nil } + +func (cs *cacheStore) postgres() error { + ctx := context.Background() + return storage.Write(ctx, cs.cache, cs.URL) +} diff --git a/pkg/daemon/daemon.go b/pkg/daemon/daemon.go index 3676564..80f824f 100644 --- a/pkg/daemon/daemon.go +++ b/pkg/daemon/daemon.go @@ -15,9 +15,13 @@ import ( ) var ( - flogger = logger.NewDefaultLogger(logger.LogLevelDebug) + flogger = logger.NewSilentLogger() ) +func SetLogger(logger logger.Logger) { + flogger = logger +} + // Start the daemon func Start(cnf *config.Configuration, cacheSize uint, compression bool, round float64) error { @@ -129,7 +133,10 @@ func Start(cnf *config.Configuration, cacheSize uint, compression bool, round fl flogger.Fatal("Received a fatal error: %v", fatal) case <-interruptChannel: flogger.Debug("Write %v cached values into storage endpoint", cache.Size()) - cache.WriteToEndpoint() + err := cache.WriteToEndpoint() + if err != nil { + flogger.Error("%v", err) + } flogger.Debug("Close context") cancel() flogger.Debug("Close channels")