evcc-io/meter/shelly.go

90 lines
2.1 KiB
Go

package meter
import (
"math"
"strings"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/api/implement"
"github.com/evcc-io/evcc/meter/shelly"
"github.com/evcc-io/evcc/util"
)
// Shelly meter considering usage
type Shelly struct {
implement.Caps
conn *shelly.Connection
usage string
}
// Shelly meter implementation
func init() {
registry.Add("shelly", NewShellyFromConfig)
}
// NewShellyFromConfig creates a Shelly charger from generic config
func NewShellyFromConfig(other map[string]any) (api.Meter, error) {
cc := struct {
URI string
User string
Password string
Channel int
Usage string
Cache time.Duration
}{
Cache: time.Second,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
c, err := NewShelly(cc.URI, cc.User, cc.Password, strings.ToLower(cc.Usage), cc.Channel, cc.Cache)
if err != nil {
return nil, err
}
// Three-phase Shelly energy meters count each phase separately (non-balanced),
// making their totals unsuitable for bidirectional grid metering.
if !(c.usage == "grid" && c.conn.IsThreePhase()) {
implement.Has(c, implement.MeterEnergy(c.conn.TotalEnergy))
implement.Has(c, implement.MeterReturnEnergy(c.conn.ReturnEnergy))
}
if phases, ok := c.conn.Generation.(shelly.Phases); ok {
implement.Has(c, implement.PhaseVoltages(phases.Voltages))
implement.Has(c, implement.PhaseCurrents(phases.Currents))
implement.Has(c, implement.PhasePowers(phases.Powers))
}
return c, nil
}
// NewShelly creates Shelly meter
func NewShelly(uri, user, password, usage string, channel int, cache time.Duration) (*Shelly, error) {
conn, err := shelly.NewConnection(uri, user, password, channel, cache)
if err != nil {
return nil, err
}
c := &Shelly{
Caps: implement.New(),
conn: conn,
usage: usage,
}
return c, nil
}
var _ api.Meter = (*Shelly)(nil)
// CurrentPower implements the api.Meter interface
func (c *Shelly) CurrentPower() (float64, error) {
power, err := c.conn.CurrentPower()
if err != nil {
return 0, err
}
if c.usage == "pv" {
power = math.Abs(power)
}
return power, nil
}