Skip to content

Commit

Permalink
Return errors instead of failing
Browse files Browse the repository at this point in the history
andig committed Jul 29, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 9e7cf67 commit b1de095
Showing 51 changed files with 629 additions and 412 deletions.
44 changes: 32 additions & 12 deletions charger/charger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package charger

import (
"fmt"

"github.com/andig/evcc/api"
"github.com/andig/evcc/provider"
"github.com/andig/evcc/util"
@@ -15,9 +17,11 @@ type Charger struct {
}

// NewConfigurableFromConfig creates a new configurable charger
func NewConfigurableFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewConfigurableFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct{ Status, Enable, Enabled, MaxCurrent provider.Config }{}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

for k, v := range map[string]string{
"status": cc.Status.Type,
@@ -26,18 +30,32 @@ func NewConfigurableFromConfig(log *util.Logger, other map[string]interface{}) a
"maxcurrent": cc.MaxCurrent.Type,
} {
if v == "" {
log.FATAL.Fatalf("default charger config: %s required", k)
return nil, fmt.Errorf("default charger config: %s required", k)
}
}

charger := NewConfigurable(
provider.NewStringGetterFromConfig(log, cc.Status),
provider.NewBoolGetterFromConfig(log, cc.Enabled),
provider.NewBoolSetterFromConfig(log, "enable", cc.Enable),
provider.NewIntSetterFromConfig(log, "maxcurrent", cc.MaxCurrent),
)
status, err := provider.NewStringGetterFromConfig(cc.Status)

var enabled func() (bool, error)
if err == nil {
enabled, err = provider.NewBoolGetterFromConfig(cc.Enabled)
}

var enable func(bool) error
if err == nil {
enable, err = provider.NewBoolSetterFromConfig("enable", cc.Enable)
}

var maxcurrent func(int64) error
if err == nil {
maxcurrent, err = provider.NewIntSetterFromConfig("maxcurrent", cc.MaxCurrent)
}

if err != nil {
return nil, err
}

return charger
return NewConfigurable(status, enabled, enable, maxcurrent)
}

