/
tplink.go
100 lines (78 loc) · 2.24 KB
/
tplink.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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]interface{}) (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()
}