125 lines
2.9 KiB
Go
125 lines
2.9 KiB
Go
package core
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"slices"
|
|
|
|
"github.com/evcc-io/evcc/api"
|
|
"github.com/evcc-io/evcc/core/keys"
|
|
"github.com/evcc-io/evcc/util/config"
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type circuitStruct struct {
|
|
Title string `json:"title,omitempty"`
|
|
Icon string `json:"icon,omitempty"`
|
|
Parent string `json:"parent,omitempty"`
|
|
Power float64 `json:"power"`
|
|
Current *float64 `json:"current,omitempty"`
|
|
MaxPower float64 `json:"maxPower,omitempty"`
|
|
MaxCurrent float64 `json:"maxCurrent,omitempty"`
|
|
Dimmed *bool `json:"dimmed,omitempty"`
|
|
Curtailed *bool `json:"curtailed,omitempty"`
|
|
}
|
|
|
|
// publishCircuits returns a list of circuit titles
|
|
func (site *Site) publishCircuits() {
|
|
cc := config.Circuits().Devices()
|
|
res := make(map[string]circuitStruct, len(cc))
|
|
|
|
names := make(map[api.Circuit]string, len(cc))
|
|
for _, c := range cc {
|
|
names[c.Instance()] = c.Config().Name
|
|
}
|
|
|
|
for _, c := range cc {
|
|
instance := c.Instance()
|
|
props := deviceProperties(c)
|
|
|
|
data := circuitStruct{
|
|
Title: instance.GetTitle(),
|
|
Icon: props.Icon,
|
|
Parent: names[instance.GetParent()],
|
|
Power: instance.GetChargePower(),
|
|
MaxPower: instance.GetMaxPower(),
|
|
MaxCurrent: instance.GetMaxCurrent(),
|
|
Dimmed: instance.Dimmed(),
|
|
Curtailed: instance.Curtailed(),
|
|
}
|
|
|
|
if instance.GetMaxCurrent() > 0 {
|
|
data.Current = lo.EmptyableToPtr(instance.GetMaxPhaseCurrent())
|
|
}
|
|
|
|
res[c.Config().Name] = data
|
|
}
|
|
|
|
site.publish(keys.Circuits, res)
|
|
}
|
|
|
|
func (site *Site) dimMeters(dim *bool) error {
|
|
if dim == nil {
|
|
return nil
|
|
}
|
|
|
|
var errs error
|
|
for _, dev := range slices.Concat(site.auxMeters, site.extMeters) {
|
|
m, ok := api.Cap[api.Dimmer](dev.Instance())
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if dimmed, err := m.Dimmed(); err == nil {
|
|
if *dim == dimmed {
|
|
continue
|
|
}
|
|
} else {
|
|
if !errors.Is(err, api.ErrNotAvailable) {
|
|
errs = errors.Join(errs, fmt.Errorf("%s dimmed: %w", dev.Config().Name, err))
|
|
}
|
|
continue
|
|
}
|
|
|
|
if err := m.Dim(*dim); err == nil {
|
|
site.log.DEBUG.Printf("%s dim: %t", dev.Config().Name, *dim)
|
|
} else if !errors.Is(err, api.ErrNotAvailable) {
|
|
errs = errors.Join(errs, fmt.Errorf("%s dim: %w", dev.Config().Name, err))
|
|
}
|
|
}
|
|
|
|
return errs
|
|
}
|
|
|
|
func (site *Site) curtailPV(curtail *bool) error {
|
|
if curtail == nil {
|
|
return nil
|
|
}
|
|
|
|
var errs error
|
|
for _, dev := range site.pvMeters {
|
|
m, ok := api.Cap[api.Curtailer](dev.Instance())
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
if curtailed, err := m.Curtailed(); err == nil {
|
|
if *curtail == curtailed {
|
|
continue
|
|
}
|
|
} else {
|
|
if !errors.Is(err, api.ErrNotAvailable) {
|
|
errs = errors.Join(errs, fmt.Errorf("%s curtailed: %w", dev.Config().Name, err))
|
|
}
|
|
continue
|
|
}
|
|
|
|
if err := m.Curtail(*curtail); err == nil {
|
|
site.log.DEBUG.Printf("%s curtail: %t", dev.Config().Name, *curtail)
|
|
} else if !errors.Is(err, api.ErrNotAvailable) {
|
|
errs = errors.Join(errs, fmt.Errorf("%s curtail: %w", dev.Config().Name, err))
|
|
}
|
|
}
|
|
|
|
return errs
|
|
}
|