// NewConfigurable creates a new charger
@@ -46,13 +64,15 @@ func NewConfigurable(
enabledG func() (bool, error),
enableS func(bool) error,
maxCurrentS func(int64) error,
) api.Charger {
return &Charger{
) (api.Charger, error) {
c := &Charger{
statusG: statusG,
enabledG: enabledG,
enableS: enableS,
maxCurrentS: maxCurrentS,
}

return c, nil
}

// Status implements the Charger.Status interface
32 changes: 15 additions & 17 deletions charger/config.go
Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
package charger

import (
"fmt"
"strings"

"github.com/andig/evcc/api"
"github.com/andig/evcc/util"
)

type apiFunction string

// NewFromConfig creates charger from configuration
func NewFromConfig(log *util.Logger, typ string, other map[string]interface{}) api.Charger {
var c api.Charger

func NewFromConfig(typ string, other map[string]interface{}) (charger api.Charger, err error) {
switch strings.ToLower(typ) {
case "default", "configurable":
c = NewConfigurableFromConfig(log, other)
charger, err = NewConfigurableFromConfig(other)
case "wallbe":
c = NewWallbeFromConfig(log, other)
charger, err = NewWallbeFromConfig(other)
case "phoenix-emcp":
c = NewPhoenixEMCPFromConfig(log, other)
charger, err = NewPhoenixEMCPFromConfig(other)
case "phoenix-evcc":
c = NewPhoenixEVCCFromConfig(log, other)
charger, err = NewPhoenixEVCCFromConfig(other)
case "nrgkick-bluetooth", "nrgkick-bt", "nrgble":
c = NewNRGKickBLEFromConfig(log, other)
charger, err = NewNRGKickBLEFromConfig(other)
case "nrgkick-connect", "nrgconnect":
c = NewNRGKickConnectFromConfig(log, other)
charger, err = NewNRGKickConnectFromConfig(other)
case "go-e", "goe":
c = NewGoEFromConfig(log, other)
charger, err = NewGoEFromConfig(other)
case "evsewifi":
c = NewEVSEWifiFromConfig(log, other)
charger, err = NewEVSEWifiFromConfig(other)
case "simpleevse", "evse":
c = NewSimpleEVSEFromConfig(log, other)
charger, err = NewSimpleEVSEFromConfig(other)
case "porsche", "audi", "bentley", "mcc":
c = NewMobileConnectFromConfig(log, other)
charger, err = NewMobileConnectFromConfig(other)
case "keba", "bmw":
c = NewKebaFromConfig(log, other)
charger, err = NewKebaFromConfig(other)
default:
log.FATAL.Fatalf("invalid charger type '%s'", typ)
return nil, fmt.Errorf("invalid charger type: %s", typ)
}

return c
return charger, err
}
10 changes: 6 additions & 4 deletions charger/evsewifi.go
Original file line number Diff line number Diff line change
@@ -50,21 +50,23 @@ type EVSEWifi struct {
}

// NewEVSEWifiFromConfig creates a EVSEWifi charger from generic config
func NewEVSEWifiFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewEVSEWifiFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct{ URI string }{}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

return NewEVSEWifi(cc.URI)
}

// NewEVSEWifi creates EVSEWifi charger
func NewEVSEWifi(uri string) api.Charger {
func NewEVSEWifi(uri string) (api.Charger, error) {
evse := &EVSEWifi{
HTTPHelper: util.NewHTTPHelper(util.NewLogger("wifi")),
uri: strings.TrimRight(uri, "/"),
}

return evse
return evse, nil
}

func (evse *EVSEWifi) apiURL(service apiFunction) string {
14 changes: 8 additions & 6 deletions charger/go-e.go
Original file line number Diff line number Diff line change
@@ -45,33 +45,35 @@ type GoE struct {
}

// NewGoEFromConfig creates a go-e charger from generic config
func NewGoEFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewGoEFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct {
Token string
URI string
Cache time.Duration
}{}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

if cc.URI != "" && cc.Token != "" {
log.FATAL.Fatal("config: should only have one of uri/token")
return nil, errors.New("go-e config: should only have one of uri/token")
}
if cc.URI == "" && cc.Token == "" {
log.FATAL.Fatal("config: must have one of uri/token")
return nil, errors.New("go-e config: must have one of uri/token")
}

return NewGoE(cc.URI, cc.Token, cc.Cache)
}

// NewGoE creates GoE charger
func NewGoE(uri, token string, cache time.Duration) *GoE {
func NewGoE(uri, token string, cache time.Duration) (*GoE, error) {
c := &GoE{
HTTPHelper: util.NewHTTPHelper(util.NewLogger("go-e")),
uri: strings.TrimRight(uri, "/"),
token: strings.TrimSpace(token),
}

return c
return c, nil
}

func (c *GoE) localResponse(function, payload string) (goeStatusResponse, error) {
6 changes: 5 additions & 1 deletion charger/go-e-test.go → charger/go-e_test.go
Original file line number Diff line number Diff line change
@@ -8,7 +8,11 @@ import (

// TestGoE tests interfaces
func TestGoE(t *testing.T) {
var wb api.Charger = NewGoE("foo", "bar", 0)
var wb api.Charger
wb, err := NewGoE("foo", "bar", 0)
if err != nil {
t.Error(err)
}

if _, ok := wb.(api.MeterCurrent); !ok {
t.Error("missing MeterCurrent interface")
10 changes: 6 additions & 4 deletions charger/keba.go
Original file line number Diff line number Diff line change
@@ -37,19 +37,21 @@ type Keba struct {
}

// NewKebaFromConfig creates a new configurable charger
func NewKebaFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewKebaFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct {
URI string
Timeout time.Duration
RFID RFID
}{}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

return NewKeba(cc.URI, cc.RFID, cc.Timeout)
}

// NewKeba creates a new charger
func NewKeba(conn string, rfid RFID, timeout time.Duration) api.Charger {
func NewKeba(conn string, rfid RFID, timeout time.Duration) (api.Charger, error) {
log := util.NewLogger("keba")

if keba.Instance == nil {
@@ -75,7 +77,7 @@ func NewKeba(conn string, rfid RFID, timeout time.Duration) api.Charger {

keba.Instance.Subscribe(conn, c.recv)

return c
return c, nil
}

func (c *Keba) send(msg string) error {
6 changes: 5 additions & 1 deletion charger/keba_test.go
Original file line number Diff line number Diff line change
@@ -7,7 +7,11 @@ import (
)

func TestKeba(t *testing.T) {
var wb api.Charger = NewKeba("foo", RFID{}, 0)
var wb api.Charger
wb, err := NewKeba("foo", RFID{}, 0)
if err != nil {
t.Error(err)
}

if _, ok := wb.(api.MeterEnergy); !ok {
t.Error("missing MeterEnergy interface")
12 changes: 7 additions & 5 deletions charger/mcc.go
Original file line number Diff line number Diff line change
@@ -68,17 +68,19 @@ type MobileConnect struct {
}

// NewMobileConnectFromConfig creates a MCC charger from generic config
func NewMobileConnectFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewMobileConnectFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct{ URI, Password string }{}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

return NewMobileConnect(cc.URI, cc.Password)
}

// NewMobileConnect creates MCC charger
func NewMobileConnect(uri string, password string) *MobileConnect {
func NewMobileConnect(uri string, password string) (*MobileConnect, error) {
mcc := &MobileConnect{
HTTPHelper: util.NewHTTPHelper(util.NewLogger("mcc ")),
HTTPHelper: util.NewHTTPHelper(util.NewLogger("mcc")),
uri: strings.TrimRight(uri, "/"),
password: password,
}
@@ -89,7 +91,7 @@ func NewMobileConnect(uri string, password string) *MobileConnect {

mcc.HTTPHelper.Client.Transport = customTransport

return mcc
return mcc, nil
}

// construct the URL for a given apiFunction
8 changes: 4 additions & 4 deletions charger/nrgble.go
Original file line number Diff line number Diff line change
@@ -3,12 +3,12 @@
package charger

import (
"errors"

"github.com/andig/evcc/api"
"github.com/andig/evcc/util"
)

// NewNRGKickBLEFromConfig creates a NRGKickBLE charger from generic config
func NewNRGKickBLEFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
log.FATAL.Fatal("config: NRGKick bluetooth is only supported on linux")
return nil
func NewNRGKickBLEFromConfig(other map[string]interface{}) (api.Charger, error) {
return nil, errors.New("NRGKick bluetooth is only supported on linux")
}
21 changes: 12 additions & 9 deletions charger/nrgble_linux.go
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package charger

import (
"bytes"
"errors"
"fmt"
"os"
"strconv"
@@ -35,23 +36,25 @@ type NRGKickBLE struct {
}

// NewNRGKickBLEFromConfig creates a NRGKickBLE charger from generic config
func NewNRGKickBLEFromConfig(log *util.Logger, other map[string]interface{}) api.Charger {
func NewNRGKickBLEFromConfig(other map[string]interface{}) (api.Charger, error) {
cc := struct{ Device, MacAddress, PIN string }{
Device: "hci0",
}
util.DecodeOther(log, other, &cc)
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}

// decode PIN with leading zero
pin, err := strconv.Atoi(cc.PIN)
if err != nil {
log.FATAL.Fatalf("config: invalid pin '%s'", cc.PIN)
return nil, errors.New("config: invalid pin '%s'", cc.PIN)
}

return NewNRGKickBLE(cc.Device, cc.MacAddress, pin)
}

// NewNRGKickBLE creates NRGKickBLE charger
func NewNRGKickBLE(device, macaddress string, pin int) *NRGKickBLE {
func NewNRGKickBLE(device, macaddress string, pin int) (*NRGKickBLE, error) {
logger := util.NewLogger("nrg-bt")

// set LE mode
@@ -73,18 +76,18 @@ func NewNRGKickBLE(device, macaddress string, pin int) *NRGKickBLE {
}

if err != nil {
logger.FATAL.Fatal(err)
return nil, err
}

adapt, err := adapter.NewAdapter1FromAdapterID(device)
if err != nil {
logger.FATAL.Fatal(err)
return nil, err
}

//Connect DBus System bus
conn, err := dbus.SystemBus()
if err != nil {
logger.FATAL.Fatal(err)
return nil, err
}

// do not reuse agent0 from service
@@ -93,7 +96,7 @@ func NewNRGKickBLE(device, macaddress string, pin int) *NRGKickBLE {
ag := agent.NewSimpleAgent()
err = agent.ExposeAgent(conn, ag, agent.CapNoInputNoOutput, true)
if err != nil {
logger.FATAL.Fatal(err)
return nil, err
}

nrg := &NRGKickBLE{
@@ -106,7 +109,7 @@ func NewNRGKickBLE(device, macaddress string, pin int) *NRGKickBLE {
agent: ag,
}

return nrg
return nrg, nil
}

func (nrg *NRGKickBLE) connect() (*device.Device1, error) {
Loading

0 comments on commit b1de095

Please sign in to comment.