diff --git a/cmd/root.go b/cmd/root.go index 92f329a50..4fcbd55db 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -33,11 +33,13 @@ import ( const ( rebootDelay = 15 * time.Minute // delayed reboot on error serviceDB = "/var/lib/evcc/evcc.db" + userDB = "~/.evcc/evcc.db" ) var ( - log = util.NewLogger("main") - cfgFile string + log = util.NewLogger("main") + cfgFile string + cfgDatabase string ignoreEmpty = "" // ignore empty keys ignoreLogs = []string{"log"} // ignore log messages, including warn/error @@ -63,6 +65,7 @@ func init() { // global options rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file (default \"~/evcc.yaml\" or \"/etc/evcc.yaml\")") + rootCmd.PersistentFlags().StringVarP(&cfgDatabase, "database", "d", "", "Database location (default \"~/.evcc/evcc.db\")") rootCmd.PersistentFlags().BoolP("help", "h", false, "Help") rootCmd.PersistentFlags().Bool(flagHeaders, false, flagHeadersDescription) rootCmd.PersistentFlags().Bool(flagIgnoreDatabase, false, flagIgnoreDatabaseDescription) @@ -97,6 +100,9 @@ func initConfig() { viper.SetConfigName("evcc") } + if cfgDatabase != "" { + viper.Set("Database.Dsn", cfgDatabase) + } viper.SetEnvPrefix("evcc") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) diff --git a/cmd/setup.go b/cmd/setup.go index 356ea6134..9733e0e8b 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -68,7 +68,7 @@ var conf = globalconfig.All{ }, Database: globalconfig.DB{ Type: "sqlite", - Dsn: "~/.evcc/evcc.db", + Dsn: "", }, } @@ -81,22 +81,6 @@ func nameValid(name string) error { return nil } -func tokenDanger(conf []config.Named) bool { - problematic := []string{"tesla", "psa", "opel", "citroen", "ds", "peugeot"} - - for _, cc := range conf { - if slices.Contains(problematic, cc.Type) { - return true - } - template, ok := cc.Other["template"].(string) - if ok && cc.Type == "template" && slices.Contains(problematic, template) { - return true - } - } - - return false -} - func loadConfigFile(conf *globalconfig.All, checkDB bool) error { err := viper.ReadInConfig() @@ -112,17 +96,33 @@ func loadConfigFile(conf *globalconfig.All, checkDB bool) error { } } - // check service database - if _, err := os.Stat(serviceDB); err == nil && checkDB && conf.Database.Dsn != serviceDB && tokenDanger(conf.Vehicles) { - log.FATAL.Fatal(` + // user did not specify a database path + if conf.Database.Dsn == "" { + // check if service database exists + if _, err := os.Stat(serviceDB); err == nil && checkDB { + // service database found, ask user what to do + sudo := "" + if !isWritable(serviceDB) { + sudo = "sudo " + } + log.FATAL.Fatal(` +Found systemd service database at "` + serviceDB + `", evcc has been invoked with no explicit database path. +Running the same config with multiple databases can lead to expiring vehicle tokens. -Found systemd service database at "` + serviceDB + `", evcc has been invoked with database "` + conf.Database.Dsn + `". -Running evcc with vehicles configured in evcc.yaml may lead to expiring the yaml configuration's vehicle tokens. -This is due to the fact, that the token refresh will be saved to the local instead of the service's database. -If you have vehicles with touchy tokens like PSA or Tesla, make sure to remove vehicle configuration from the yaml file. +If you want to use the existing service database run the following command: -If you know what you're doing, you can run evcc ignoring the service database with the --ignore-db flag. -`) +` + sudo + `evcc --database ` + serviceDB + ` + +If you want to create a new user-space database run the following command: + +evcc --database ~/.evcc/evcc.db + +If you know what you're doing, you can skip the database check with the --ignore-db flag. + `) + } + + // default to user database + conf.Database.Dsn = userDB } // parse log levels after reading config @@ -133,6 +133,15 @@ If you know what you're doing, you can run evcc ignoring the service database wi return err } +func isWritable(filePath string) bool { + file, err := os.OpenFile(filePath, os.O_WRONLY, 0666) + if err != nil { + return false + } + file.Close() + return true +} + func configureCircuits(conf []config.Named) error { // migrate settings if settings.Exists(keys.Circuits) {