diff --git a/charger/fritzdect.go b/charger/fritzdect.go index 8b80de1df..2c71130b7 100644 --- a/charger/fritzdect.go +++ b/charger/fritzdect.go @@ -14,8 +14,8 @@ import ( // FritzDECT charger implementation type FritzDECT struct { - conn *fritzdect.Connection - standbypower float64 + conn *fritzdect.Connection + *switchSocket } func init() { @@ -40,12 +40,31 @@ func NewFritzDECTFromConfig(other map[string]interface{}) (api.Charger, error) { func NewFritzDECT(uri, ain, user, password string, standbypower float64) (*FritzDECT, error) { conn, err := fritzdect.NewConnection(uri, ain, user, password) - m := &FritzDECT{ - conn: conn, - standbypower: standbypower, + c := &FritzDECT{ + conn: conn, } - return m, err + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) + + return c, err +} + +// Status implements the api.Charger interface +func (c *FritzDECT) Status() (api.ChargeStatus, error) { + resp, err := c.conn.ExecCmd("getswitchpresent") + + if err == nil { + var present bool + present, err = strconv.ParseBool(resp) + if err == nil && !present { + err = api.ErrNotAvailable + } + } + if err != nil { + return api.StatusNone, err + } + + return c.switchSocket.Status() } // Enabled implements the api.Charger interface @@ -84,64 +103,6 @@ func (c *FritzDECT) MaxCurrent(current int64) error { return nil } -// Status implements the api.Charger interface -func (c *FritzDECT) Status() (api.ChargeStatus, error) { - resp, err := c.conn.ExecCmd("getswitchpresent") - - if err == nil { - var present bool - present, err = strconv.ParseBool(resp) - if err == nil && !present { - err = api.ErrNotAvailable - } - } - if err != nil { - return api.StatusNone, err - } - - res := api.StatusB - on, err := c.Enabled() - if err != nil { - return res, err - } - - power, err := c.conn.CurrentPower() - if err != nil { - return res, err - } - - // static mode || standby power mode condition - if on && (c.standbypower < 0 || power > c.standbypower) { - res = api.StatusC - } - - return res, nil -} - -var _ api.Meter = (*FritzDECT)(nil) - -// CurrentPower implements the api.Meter interface -func (c *FritzDECT) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} - var _ api.MeterEnergy = (*FritzDECT)(nil) // TotalEnergy implements the api.MeterEnergy interface diff --git a/charger/helper.go b/charger/helper.go deleted file mode 100644 index 4b1c808c0..000000000 --- a/charger/helper.go +++ /dev/null @@ -1,30 +0,0 @@ -package charger - -import "github.com/evcc-io/evcc/api" - -// switchStatus calculates a generic switches status -func switchStatus( - enabled func() (bool, error), - currentPower func() (float64, error), - standbypower float64, -) (api.ChargeStatus, error) { - res := api.StatusB - - // static mode - if standbypower < 0 { - on, err := enabled() - if on { - res = api.StatusC - } - - return res, err - } - - // standby power mode - power, err := currentPower() - if power > standbypower { - res = api.StatusC - } - - return res, err -} diff --git a/charger/homematic.go b/charger/homematic.go index a2390e943..48ee721b6 100644 --- a/charger/homematic.go +++ b/charger/homematic.go @@ -8,8 +8,8 @@ import ( // Homematic CCU charger implementation type CCU struct { - conn *homematic.Connection - standbypower float64 + conn *homematic.Connection + *switchSocket } func init() { @@ -39,12 +39,13 @@ func NewCCUFromConfig(other map[string]interface{}) (api.Charger, error) { func NewCCU(uri, deviceid, meterid, switchid, user, password string, standbypower float64) (*CCU, error) { conn, err := homematic.NewConnection(uri, deviceid, meterid, switchid, user, password) - wb := &CCU{ - conn: conn, - standbypower: standbypower, + c := &CCU{ + conn: conn, } - return wb, err + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) + + return c, err } // Enabled implements the api.Charger interface @@ -62,51 +63,6 @@ func (c *CCU) MaxCurrent(current int64) error { return nil } -// Status implements the api.Charger interface -func (c *CCU) Status() (api.ChargeStatus, error) { - res := api.StatusB - on, err := c.Enabled() - if err != nil { - return res, err - } - - power, err := c.conn.CurrentPower() - if err != nil { - return res, err - } - - // static mode || standby power mode condition - if on && (c.standbypower < 0 || power > c.standbypower) { - res = api.StatusC - } - - return res, nil -} - -var _ api.Meter = (*CCU)(nil) - -// CurrentPower implements the api.Meter interface -func (c *CCU) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} - var _ api.MeterEnergy = (*CCU)(nil) // TotalEnergy implements the api.MeterEnergy interface diff --git a/charger/mystrom.go b/charger/mystrom.go index 570d996e4..b1a8603ac 100644 --- a/charger/mystrom.go +++ b/charger/mystrom.go @@ -19,10 +19,10 @@ func init() { // MyStrom charger implementation type MyStrom struct { - *mystrom.Connection - standbypower float64 - cache time.Duration - reportG func() (mystrom.Report, error) + conn *mystrom.Connection + *switchSocket + cache time.Duration + reportG func() (mystrom.Report, error) } // NewMyStromFromConfig creates a myStrom charger from generic config @@ -40,23 +40,16 @@ func NewMyStromFromConfig(other map[string]interface{}) (api.Charger, error) { } c := &MyStrom{ - Connection: mystrom.NewConnection(cc.URI), - standbypower: cc.StandbyPower, - cache: cc.Cache, + conn: mystrom.NewConnection(cc.URI), + cache: cc.Cache, } - c.reportG = provider.Cached(c.Report, c.cache) + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, cc.StandbyPower) + c.reportG = provider.Cached(c.conn.Report, c.cache) return c, nil } -var _ api.Meter = (*MyStrom)(nil) - -// Status implements the api.Charger interface -func (c *MyStrom) Status() (api.ChargeStatus, error) { - return switchStatus(c.Enabled, c.CurrentPower, c.standbypower) -} - // Enabled implements the api.Charger interface func (c *MyStrom) Enabled() (bool, error) { res, err := c.reportG() @@ -66,10 +59,10 @@ func (c *MyStrom) Enabled() (bool, error) { // Enable implements the api.Charger interface func (c *MyStrom) Enable(enable bool) error { // reset cache - c.reportG = provider.Cached(c.Report, c.cache) + c.reportG = provider.Cached(c.conn.Report, c.cache) onoff := map[bool]int{false: 0, true: 1} - return c.Request(fmt.Sprintf("relay?state=%d", onoff[enable])) + return c.conn.Request(fmt.Sprintf("relay?state=%d", onoff[enable])) } // MaxCurrent implements the api.Charger interface diff --git a/charger/shelly.go b/charger/shelly.go index ab823e689..b0b85554e 100644 --- a/charger/shelly.go +++ b/charger/shelly.go @@ -10,8 +10,8 @@ import ( // Shelly charger implementation type Shelly struct { - conn *shelly.Connection - standbypower float64 + conn *shelly.Connection + *switchSocket } func init() { @@ -42,12 +42,13 @@ func NewShelly(uri, user, password string, channel int, standbypower float64) (* return nil, err } - shelly := &Shelly{ - conn: conn, - standbypower: standbypower, + c := &Shelly{ + conn: conn, } - return shelly, nil + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) + + return c, nil } // Enabled implements the api.Charger interface @@ -78,50 +79,3 @@ func (c *Shelly) Enable(enable bool) error { func (c *Shelly) MaxCurrent(current int64) error { return nil } - -// Status implements the api.Charger interface -func (c *Shelly) Status() (api.ChargeStatus, error) { - res := api.StatusB - - // static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - res = api.StatusC - } - - return res, err - } - - // standby power mode - power, err := c.CurrentPower() - if power > c.standbypower { - res = api.StatusC - } - - return res, err -} - -var _ api.Meter = (*Shelly)(nil) - -// CurrentPower implements the api.Meter interface -func (c *Shelly) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} diff --git a/charger/switchsocket.go b/charger/switchsocket.go new file mode 100644 index 000000000..0bcf76bb2 --- /dev/null +++ b/charger/switchsocket.go @@ -0,0 +1,70 @@ +package charger + +import "github.com/evcc-io/evcc/api" + +// switchSocket implements the api.Charger Status and CurrentPower methods +// using basic generic switch socket functions +type switchSocket struct { + enabled func() (bool, error) + currentPower func() (float64, error) + standbypower float64 +} + +func NewSwitchSocket( + enabled func() (bool, error), + currentPower func() (float64, error), + standbypower float64, +) *switchSocket { + return &switchSocket{ + enabled: enabled, + currentPower: currentPower, + standbypower: standbypower, + } +} + +// Status calculates a generic switches status +func (c *switchSocket) Status() (api.ChargeStatus, error) { + res := api.StatusB + + // static mode + if c.standbypower < 0 { + on, err := c.enabled() + if on { + res = api.StatusC + } + + return res, err + } + + // standby power mode + power, err := c.currentPower() + if power > c.standbypower { + res = api.StatusC + } + + return res, err +} + +var _ api.Meter = (*switchSocket)(nil) + +// CurrentPower calculates a generic switches power +func (c *switchSocket) CurrentPower() (float64, error) { + var power float64 + + // set fix static power in static mode + if c.standbypower < 0 { + on, err := c.enabled() + if on { + power = -c.standbypower + } + return power, err + } + + // ignore power in standby mode + power, err := c.currentPower() + if power <= c.standbypower { + power = 0 + } + + return power, err +} diff --git a/charger/tapo.go b/charger/tapo.go index 5c9d695b3..e87e00c75 100644 --- a/charger/tapo.go +++ b/charger/tapo.go @@ -8,8 +8,8 @@ import ( // TP-Link Tapo charger implementation type Tapo struct { - conn *tapo.Connection - standbypower float64 + conn *tapo.Connection + *switchSocket } func init() { @@ -39,12 +39,13 @@ func NewTapo(uri, user, password string, standbypower float64) (*Tapo, error) { return nil, err } - tapo := &Tapo{ - conn: conn, - standbypower: standbypower, + c := &Tapo{ + conn: conn, } - return tapo, nil + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) + + return c, nil } // Enabled implements the api.Charger interface @@ -67,51 +68,6 @@ func (c *Tapo) MaxCurrent(current int64) error { return nil } -// Status implements the api.Charger interface -func (c *Tapo) Status() (api.ChargeStatus, error) { - res := api.StatusB - on, err := c.Enabled() - if err != nil { - return res, err - } - - power, err := c.conn.CurrentPower() - if err != nil { - return res, err - } - - // static mode || standby power mode condition - if on && (c.standbypower < 0 || power > c.standbypower) { - res = api.StatusC - } - - return res, nil -} - -var _ api.Meter = (*Tapo)(nil) - -// CurrentPower implements the api.Meter interface -func (c *Tapo) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} - var _ api.ChargeRater = (*Tapo)(nil) // ChargedEnergy implements the api.ChargeRater interface diff --git a/charger/tasmota.go b/charger/tasmota.go index 8783459a8..bcb067c1b 100644 --- a/charger/tasmota.go +++ b/charger/tasmota.go @@ -17,9 +17,9 @@ import ( // Tasmota charger implementation type Tasmota struct { - conn *tasmota.Connection - channel int - standbypower float64 + conn *tasmota.Connection + channel int + *switchSocket } func init() { @@ -53,14 +53,13 @@ func NewTasmota(uri, user, password string, channel int, standbypower float64) ( } c := &Tasmota{ - conn: conn, - channel: channel, - standbypower: standbypower, + conn: conn, + channel: channel, } - err = c.channelExists(channel) + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) - return c, err + return c, c.channelExists(channel) } // channelExists checks the existence of the configured relay channel interface @@ -173,53 +172,6 @@ func (c *Tasmota) MaxCurrent(current int64) error { return nil } -// Status implements the api.Charger interface -func (c *Tasmota) Status() (api.ChargeStatus, error) { - res := api.StatusB - - // static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - res = api.StatusC - } - - return res, err - } - - // standby power mode - power, err := c.CurrentPower() - if power > c.standbypower { - res = api.StatusC - } - - return res, err -} - -var _ api.Meter = (*Tasmota)(nil) - -// CurrentPower implements the api.Meter interface -func (c *Tasmota) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} - var _ api.MeterEnergy = (*Tasmota)(nil) // TotalEnergy implements the api.MeterEnergy interface diff --git a/charger/tplink.go b/charger/tplink.go index 9ec7be5d8..bc5be79ed 100644 --- a/charger/tplink.go +++ b/charger/tplink.go @@ -12,8 +12,8 @@ import ( // TPLink charger implementation type TPLink struct { - conn *tplink.Connection - standbypower float64 + conn *tplink.Connection + *switchSocket } func init() { @@ -46,9 +46,11 @@ func NewTPLink(uri string, standbypower float64) (*TPLink, error) { } c := &TPLink{ - conn: conn, - standbypower: standbypower, + conn: conn, } + + c.switchSocket = NewSwitchSocket(c.Enabled, c.conn.CurrentPower, standbypower) + return c, nil } @@ -94,53 +96,6 @@ func (c *TPLink) MaxCurrent(current int64) error { return nil } -// Status implements the api.Charger interface -func (c *TPLink) Status() (api.ChargeStatus, error) { - res := api.StatusB - - // static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - res = api.StatusC - } - - return res, err - } - - // standby power mode - power, err := c.CurrentPower() - if power > c.standbypower { - res = api.StatusC - } - - return res, err -} - -var _ api.Meter = (*TPLink)(nil) - -// CurrentPower implements the api.Meter interface -func (c *TPLink) CurrentPower() (float64, error) { - var power float64 - - // set fix static power in static mode - if c.standbypower < 0 { - on, err := c.Enabled() - if on { - power = -c.standbypower - } - return power, err - } - - // ignore power in standby mode - power, err := c.conn.CurrentPower() - if power <= c.standbypower { - power = 0 - } - - return power, err -} - var _ api.MeterEnergy = (*TPLink)(nil) // TotalEnergy implements the api.MeterEnergy interface diff --git a/core/loadpoint_api.go b/core/loadpoint_api.go index 3b72f2668..a2dada557 100644 --- a/core/loadpoint_api.go +++ b/core/loadpoint_api.go @@ -201,7 +201,7 @@ func (lp *LoadPoint) GetMaxCurrent() float64 { return lp.MaxCurrent } -// SetMaxCurrent returns the max loadpoint current +// SetMaxCurrent sets the max loadpoint current func (lp *LoadPoint) SetMaxCurrent(current float64) { lp.Lock() defer lp.Unlock()