Skip to content

Commit

Permalink
Fix loadpoint persistence
Browse files Browse the repository at this point in the history
  • Loading branch information
andig committed Oct 4, 2024
1 parent 4d5acc5 commit feec740
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 227 deletions.
22 changes: 11 additions & 11 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ func configureMeters(static []config.Named, names ...string) error {
return &DeviceError{cc.Name, fmt.Errorf("cannot create meter '%s': %w", cc.Name, err)}
}

if err := config.Meters().Add(config.NewConfigurableDevice(conf, instance)); err != nil {
if err := config.Meters().Add(config.NewConfigurableDevice(&conf, instance)); err != nil {
return &DeviceError{cc.Name, err}
}

Expand Down Expand Up @@ -319,7 +319,7 @@ func configureChargers(static []config.Named, names ...string) error {
return fmt.Errorf("cannot create charger '%s': %w", cc.Name, err)
}

if err := config.Chargers().Add(config.NewConfigurableDevice(conf, instance)); err != nil {
if err := config.Chargers().Add(config.NewConfigurableDevice(&conf, instance)); err != nil {
return &DeviceError{cc.Name, err}
}

Expand Down Expand Up @@ -410,7 +410,7 @@ func configureVehicles(static []config.Named, names ...string) error {

mu.Lock()
defer mu.Unlock()
devs2 = append(devs2, config.NewConfigurableDevice(conf, instance))
devs2 = append(devs2, config.NewConfigurableDevice(&conf, instance))

return nil
})
Expand Down Expand Up @@ -979,22 +979,22 @@ func configureLoadpoints(conf globalconfig.All) error {

id := len(config.Loadpoints().Devices())
name := "lp-" + strconv.Itoa(id+1)

log := util.NewLoggerWithLoadpoint(name, id+1)

dev := config.BlankConfigurableDevice[loadpoint.API]()
settings := coresettings.NewDeviceSettingsAdapter(dev)
settings := coresettings.NewConfigSettingsAdapter(&conf)

// TODO: proper handling of id/name
delete(cc.Other, "id")
delete(cc.Other, "name")
dynamic, static, err := loadpoint.SplitConfig(cc.Other)

instance, err := core.NewLoadpointFromConfig(log, settings, cc.Other)
instance, err := core.NewLoadpointFromConfig(log, settings, static)
if err != nil {
return fmt.Errorf("failed configuring loadpoint: %w", err)
}
dev.Update(cc.Other, instance)

if err := dynamic.Apply(instance); err != nil {
return err
}

dev := config.NewConfigurableDevice[loadpoint.API](&conf, instance)
if err := config.Loadpoints().Add(dev); err != nil {
return err
}
Expand Down
75 changes: 75 additions & 0 deletions core/loadpoint/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package loadpoint

import (
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/util"
)

type StaticConfig struct {
// static config
Charger string `json:"charger,omitempty"`
Meter string `json:"meter,omitempty"`
Circuit string `json:"circuit,omitempty"`
Vehicle string `json:"vehicle,omitempty"`
}

type DynamicConfig struct {
// dynamic config
Title string `json:"title"`
Mode string `json:"mode"`
Priority int `json:"priority"`
Phases int `json:"phases"`
MinCurrent float64 `json:"minCurrent"`
MaxCurrent float64 `json:"maxCurrent"`
SmartCostLimit *float64 `json:"smartCostLimit"`

Thresholds ThresholdsConfig `json:"thresholds"`
Soc SocConfig `json:"soc"`
}

func SplitConfig(payload map[string]any) (DynamicConfig, map[string]any, error) {
// split static and dynamic config via mapstructure
var cc struct {
DynamicConfig `mapstructure:",squash"`
Other map[string]any `mapstructure:",remain"`
}

if err := util.DecodeOther(payload, &cc); err != nil {
return DynamicConfig{}, nil, err
}

// TODO: proper handling of id/name
delete(cc.Other, "id")
delete(cc.Other, "name")

return cc.DynamicConfig, cc.Other, nil
}

func (payload DynamicConfig) Apply(lp API) error {
lp.SetTitle(payload.Title)
lp.SetPriority(payload.Priority)
lp.SetSmartCostLimit(payload.SmartCostLimit)
lp.SetThresholds(payload.Thresholds)

// TODO mode warning
lp.SetSocConfig(payload.Soc)

mode, err := api.ChargeModeString(payload.Mode)
if err == nil {
lp.SetMode(mode)
}

if err == nil {
err = lp.SetPhases(payload.Phases)
}

if err == nil {
err = lp.SetMinCurrent(payload.MinCurrent)
}

if err == nil {
err = lp.SetMaxCurrent(payload.MaxCurrent)
}

return err
}
119 changes: 119 additions & 0 deletions core/settings/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package settings

import (
"encoding/json"
"time"

"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/config"
"github.com/spf13/cast"
)

var _ Settings = (*ConfigSettings)(nil)

type ConfigSettings struct {
log *util.Logger
conf *config.Config
}

func NewConfigSettingsAdapter(log *util.Logger, conf *config.Config) *ConfigSettings {
return &ConfigSettings{log, conf}
}

func (s *ConfigSettings) get(key string) any {
return s.conf.Named().Other[key]
}

func (s *ConfigSettings) set(key string, val any) {
data := s.conf.Named().Other
data[key] = val
if err := s.conf.Update(data); err != nil {
s.log.ERROR.Println(err)
}
}

func (s *ConfigSettings) SetString(key string, val string) {
if s == nil {
return
}
s.set(key, val)
}

func (s *ConfigSettings) SetInt(key string, val int64) {
if s == nil {
return
}
s.set(key, val)
}

func (s *ConfigSettings) SetFloat(key string, val float64) {
if s == nil {
return
}
s.set(key, val)
}

func (s *ConfigSettings) SetTime(key string, val time.Time) {
if s == nil {
return
}
s.set(key, val)
}

func (s *ConfigSettings) SetBool(key string, val bool) {
if s == nil {
return
}
s.set(key, val)
}

func (s *ConfigSettings) SetJson(key string, val any) error {
if s == nil {
return nil
}
s.set(key, val)
return nil
}

func (s *ConfigSettings) String(key string) (string, error) {
if s == nil {
return "", nil
}
return cast.ToStringE(s.get(key))
}

func (s *ConfigSettings) Int(key string) (int64, error) {
if s == nil {
return 0, nil
}
return cast.ToInt64E(s.get(key))
}

func (s *ConfigSettings) Float(key string) (float64, error) {
if s == nil {
return 0, nil
}
return cast.ToFloat64E(s.get(key))
}

func (s *ConfigSettings) Time(key string) (time.Time, error) {
if s == nil {
return time.Time{}, nil
}
return cast.ToTimeE(s.get(key))
}

func (s *ConfigSettings) Bool(key string) (bool, error) {
if s == nil {
return false, nil
}
return cast.ToBoolE(s.get(key))
}

func (s *ConfigSettings) Json(key string, res any) error {
str, err := s.String(key)
if str == "" || err != nil {
return err
}
return json.Unmarshal([]byte(str), &res)
}
121 changes: 0 additions & 121 deletions core/settings/device.go

This file was deleted.

2 changes: 1 addition & 1 deletion server/http_config_device_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func newDevice[T any](class templates.Class, req map[string]any, newFromConf fun
return nil, err
}

return &conf, h.Add(config.NewConfigurableDevice[T](conf, instance))
return &conf, h.Add(config.NewConfigurableDevice[T](&conf, instance))
}

// newDeviceHandler creates a new device by class
Expand Down
Loading

0 comments on commit feec740

Please sign in to comment.