Harmonise switch sockets status and power api implementations (#3833)

This commit is contained in:
andig 2022-07-14 21:35:33 +02:00
parent ffd5eb03a7
commit 03da7205c2
10 changed files with 140 additions and 373 deletions

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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
}

70
charger/switchsocket.go Normal file
View file

@ -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
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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()