diff --git a/core/settings/config.go b/core/settings/config.go index 9b7bd5ae0..7e9c63d08 100644 --- a/core/settings/config.go +++ b/core/settings/config.go @@ -3,6 +3,7 @@ package settings import ( "encoding/json" "errors" + "sync" "time" "github.com/evcc-io/evcc/util" @@ -13,15 +14,18 @@ import ( var _ Settings = (*ConfigSettings)(nil) type ConfigSettings struct { + mu sync.Mutex log *util.Logger conf *config.Config } func NewConfigSettingsAdapter(log *util.Logger, conf *config.Config) *ConfigSettings { - return &ConfigSettings{log, conf} + return &ConfigSettings{log: log, conf: conf} } func (s *ConfigSettings) get(key string) (any, error) { + s.mu.Lock() + defer s.mu.Unlock() val := s.conf.Named().Other[key] if val == nil { return nil, errors.New("not found") @@ -29,10 +33,13 @@ func (s *ConfigSettings) get(key string) (any, error) { return val, nil } +// TODO remove broken error handling when settings api is retired func (s *ConfigSettings) set(key string, val any) { + s.mu.Lock() + defer s.mu.Unlock() data := s.conf.Named().Other data[key] = val - if err := s.conf.PartialUpdate(data); err != nil { + if err := s.conf.Update(data); err != nil { s.log.ERROR.Println(err) } } diff --git a/server/http_config_loadpoint_handler.go b/server/http_config_loadpoint_handler.go index 16e7dc6c3..c235c3811 100644 --- a/server/http_config_loadpoint_handler.go +++ b/server/http_config_loadpoint_handler.go @@ -6,6 +6,7 @@ import ( "net/http" "strconv" + "dario.cat/mergo" "github.com/evcc-io/evcc/core" "github.com/evcc-io/evcc/core/loadpoint" coresettings "github.com/evcc-io/evcc/core/settings" @@ -194,8 +195,6 @@ func updateLoadpointHandler() http.HandlerFunc { return } - instance := dev.Instance() - dynamic, static, err := loadpointSplitConfig(r.Body) if err != nil { jsonError(w, http.StatusBadRequest, err) @@ -203,7 +202,17 @@ func updateLoadpointHandler() http.HandlerFunc { } // static - if err := configurable.PartialUpdate(static, instance); err != nil { + + // merge here to maintain dynamic part of the config + other := configurable.Config().Other + if err := mergo.Merge(&other, static); err != nil { + jsonError(w, http.StatusBadRequest, err) + return + } + + instance := dev.Instance() + + if err := configurable.Update(other, instance); err != nil { jsonError(w, http.StatusBadRequest, err) return } diff --git a/util/config/config.go b/util/config/config.go index 74916fc12..8e8617135 100644 --- a/util/config/config.go +++ b/util/config/config.go @@ -6,7 +6,6 @@ import ( "strconv" "strings" - "dario.cat/mergo" "github.com/evcc-io/evcc/util/templates" "gorm.io/gorm" ) @@ -58,22 +57,6 @@ func (d *Config) Update(conf map[string]any) error { }) } -// PartialUpdate partially updates a config's details to the database -func (d *Config) PartialUpdate(conf map[string]any) error { - return db.Transaction(func(tx *gorm.DB) error { - var config Config - if err := tx.Where(Config{Class: d.Class, ID: d.ID}).First(&config).Error; err != nil { - return err - } - - if err := mergo.Merge(&d.Data, conf, mergo.WithOverride); err != nil { - return err - } - - return tx.Save(&d).Error - }) -} - // Delete deletes a config from the database func (d *Config) Delete() error { return db.Delete(Config{ID: d.ID}).Error diff --git a/util/config/device.go b/util/config/device.go index 8d60b1b5f..d37d05dff 100644 --- a/util/config/device.go +++ b/util/config/device.go @@ -8,7 +8,6 @@ type ConfigurableDevice[T any] interface { Device[T] ID() int Update(map[string]any, T) error - PartialUpdate(map[string]any, T) error Delete() error } @@ -36,14 +35,6 @@ func (d *configurableDevice[T]) ID() int { return d.config.ID } -// func (d *configurableDevice[T]) Assign(instance T) { -// d.instance = instance -// } - -// func (d *configurableDevice[T]) Update(config map[string]any) error { -// return d.config.Update(config) -// } - func (d *configurableDevice[T]) Update(config map[string]any, instance T) error { if err := d.config.Update(config); err != nil { return err @@ -52,14 +43,6 @@ func (d *configurableDevice[T]) Update(config map[string]any, instance T) error return nil } -func (d *configurableDevice[T]) PartialUpdate(config map[string]any, instance T) error { - if err := d.config.PartialUpdate(config); err != nil { - return err - } - d.instance = instance - return nil -} - func (d *configurableDevice[T]) Delete() error { return d.config.Delete() } diff --git a/util/config/types.go b/util/config/types.go index 4af9e13b7..1d27474ba 100644 --- a/util/config/types.go +++ b/util/config/types.go @@ -6,13 +6,13 @@ import ( type Typed struct { Type string `json:"type"` - Other map[string]any `mapstructure:",remain" yaml:",inline"` + Other map[string]any `mapstructure:",remain" yaml:",inline"` // TODO JSON serialization } type Named struct { Name string `json:"name"` Type string `json:"type"` - Other map[string]any `mapstructure:",remain" yaml:",inline"` + Other map[string]any `mapstructure:",remain" yaml:",inline"` // TODO JSON serialization } // Property returns the value of the named property