evcc-io/meter/bosch_bpts5_hybrid.go

93 lines
2.4 KiB
Go

package meter
import (
"errors"
"strings"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/api/implement"
"github.com/evcc-io/evcc/meter/bosch"
"github.com/evcc-io/evcc/util"
)
type BoschBpts5Hybrid struct {
implement.Caps
api *bosch.API
usage string
}
func init() {
registry.Add("bosch-bpt", NewBoschBpts5HybridFromConfig)
}
// NewBoschBpts5HybridFromConfig creates a Bosch BPT-S 5 Hybrid Meter from generic config
func NewBoschBpts5HybridFromConfig(other map[string]any) (api.Meter, error) {
var cc struct {
batteryCapacity `mapstructure:",squash"`
batteryPowerLimits `mapstructure:",squash"`
batterySocLimits `mapstructure:",squash"`
URI string
Usage string
Cache time.Duration
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
if cc.Usage == "" {
return nil, errors.New("missing usage")
}
return NewBoschBpts5Hybrid(cc.URI, cc.Usage, cc.Cache, cc.batteryCapacity.Decorator(), cc.batterySocLimits.Decorator(), cc.batteryPowerLimits.Decorator())
}
// NewBoschBpts5Hybrid creates a Bosch BPT-S 5 Hybrid Meter
func NewBoschBpts5Hybrid(uri, usage string, cache time.Duration, capacity func() float64, batterySocLimits, batteryPowerLimits func() (float64, float64)) (*BoschBpts5Hybrid, error) {
log := util.NewLogger("bosch-bpt")
instance, exists := bosch.Instances.LoadOrStore(uri, bosch.NewLocal(log, uri, cache))
if !exists {
if err := instance.(*bosch.API).Login(); err != nil {
return nil, err
}
}
m := &BoschBpts5Hybrid{
Caps: implement.New(),
api: instance.(*bosch.API),
usage: strings.ToLower(usage),
}
if usage == "battery" {
implement.Has(m, implement.Battery(m.soc))
implement.May(m, implement.BatteryCapacity(capacity))
implement.May(m, implement.BatterySocLimiter(batterySocLimits))
implement.May(m, implement.BatteryPowerLimiter(batteryPowerLimits))
}
return m, nil
}
// CurrentPower implements the api.Meter interface
func (m *BoschBpts5Hybrid) CurrentPower() (float64, error) {
status, err := m.api.Status()
switch m.usage {
case "grid":
return status.BuyFromGrid - status.SellToGrid, err
case "pv":
return status.PvPower, err
case "battery":
return status.BatteryDischargePower - status.BatteryChargePower, err
default:
return 0, err
}
}
// soc implements the api.Battery interface
func (m *BoschBpts5Hybrid) soc() (float64, error) {
status, err := m.api.Status()
return status.CurrentBatterySoc, err
}