evcc-io/meter/zendure.go

82 lines
1.8 KiB
Go

package meter
import (
"fmt"
"strings"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/meter/zendure"
"github.com/evcc-io/evcc/util"
)
func init() {
registry.Add("zendure", NewZendureFromConfig)
}
type Zendure struct {
usage string
conn *zendure.Connection
}
//go:generate go tool decorate -f decorateZendure -b *Zendure -r api.Meter -t "api.Battery,Soc,func() (float64, error)" -t "api.BatteryCapacity,Capacity,func() float64"
// NewZendureFromConfig creates a Zendure meter from generic config
func NewZendureFromConfig(other map[string]interface{}) (api.Meter, error) {
cc := struct {
batteryCapacity `mapstructure:",squash"`
Usage, Account, Serial, Region string
Timeout time.Duration
}{
Region: "EU",
Timeout: 30 * time.Second,
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
conn, err := zendure.NewConnection(strings.ToUpper(cc.Region), cc.Account, cc.Serial, cc.Timeout)
if err != nil {
return nil, err
}
c := &Zendure{
usage: cc.Usage,
conn: conn,
}
// decorate battery
var soc func() (float64, error)
if cc.Usage == "battery" {
soc = c.soc
}
return decorateZendure(c, soc, cc.batteryCapacity.Decorator()), nil
}
// CurrentPower implements the api.Meter interface
func (c *Zendure) CurrentPower() (float64, error) {
res, err := c.conn.Data()
if err != nil {
return 0, err
}
switch c.usage {
case "pv":
return float64(res.SolarInputPower), nil
case "battery":
return float64(res.PackInputPower) - float64(res.OutputPackPower), nil
default:
return 0, fmt.Errorf("invalid usage: %s", c.usage)
}
}
// soc implements the api.Battery interface
func (c *Zendure) soc() (float64, error) {
res, err := c.conn.Data()
if err != nil {
return 0, err
}
return float64(res.ElectricLevel), nil
}