100 lines
2.2 KiB
Go
100 lines
2.2 KiB
Go
package charger
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/evcc-io/evcc/api"
|
|
"github.com/evcc-io/evcc/meter/tplink"
|
|
"github.com/evcc-io/evcc/util"
|
|
)
|
|
|
|
// TPLink charger implementation
|
|
type TPLink struct {
|
|
conn *tplink.Connection
|
|
*switchSocket
|
|
}
|
|
|
|
func init() {
|
|
registry.Add("tplink", NewTPLinkFromConfig)
|
|
}
|
|
|
|
// NewTPLinkFromConfig creates a TP-Link charger from generic config
|
|
func NewTPLinkFromConfig(other map[string]any) (api.Charger, error) {
|
|
var cc struct {
|
|
embed `mapstructure:",squash"`
|
|
URI string
|
|
StandbyPower float64
|
|
}
|
|
|
|
if err := util.DecodeOther(other, &cc); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if cc.URI == "" {
|
|
return nil, errors.New("missing uri")
|
|
}
|
|
|
|
return NewTPLink(cc.embed, cc.URI, cc.StandbyPower)
|
|
}
|
|
|
|
// NewTPLink creates TP-Link charger
|
|
func NewTPLink(embed embed, uri string, standbypower float64) (*TPLink, error) {
|
|
conn, err := tplink.NewConnection(uri)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c := &TPLink{
|
|
conn: conn,
|
|
}
|
|
|
|
c.switchSocket = NewSwitchSocket(&embed, c.Enabled, c.conn.CurrentPower, standbypower)
|
|
|
|
return c, nil
|
|
}
|
|
|
|
// Enabled implements the api.Charger interface
|
|
func (c *TPLink) Enabled() (bool, error) {
|
|
var res tplink.SystemResponse
|
|
if err := c.conn.ExecCmd(`{"system":{"get_sysinfo":null}}`, &res); err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if err := res.System.GetSysinfo.ErrCode; err != 0 {
|
|
return false, fmt.Errorf("get_sysinfo error %d", err)
|
|
}
|
|
|
|
if !strings.Contains(res.System.GetSysinfo.Feature, "ENE") {
|
|
return false, errors.New(res.System.GetSysinfo.Model + " not supported, energy meter feature missing")
|
|
}
|
|
|
|
return res.System.GetSysinfo.RelayState == 1, nil
|
|
}
|
|
|
|
// Enable implements the api.Charger interface
|
|
func (c *TPLink) Enable(enable bool) error {
|
|
var res tplink.SystemResponse
|
|
cmd := `{"system":{"set_relay_state":{"state":0}}}`
|
|
if enable {
|
|
cmd = `{"system":{"set_relay_state":{"state":1}}}`
|
|
}
|
|
|
|
if err := c.conn.ExecCmd(cmd, &res); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := res.System.SetRelayState.ErrCode; err != 0 {
|
|
return fmt.Errorf("set_relay_state error %d", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
var _ api.MeterEnergy = (*TPLink)(nil)
|
|
|
|
// TotalEnergy implements the api.MeterEnergy interface
|
|
func (c *TPLink) TotalEnergy() (float64, error) {
|
|
return c.conn.TotalEnergy()
|
|
}
|