From 1729399ef97c4d9750f5fcf34253c51c2af9c3f0 Mon Sep 17 00:00:00 2001 From: andig Date: Mon, 27 Apr 2020 18:49:04 +0200 Subject: [PATCH] Split common utility functions into util package (#64) --- charger/charger.go | 5 +- charger/config.go | 3 +- charger/evsewifi.go | 9 ++-- charger/go-e.go | 9 ++-- charger/mcc.go | 9 ++-- charger/mcc_test.go | 3 +- charger/nrgkick.go | 9 ++-- charger/phoenix.go | 9 ++-- charger/simpleevse.go | 9 ++-- charger/wallbe.go | 9 ++-- cmd/charger.go | 3 +- cmd/meter.go | 3 +- cmd/root.go | 19 ++----- cmd/setup.go | 4 +- cmd/vehicle.go | 3 +- core/loadpoint.go | 5 +- core/log.go | 4 +- core/wrapper/log.go | 4 +- meter/config.go | 3 +- meter/meter.go | 5 +- meter/sma.go | 9 ++-- meter/sma/listener.go | 6 +-- provider/cache.go | 6 +-- provider/config.go | 22 ++++---- provider/exec.go | 12 ++--- provider/modbus.go | 10 ++-- provider/mqtt.go | 12 ++--- provider/openwb.go | 5 +- push/config.go | 8 +-- push/event.go | 52 ------------------- push/hub.go | 13 +++++ server/influxdb.go | 6 +-- server/log.go | 4 +- {api => util}/decoder.go | 2 +- provider/helper.go => util/format.go | 16 +++--- .../helper_test.go => util/format_test.go | 10 ++-- {api => util}/http.go | 2 +- {api => util}/log.go | 12 ++++- vehicle/audi.go | 9 ++-- vehicle/bmw.go | 9 ++-- vehicle/config.go | 3 +- vehicle/nissan.go | 5 +- vehicle/tesla.go | 5 +- vehicle/vehicle.go | 5 +- 44 files changed, 177 insertions(+), 193 deletions(-) delete mode 100644 push/event.go rename {api => util}/decoder.go (97%) rename provider/helper.go => util/format.go (65%) rename provider/helper_test.go => util/format_test.go (81%) rename {api => util}/http.go (99%) rename {api => util}/log.go (83%) diff --git a/charger/charger.go b/charger/charger.go index b66d52967..5cd415755 100644 --- a/charger/charger.go +++ b/charger/charger.go @@ -3,6 +3,7 @@ package charger import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" ) // Charger is an api.Charger implementation with configurable getters and setters. @@ -14,9 +15,9 @@ type Charger struct { } // NewConfigurableFromConfig creates a new configurable charger -func NewConfigurableFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewConfigurableFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ Status, Enable, Enabled, MaxCurrent provider.Config }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) charger := NewConfigurable( provider.NewStringGetterFromConfig(log, cc.Status), diff --git a/charger/config.go b/charger/config.go index 8be76c685..349399781 100644 --- a/charger/config.go +++ b/charger/config.go @@ -4,12 +4,13 @@ import ( "strings" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) type apiFunction string // NewFromConfig creates charger from configuration -func NewFromConfig(log *api.Logger, typ string, other map[string]interface{}) api.Charger { +func NewFromConfig(log *util.Logger, typ string, other map[string]interface{}) api.Charger { var c api.Charger switch strings.ToLower(typ) { diff --git a/charger/evsewifi.go b/charger/evsewifi.go index 4633fb8a4..2ffe2a45d 100644 --- a/charger/evsewifi.go +++ b/charger/evsewifi.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -43,14 +44,14 @@ type EVSEListEntry struct { // EVSEWifi charger implementation type EVSEWifi struct { - *api.HTTPHelper + *util.HTTPHelper uri string } // NewEVSEWifiFromConfig creates a EVSEWifi charger from generic config -func NewEVSEWifiFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewEVSEWifiFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ URI string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewEVSEWifi(cc.URI) } @@ -58,7 +59,7 @@ func NewEVSEWifiFromConfig(log *api.Logger, other map[string]interface{}) api.Ch // NewEVSEWifi creates EVSEWifi charger func NewEVSEWifi(uri string) api.Charger { evse := &EVSEWifi{ - HTTPHelper: api.NewHTTPHelper(api.NewLogger("wifi")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("wifi")), uri: strings.TrimRight(uri, "/") + "/", } diff --git a/charger/go-e.go b/charger/go-e.go index 5eeab794d..6f2c7fe03 100644 --- a/charger/go-e.go +++ b/charger/go-e.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -26,14 +27,14 @@ type goeStatusResponse struct { // GoE charger implementation type GoE struct { - *api.HTTPHelper + *util.HTTPHelper uri string } // NewGoEFromConfig creates a go-e charger from generic config -func NewGoEFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewGoEFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ URI string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewGoE(cc.URI) } @@ -41,7 +42,7 @@ func NewGoEFromConfig(log *api.Logger, other map[string]interface{}) api.Charger // NewGoE creates GoE charger func NewGoE(URI string) *GoE { c := &GoE{ - HTTPHelper: api.NewHTTPHelper(api.NewLogger("go-e")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("go-e")), uri: strings.TrimRight(URI, "/"), } diff --git a/charger/mcc.go b/charger/mcc.go index dcc2f2bc7..98c65e26f 100644 --- a/charger/mcc.go +++ b/charger/mcc.go @@ -11,6 +11,7 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -56,7 +57,7 @@ type MCCCurrentCableInformation struct { // MobileConnect charger supporting devices from Audi, Bentley, Porsche type MobileConnect struct { - *api.HTTPHelper + *util.HTTPHelper uri string password string token string @@ -66,9 +67,9 @@ type MobileConnect struct { } // NewMobileConnectFromConfig creates a MCC charger from generic config -func NewMobileConnectFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewMobileConnectFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ URI, Password string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewMobileConnect(cc.URI, cc.Password) } @@ -76,7 +77,7 @@ func NewMobileConnectFromConfig(log *api.Logger, other map[string]interface{}) a // NewMobileConnect creates MCC charger func NewMobileConnect(uri string, password string) *MobileConnect { mcc := &MobileConnect{ - HTTPHelper: api.NewHTTPHelper(api.NewLogger("mcc ")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("mcc ")), uri: strings.TrimRight(uri, "/"), password: password, } diff --git a/charger/mcc_test.go b/charger/mcc_test.go index 769613528..69d4983de 100644 --- a/charger/mcc_test.go +++ b/charger/mcc_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) // HTTP testing appproach from http://hassansin.github.io/Unit-Testing-http-client-in-Go @@ -36,7 +37,7 @@ func NewTestClient(fn roundTripFunc) *http.Client { // NewTestMobileConnect . func NewTestMobileConnect(t *testing.T, responses []apiResponse) *MobileConnect { mcc := &MobileConnect{ - HTTPHelper: api.NewHTTPHelper(nil), + HTTPHelper: util.NewHTTPHelper(nil), uri: "http://192.168.1.1", password: "none", token: "token", diff --git a/charger/nrgkick.go b/charger/nrgkick.go index 56d6106cd..b33856924 100644 --- a/charger/nrgkick.go +++ b/charger/nrgkick.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -58,16 +59,16 @@ type NRGDeviceMetadata struct { // NRGKick charger implementation type NRGKick struct { - *api.HTTPHelper + *util.HTTPHelper IP string MacAddress string Password string } // NewNRGKickFromConfig creates a NRGKick charger from generic config -func NewNRGKickFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewNRGKickFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ IP, MacAddress, Password string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewNRGKick(cc.IP, cc.MacAddress, cc.Password) } @@ -75,7 +76,7 @@ func NewNRGKickFromConfig(log *api.Logger, other map[string]interface{}) api.Cha // NewNRGKick creates NRGKick charger func NewNRGKick(IP, MacAddress, Password string) *NRGKick { nrg := &NRGKick{ - HTTPHelper: api.NewHTTPHelper(api.NewLogger("kick")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("kick")), IP: IP, MacAddress: MacAddress, Password: Password, diff --git a/charger/phoenix.go b/charger/phoenix.go index dc44d8dfe..0b24467f3 100644 --- a/charger/phoenix.go +++ b/charger/phoenix.go @@ -5,6 +5,7 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/grid-x/modbus" ) @@ -18,22 +19,22 @@ const ( // Phoenix is an api.ChargeController implementation for Phoenix EM-CP-PP-ETH wallboxes. // It uses Modbus TCP to communicate with the wallbox at modbus client id 255. type Phoenix struct { - log *api.Logger + log *util.Logger client modbus.Client handler *modbus.TCPClientHandler } // NewPhoenixFromConfig creates a Phoenix charger from generic config -func NewPhoenixFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewPhoenixFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ URI string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewPhoenix(cc.URI) } // NewPhoenix creates a Phoenix charger func NewPhoenix(conn string) api.Charger { - log := api.NewLogger("phoe") + log := util.NewLogger("phoe") if conn == "" { log.FATAL.Fatal("missing connection") } diff --git a/charger/simpleevse.go b/charger/simpleevse.go index 8a5551950..c50642798 100644 --- a/charger/simpleevse.go +++ b/charger/simpleevse.go @@ -5,12 +5,13 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/grid-x/modbus" ) // SimpleEVSE charger implementation type SimpleEVSE struct { - log *api.Logger + log *util.Logger client modbus.Client handler modbus.ClientHandler } @@ -22,16 +23,16 @@ const ( ) // NewSimpleEVSEFromConfig creates a SimpleEVSE charger from generic config -func NewSimpleEVSEFromConfig(log *api.Logger, other map[string]interface{}) api.Charger { +func NewSimpleEVSEFromConfig(log *util.Logger, other map[string]interface{}) api.Charger { cc := struct{ URI, Device string }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewSimpleEVSE(cc.URI, cc.Device) } // NewSimpleEVSE creates SimpleEVSE charger func NewSimpleEVSE(conn, device string) api.Charger { - log := api.NewLogger("evse") + log := util.NewLogger("evse") var handler modbus.ClientHandler if conn != "" && device != "" { diff --git a/charger/wallbe.go b/charger/wallbe.go index bfd3fddd8..7a66edc26 100644 --- a/charger/wallbe.go +++ b/charger/wallbe.go @@ -6,6 +6,7 @@ import ( "time" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/grid-x/modbus" ) @@ -27,19 +28,19 @@ const ( // Phoenix EV-CC-AC1-M3-CBC-RCM-ETH controller. // It uses Modbus TCP to communicate with the wallbox at modbus client id 255. type Wallbe struct { - log *api.Logger + log *util.Logger client modbus.Client handler *modbus.TCPClientHandler factor int64 } // NewWallbeFromConfig creates a Wallbe charger from generic config -func NewWallbeFromConfig(log *api.Logger, other map[string]interface{}) *Wallbe { +func NewWallbeFromConfig(log *util.Logger, other map[string]interface{}) *Wallbe { cc := struct { URI string Legacy bool }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) wb := NewWallbe(cc.URI) @@ -64,7 +65,7 @@ func NewWallbe(conn string) *Wallbe { handler.ProtocolRecoveryTimeout = protocolTimeout wb := &Wallbe{ - log: api.NewLogger("wlbe"), + log: util.NewLogger("wlbe"), client: client, handler: handler, factor: 10, diff --git a/cmd/charger.go b/cmd/charger.go index 90fb61e46..6c1b95736 100644 --- a/cmd/charger.go +++ b/cmd/charger.go @@ -6,6 +6,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" "github.com/andig/evcc/server" + "github.com/andig/evcc/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -22,7 +23,7 @@ func init() { } func runCharger(cmd *cobra.Command, args []string) { - configureLogging() + util.LogLevel(viper.GetString("log")) log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit) // load config diff --git a/cmd/meter.go b/cmd/meter.go index 17bf48459..244d4c7f8 100644 --- a/cmd/meter.go +++ b/cmd/meter.go @@ -6,6 +6,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" "github.com/andig/evcc/server" + "github.com/andig/evcc/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -22,7 +23,7 @@ func init() { } func runMeter(cmd *cobra.Command, args []string) { - configureLogging() + util.LogLevel(viper.GetString("log")) log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit) // load config diff --git a/cmd/root.go b/cmd/root.go index 260f77e7b..89ee781d3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,10 +5,10 @@ import ( "os" "time" - "github.com/andig/evcc/api" "github.com/andig/evcc/core" "github.com/andig/evcc/provider" "github.com/andig/evcc/server" + "github.com/andig/evcc/util" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -16,7 +16,7 @@ import ( ) var ( - log = api.NewLogger("main") + log = util.NewLogger("main") cfgFile string ) @@ -114,17 +114,6 @@ func Execute() { } } -func configureLogging() { - level := viper.GetString("log") - - api.OutThreshold = api.LogLevelToThreshold(level) - api.LogThreshold = api.OutThreshold - - api.Loggers(func(name string, logger *api.Logger) { - logger.SetStdoutThreshold(api.OutThreshold) - }) -} - // checkVersion validates if updates are available func checkVersion() { githubTag := &latest.GithubTag{ @@ -161,12 +150,12 @@ func tee(in chan core.Param) (chan core.Param, <-chan core.Param) { } func run(cmd *cobra.Command, args []string) { - configureLogging() + util.LogLevel(viper.GetString("log")) log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit) // load config and re-configure logging after reading config file conf := loadConfigFile(cfgFile) - configureLogging() + util.LogLevel(viper.GetString("log")) go checkVersion() diff --git a/cmd/setup.go b/cmd/setup.go index e690c88c5..feac9fdbe 100644 --- a/cmd/setup.go +++ b/cmd/setup.go @@ -5,9 +5,9 @@ import ( "math/rand" "time" - "github.com/andig/evcc/api" "github.com/andig/evcc/core" "github.com/andig/evcc/push" + "github.com/andig/evcc/util" "github.com/spf13/viper" ) @@ -46,7 +46,7 @@ func loadConfig(conf config, eventsChan chan push.Event) (loadPoints []*core.Loa // decode slice into slice of maps var lpm []map[string]interface{} - api.DecodeOther(log, lps, &lpm) + util.DecodeOther(log, lps, &lpm) for _, lpc := range lpm { lp := core.NewLoadPointFromConfig(log, cp, lpc) diff --git a/cmd/vehicle.go b/cmd/vehicle.go index 113226449..c6b0323cc 100644 --- a/cmd/vehicle.go +++ b/cmd/vehicle.go @@ -6,6 +6,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" "github.com/andig/evcc/server" + "github.com/andig/evcc/util" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -22,7 +23,7 @@ func init() { } func runVehicle(cmd *cobra.Command, args []string) { - configureLogging() + util.LogLevel(viper.GetString("log")) log.INFO.Printf("evcc %s (%s)", server.Version, server.Commit) // load config diff --git a/core/loadpoint.go b/core/loadpoint.go index a53c48056..f2d4dbb77 100644 --- a/core/loadpoint.go +++ b/core/loadpoint.go @@ -9,6 +9,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/core/wrapper" "github.com/andig/evcc/push" + "github.com/andig/evcc/util" "github.com/pkg/errors" evbus "github.com/asaskevich/EventBus" @@ -98,9 +99,9 @@ type configProvider interface { } // NewLoadPointFromConfig creates a new loadpoint -func NewLoadPointFromConfig(log *api.Logger, cp configProvider, other map[string]interface{}) *LoadPoint { +func NewLoadPointFromConfig(log *util.Logger, cp configProvider, other map[string]interface{}) *LoadPoint { lp := NewLoadPoint() - api.DecodeOther(log, other, &lp) + util.DecodeOther(log, other, &lp) if lp.ChargerRef != "" { lp.charger = cp.Charger(lp.ChargerRef) diff --git a/core/log.go b/core/log.go index 79b09e745..a38ced6d3 100644 --- a/core/log.go +++ b/core/log.go @@ -1,5 +1,5 @@ package core -import "github.com/andig/evcc/api" +import "github.com/andig/evcc/util" -var log = api.NewLogger("load") +var log = util.NewLogger("load") diff --git a/core/wrapper/log.go b/core/wrapper/log.go index e74424c2b..6e9017896 100644 --- a/core/wrapper/log.go +++ b/core/wrapper/log.go @@ -1,5 +1,5 @@ package wrapper -import "github.com/andig/evcc/api" +import "github.com/andig/evcc/util" -var log = api.NewLogger("wrap") +var log = util.NewLogger("wrap") diff --git a/meter/config.go b/meter/config.go index 568d9ae1d..6a70cbf6d 100644 --- a/meter/config.go +++ b/meter/config.go @@ -4,10 +4,11 @@ import ( "strings" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) // NewFromConfig creates meter from configuration -func NewFromConfig(log *api.Logger, typ string, other map[string]interface{}) api.Meter { +func NewFromConfig(log *util.Logger, typ string, other map[string]interface{}) api.Meter { var c api.Meter switch strings.ToLower(typ) { diff --git a/meter/meter.go b/meter/meter.go index cad10614a..5745c537f 100644 --- a/meter/meter.go +++ b/meter/meter.go @@ -3,6 +3,7 @@ package meter import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" ) // CompositeMeter decorates a Meter with MeterEnergy. @@ -12,12 +13,12 @@ type CompositeMeter struct { } // NewConfigurableFromConfig creates api.Meter from config -func NewConfigurableFromConfig(log *api.Logger, other map[string]interface{}) api.Meter { +func NewConfigurableFromConfig(log *util.Logger, other map[string]interface{}) api.Meter { cc := struct { Power provider.Config Energy *provider.Config // optional }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) m := NewConfigurable(provider.NewFloatGetterFromConfig(log, cc.Power)) diff --git a/meter/sma.go b/meter/sma.go index 7d9002302..304160edc 100644 --- a/meter/sma.go +++ b/meter/sma.go @@ -7,6 +7,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/meter/sma" + "github.com/andig/evcc/util" ) const ( @@ -16,7 +17,7 @@ const ( // SMA supporting SMA Home Manager 2.0 and SMA Energy Meter 30 type SMA struct { - log *api.Logger + log *util.Logger uri string power float64 updated time.Time @@ -26,18 +27,18 @@ type SMA struct { } // NewSMAFromConfig creates a SMA Meter from generic config -func NewSMAFromConfig(log *api.Logger, other map[string]interface{}) api.Meter { +func NewSMAFromConfig(log *util.Logger, other map[string]interface{}) api.Meter { sm := struct { URI string }{} - api.DecodeOther(log, other, &sm) + util.DecodeOther(log, other, &sm) return NewSMA(sm.URI) } // NewSMA creates a SMA Meter func NewSMA(uri string) *SMA { - log := api.NewLogger("sma ") + log := util.NewLogger("sma ") sm := &SMA{ log: log, diff --git a/meter/sma/listener.go b/meter/sma/listener.go index a3bf6e563..e63c12ec8 100644 --- a/meter/sma/listener.go +++ b/meter/sma/listener.go @@ -8,7 +8,7 @@ import ( "strconv" "sync" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -85,13 +85,13 @@ type Telegram struct { // Listener for receiving SMA multicast data packages type Listener struct { mux sync.Mutex - log *api.Logger + log *util.Logger conn *net.UDPConn clients map[string]chan<- Telegram } // New creates a Listener -func New(log *api.Logger, addr string) *Listener { +func New(log *util.Logger, addr string) *Listener { // Parse the string address gaddr, err := net.ResolveUDPAddr("udp4", multicastAddr) if err != nil { diff --git a/provider/cache.go b/provider/cache.go index 026420766..e77c4ceb9 100644 --- a/provider/cache.go +++ b/provider/cache.go @@ -3,13 +3,13 @@ package provider import ( "time" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/benbjohnson/clock" ) // Cached wraps a getter with a cache type Cached struct { - log *api.Logger + log *util.Logger clock clock.Clock updated time.Time cache time.Duration @@ -18,7 +18,7 @@ type Cached struct { } // NewCached wraps a getter with a cache -func NewCached(log *api.Logger, getter interface{}, cache time.Duration) *Cached { +func NewCached(log *util.Logger, getter interface{}, cache time.Duration) *Cached { return &Cached{ log: log, clock: clock.New(), diff --git a/provider/config.go b/provider/config.go index b5685039b..00c428c3a 100644 --- a/provider/config.go +++ b/provider/config.go @@ -4,7 +4,7 @@ import ( "strings" "time" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) const ( @@ -34,13 +34,13 @@ type scriptConfig struct { // MQTT singleton var MQTT *MqttClient -func mqttFromConfig(log *api.Logger, other map[string]interface{}) mqttConfig { +func mqttFromConfig(log *util.Logger, other map[string]interface{}) mqttConfig { if MQTT == nil { log.FATAL.Fatal("mqtt not configured") } var pc mqttConfig - api.DecodeOther(log, other, &pc) + util.DecodeOther(log, other, &pc) if pc.Multiplier == 0 { pc.Multiplier = 1 @@ -49,9 +49,9 @@ func mqttFromConfig(log *api.Logger, other map[string]interface{}) mqttConfig { return pc } -func scriptFromConfig(log *api.Logger, other map[string]interface{}) scriptConfig { +func scriptFromConfig(log *util.Logger, other map[string]interface{}) scriptConfig { var pc scriptConfig - api.DecodeOther(log, other, &pc) + util.DecodeOther(log, other, &pc) if pc.Timeout == 0 { pc.Timeout = execTimeout @@ -61,7 +61,7 @@ func scriptFromConfig(log *api.Logger, other map[string]interface{}) scriptConfi } // NewFloatGetterFromConfig creates a FloatGetter from config -func NewFloatGetterFromConfig(log *api.Logger, config Config) (res FloatGetter) { +func NewFloatGetterFromConfig(log *util.Logger, config Config) (res FloatGetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) @@ -82,7 +82,7 @@ func NewFloatGetterFromConfig(log *api.Logger, config Config) (res FloatGetter) } // NewIntGetterFromConfig creates a IntGetter from config -func NewIntGetterFromConfig(log *api.Logger, config Config) (res IntGetter) { +func NewIntGetterFromConfig(log *util.Logger, config Config) (res IntGetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) @@ -103,7 +103,7 @@ func NewIntGetterFromConfig(log *api.Logger, config Config) (res IntGetter) { } // NewStringGetterFromConfig creates a StringGetter from config -func NewStringGetterFromConfig(log *api.Logger, config Config) (res StringGetter) { +func NewStringGetterFromConfig(log *util.Logger, config Config) (res StringGetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) @@ -124,7 +124,7 @@ func NewStringGetterFromConfig(log *api.Logger, config Config) (res StringGetter } // NewBoolGetterFromConfig creates a BoolGetter from config -func NewBoolGetterFromConfig(log *api.Logger, config Config) (res BoolGetter) { +func NewBoolGetterFromConfig(log *util.Logger, config Config) (res BoolGetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) @@ -143,7 +143,7 @@ func NewBoolGetterFromConfig(log *api.Logger, config Config) (res BoolGetter) { } // NewIntSetterFromConfig creates a IntSetter from config -func NewIntSetterFromConfig(log *api.Logger, param string, config Config) (res IntSetter) { +func NewIntSetterFromConfig(log *util.Logger, param string, config Config) (res IntSetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) @@ -159,7 +159,7 @@ func NewIntSetterFromConfig(log *api.Logger, param string, config Config) (res I } // NewBoolSetterFromConfig creates a BoolSetter from config -func NewBoolSetterFromConfig(log *api.Logger, param string, config Config) (res BoolSetter) { +func NewBoolSetterFromConfig(log *util.Logger, param string, config Config) (res BoolSetter) { switch strings.ToLower(config.Type) { case "mqtt": pc := mqttFromConfig(log, config.Other) diff --git a/provider/exec.go b/provider/exec.go index 15a47d104..88698ba64 100644 --- a/provider/exec.go +++ b/provider/exec.go @@ -8,13 +8,13 @@ import ( "strings" "time" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/kballard/go-shellquote" ) // Script implements shell script-based providers and setters type Script struct { - log *api.Logger + log *util.Logger timeout time.Duration } @@ -22,7 +22,7 @@ type Script struct { // Script execution is aborted after given timeout. func NewScriptProvider(timeout time.Duration) *Script { return &Script{ - log: api.NewLogger("exec"), + log: util.NewLogger("exec"), timeout: timeout, } } @@ -103,7 +103,7 @@ func (e *Script) BoolGetter(script string) BoolGetter { return false, err } - return truish(s), nil + return util.Truish(s), nil } } @@ -111,7 +111,7 @@ func (e *Script) BoolGetter(script string) BoolGetter { func (e *Script) IntSetter(param, script string) IntSetter { // return func to access cached value return func(i int64) error { - cmd, err := replaceFormatted(script, map[string]interface{}{ + cmd, err := util.ReplaceFormatted(script, map[string]interface{}{ param: i, }) if err != nil { @@ -131,7 +131,7 @@ func (e *Script) IntSetter(param, script string) IntSetter { func (e *Script) BoolSetter(param, script string) BoolSetter { // return func to access cached value return func(b bool) error { - cmd, err := replaceFormatted(script, map[string]interface{}{ + cmd, err := util.ReplaceFormatted(script, map[string]interface{}{ param: b, }) if err != nil { diff --git a/provider/modbus.go b/provider/modbus.go index a50a26246..8a2be0bb5 100644 --- a/provider/modbus.go +++ b/provider/modbus.go @@ -4,7 +4,7 @@ import ( "math" "strings" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" "github.com/volkszaehler/mbmd/meters" "github.com/volkszaehler/mbmd/meters/rs485" "github.com/volkszaehler/mbmd/meters/sunspec" @@ -12,7 +12,7 @@ import ( // Modbus implements modbus RTU and TCP access type Modbus struct { - log *api.Logger + log *util.Logger conn meters.Connection device meters.Device slaveID uint8 @@ -35,14 +35,14 @@ func modbusConnection(key string, newConn meters.Connection) meters.Connection { } // NewModbusFromConfig creates Modbus plugin -func NewModbusFromConfig(log *api.Logger, typ string, other map[string]interface{}) *Modbus { +func NewModbusFromConfig(log *util.Logger, typ string, other map[string]interface{}) *Modbus { cc := struct { URI, Device, Comset string Meter, Value string Baudrate int ID uint8 }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) var conn meters.Connection var device meters.Device @@ -62,7 +62,7 @@ func NewModbusFromConfig(log *api.Logger, typ string, other map[string]interface log.FATAL.Fatalf("invalid provider type %s", typ) } - log = api.NewLogger("modb") + log = util.NewLogger("modb") conn.Logger(log.TRACE) // prepare device diff --git a/provider/mqtt.go b/provider/mqtt.go index 5e0ec2c58..966dbfef1 100644 --- a/provider/mqtt.go +++ b/provider/mqtt.go @@ -7,7 +7,7 @@ import ( "sync" "time" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" mqtt "github.com/eclipse/paho.mqtt.golang" ) @@ -18,7 +18,7 @@ const ( // MqttClient is a paho publisher type MqttClient struct { - log *api.Logger + log *util.Logger mux sync.Mutex Client mqtt.Client broker string @@ -34,7 +34,7 @@ func NewMqttClient( clientID string, qos byte, ) *MqttClient { - log := api.NewLogger("mqtt") + log := util.NewLogger("mqtt") log.INFO.Printf("connecting %s at %s", clientID, broker) mc := &MqttClient{ @@ -160,7 +160,7 @@ func (m *MqttClient) formatValue(param, message string, v interface{}) (string, return fmt.Sprintf("%v", v), nil } - return replaceFormatted(message, map[string]interface{}{ + return util.ReplaceFormatted(message, map[string]interface{}{ param: v, }) } @@ -213,7 +213,7 @@ func (m *MqttClient) WaitForToken(token mqtt.Token) { } type msgHandler struct { - log *api.Logger + log *util.Logger once sync.Once mux sync.Mutex updated time.Time @@ -292,5 +292,5 @@ func (h *msgHandler) boolGetter() (bool, error) { return false, fmt.Errorf("%s outdated: %v", h.topic, elapsed.Truncate(time.Second)) } - return truish(string(h.payload)), nil + return util.Truish(string(h.payload)), nil } diff --git a/provider/openwb.go b/provider/openwb.go index e67d4094e..f43bd683b 100644 --- a/provider/openwb.go +++ b/provider/openwb.go @@ -2,17 +2,18 @@ package provider import ( "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) type openWBStatusProvider struct { plugged, charging BoolGetter } -func openWBStatusFromConfig(log *api.Logger, other map[string]interface{}) StringGetter { +func openWBStatusFromConfig(log *util.Logger, other map[string]interface{}) StringGetter { cc := struct { Plugged, Charging Config }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) o := &openWBStatusProvider{ plugged: NewBoolGetterFromConfig(log, cc.Plugged), diff --git a/push/config.go b/push/config.go index 225051691..c555cdd17 100644 --- a/push/config.go +++ b/push/config.go @@ -3,7 +3,7 @@ package push import ( "strings" - "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) // Sender implements message sending @@ -16,18 +16,18 @@ type EventTemplate struct { Title, Msg string } -var log = api.NewLogger("push") +var log = util.NewLogger("push") // NewMessengerFromConfig creates a new messenger func NewMessengerFromConfig(typ string, other map[string]interface{}) Sender { switch strings.ToLower(typ) { case "pushover": var cc pushOverConfig - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewPushOverMessenger(cc.App, cc.Recipients) case "telegram": var cc telegramConfig - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) return NewTelegramMessenger(cc.Token, cc.Chats) } diff --git a/push/event.go b/push/event.go deleted file mode 100644 index 6a9c4b65b..000000000 --- a/push/event.go +++ /dev/null @@ -1,52 +0,0 @@ -package push - -import ( - "errors" - "fmt" - "regexp" - "strings" -) - -// Event is a notification event -type Event struct { - Event string - Attributes map[string]interface{} -} - -// apply applies the event template to the content to produce the actual message -func (e Event) apply(template string) (string, error) { - return replaceFormatted(template, e.Attributes) -} - -var re = regexp.MustCompile(`\${(\w+)(:([a-zA-Z0-9%.]+))?}`) - -// replaceFormatted replaces all occurrances of ${key} with val from the kv map. -// All keys of kv must exist inside the string to apply replacements to -func replaceFormatted(s string, kv map[string]interface{}) (string, error) { - matches := re.FindAllStringSubmatch(s, -1) - - for len(matches) > 0 { - for _, m := range matches { - key := m[1] - val, ok := kv[key] - if !ok { - return "", errors.New("could not find match for " + m[0]) - } - - // apply format - format := m[3] - if format != "" { - val = fmt.Sprintf(format, val) - } - - // update string - literalMatch := m[0] - s = strings.ReplaceAll(s, literalMatch, fmt.Sprintf("%v", val)) - } - - // update matches - matches = re.FindAllStringSubmatch(s, -1) - } - - return s, nil -} diff --git a/push/hub.go b/push/hub.go index cd1a31cdd..e43263a8b 100644 --- a/push/hub.go +++ b/push/hub.go @@ -1,5 +1,18 @@ package push +import "github.com/andig/evcc/util" + +// Event is a notification event +type Event struct { + Event string + Attributes map[string]interface{} +} + +// apply applies the event template to the content to produce the actual message +func (e Event) apply(template string) (string, error) { + return util.ReplaceFormatted(template, e.Attributes) +} + // Hub subscribes to event notifications and sends them to client devices type Hub struct { definitions map[string]EventTemplate diff --git a/server/influxdb.go b/server/influxdb.go index 027ca00d5..36473016b 100644 --- a/server/influxdb.go +++ b/server/influxdb.go @@ -4,8 +4,8 @@ import ( "sync" "time" - "github.com/andig/evcc/api" "github.com/andig/evcc/core" + "github.com/andig/evcc/util" influxdb "github.com/influxdata/influxdb1-client/v2" ) @@ -18,7 +18,7 @@ const ( // Influx is a influx publisher type Influx struct { sync.Mutex - log *api.Logger + log *util.Logger client influxdb.Client points []*influxdb.Point pointsConf influxdb.BatchPointsConfig @@ -33,7 +33,7 @@ func NewInfluxClient( user string, password string, ) *Influx { - log := api.NewLogger("iflx") + log := util.NewLogger("iflx") if database == "" { log.FATAL.Fatal("missing database") diff --git a/server/log.go b/server/log.go index 9e4cff19c..01e6f6be8 100644 --- a/server/log.go +++ b/server/log.go @@ -1,5 +1,5 @@ package server -import "github.com/andig/evcc/api" +import "github.com/andig/evcc/util" -var log = api.NewLogger("srvr") +var log = util.NewLogger("srvr") diff --git a/api/decoder.go b/util/decoder.go similarity index 97% rename from api/decoder.go rename to util/decoder.go index 395cdb989..ad30e9271 100644 --- a/api/decoder.go +++ b/util/decoder.go @@ -1,4 +1,4 @@ -package api +package util import ( "github.com/mitchellh/mapstructure" diff --git a/provider/helper.go b/util/format.go similarity index 65% rename from provider/helper.go rename to util/format.go index 8c015ec84..9042b66b4 100644 --- a/provider/helper.go +++ b/util/format.go @@ -1,4 +1,4 @@ -package provider +package util import ( "errors" @@ -9,13 +9,13 @@ import ( var re = regexp.MustCompile(`\${(\w+)(:([a-zA-Z0-9%.]+))?}`) -// truish returns true if value is truish (true/1/on) -func truish(s string) bool { +// Truish returns true if value is truish (true/1/on) +func Truish(s string) bool { return s == "1" || strings.ToLower(s) == "true" || strings.ToLower(s) == "on" } -// formatValue will apply specific formatting in addition to standard sprintf -func formatValue(format string, val interface{}) string { +// FormatValue will apply specific formatting in addition to standard sprintf +func FormatValue(format string, val interface{}) string { switch val := val.(type) { case bool: if format == "%d" { @@ -33,8 +33,8 @@ func formatValue(format string, val interface{}) string { return fmt.Sprintf(format, val) } -// replaceFormatted replaces all occurrences of ${key} with formatted val from the kv map -func replaceFormatted(s string, kv map[string]interface{}) (string, error) { +// ReplaceFormatted replaces all occurrences of ${key} with formatted val from the kv map +func ReplaceFormatted(s string, kv map[string]interface{}) (string, error) { for m := re.FindStringSubmatch(s); m != nil; m = re.FindStringSubmatch(s) { // find key and replacement value val, ok := kv[m[1]] @@ -43,7 +43,7 @@ func replaceFormatted(s string, kv map[string]interface{}) (string, error) { } // update all literal matches - new := formatValue(m[3], val) + new := FormatValue(m[3], val) s = strings.ReplaceAll(s, m[0], new) } diff --git a/provider/helper_test.go b/util/format_test.go similarity index 81% rename from provider/helper_test.go rename to util/format_test.go index baa387bf9..e8085c2ae 100644 --- a/provider/helper_test.go +++ b/util/format_test.go @@ -1,4 +1,4 @@ -package provider +package util import ( "math" @@ -20,7 +20,7 @@ func TestTruish(t *testing.T) { } for _, c := range cases { - b := truish(c.k) + b := Truish(c.k) if b != c.v { t.Errorf("expected %v got %v", c.v, b) } @@ -39,7 +39,7 @@ func TestReplace(t *testing.T) { } for _, c := range cases { - s, err := replaceFormatted(c.fmt, map[string]interface{}{ + s, err := ReplaceFormatted(c.fmt, map[string]interface{}{ c.k: c.v, }) @@ -50,7 +50,7 @@ func TestReplace(t *testing.T) { } func TestReplaceMulti(t *testing.T) { - s, err := replaceFormatted("${foo}-${bar}", map[string]interface{}{ + s, err := ReplaceFormatted("${foo}-${bar}", map[string]interface{}{ "foo": "bar", "bar": "baz", }) @@ -61,7 +61,7 @@ func TestReplaceMulti(t *testing.T) { } func TestReplaceNoMatch(t *testing.T) { - s, err := replaceFormatted("${foo}", map[string]interface{}{ + s, err := ReplaceFormatted("${foo}", map[string]interface{}{ "bar": "baz", }) diff --git a/api/http.go b/util/http.go similarity index 99% rename from api/http.go rename to util/http.go index ec312451a..f1d30af77 100644 --- a/api/http.go +++ b/util/http.go @@ -1,4 +1,4 @@ -package api +package util import ( "bytes" diff --git a/api/log.go b/util/log.go similarity index 83% rename from api/log.go rename to util/log.go index ac3d61e41..3b66129b8 100644 --- a/api/log.go +++ b/util/log.go @@ -1,4 +1,4 @@ -package api +package util import ( "io/ioutil" @@ -39,6 +39,16 @@ func Loggers(cb func(string, *Logger)) { } } +// LogLevel sets log level for all loggers +func LogLevel(level string) { + OutThreshold = LogLevelToThreshold(level) + LogThreshold = OutThreshold + + Loggers(func(name string, logger *Logger) { + logger.SetStdoutThreshold(OutThreshold) + }) +} + // LogLevelToThreshold converts log level string to a jww Threshold func LogLevelToThreshold(level string) jww.Threshold { switch strings.ToUpper(level) { diff --git a/vehicle/audi.go b/vehicle/audi.go index 1d28b871f..62ddeca45 100644 --- a/vehicle/audi.go +++ b/vehicle/audi.go @@ -11,6 +11,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" ) const ( @@ -45,7 +46,7 @@ type audiBatteryResponse struct { // Audi is an api.Vehicle implementation for Audi cars type Audi struct { *embed - *api.HTTPHelper + *util.HTTPHelper user, password, vin string token string tokenValid time.Time @@ -53,18 +54,18 @@ type Audi struct { } // NewAudiFromConfig creates a new vehicle -func NewAudiFromConfig(log *api.Logger, other map[string]interface{}) api.Vehicle { +func NewAudiFromConfig(log *util.Logger, other map[string]interface{}) api.Vehicle { cc := struct { Title string Capacity int64 User, Password, VIN string Cache time.Duration }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) v := &Audi{ embed: &embed{cc.Title, cc.Capacity}, - HTTPHelper: api.NewHTTPHelper(api.NewLogger("audi")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("audi")), user: cc.User, password: cc.Password, vin: cc.VIN, diff --git a/vehicle/bmw.go b/vehicle/bmw.go index 3710bbaa4..858e1c929 100644 --- a/vehicle/bmw.go +++ b/vehicle/bmw.go @@ -11,6 +11,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" ) const ( @@ -27,7 +28,7 @@ type bmwDynamicResponse struct { // BMW is an api.Vehicle implementation for BMW cars type BMW struct { *embed - *api.HTTPHelper + *util.HTTPHelper user, password, vin string token string tokenValid time.Time @@ -35,18 +36,18 @@ type BMW struct { } // NewBMWFromConfig creates a new vehicle -func NewBMWFromConfig(log *api.Logger, other map[string]interface{}) api.Vehicle { +func NewBMWFromConfig(log *util.Logger, other map[string]interface{}) api.Vehicle { cc := struct { Title string Capacity int64 User, Password, VIN string Cache time.Duration }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) v := &BMW{ embed: &embed{cc.Title, cc.Capacity}, - HTTPHelper: api.NewHTTPHelper(api.NewLogger("bmw ")), + HTTPHelper: util.NewHTTPHelper(util.NewLogger("bmw ")), user: cc.User, password: cc.Password, vin: cc.VIN, diff --git a/vehicle/config.go b/vehicle/config.go index 4c2a936fd..4959f86f9 100644 --- a/vehicle/config.go +++ b/vehicle/config.go @@ -4,10 +4,11 @@ import ( "strings" "github.com/andig/evcc/api" + "github.com/andig/evcc/util" ) // NewFromConfig creates vehicle from configuration -func NewFromConfig(log *api.Logger, typ string, other map[string]interface{}) api.Vehicle { +func NewFromConfig(log *util.Logger, typ string, other map[string]interface{}) api.Vehicle { var c api.Vehicle switch strings.ToLower(typ) { diff --git a/vehicle/nissan.go b/vehicle/nissan.go index 5cbafa21b..53c4a18c5 100644 --- a/vehicle/nissan.go +++ b/vehicle/nissan.go @@ -5,6 +5,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" "github.com/joeshaw/carwings" ) @@ -17,14 +18,14 @@ type Nissan struct { } // NewNissanFromConfig creates a new vehicle -func NewNissanFromConfig(log *api.Logger, other map[string]interface{}) api.Vehicle { +func NewNissanFromConfig(log *util.Logger, other map[string]interface{}) api.Vehicle { cc := struct { Title string Capacity int64 User, Password, Region string Cache time.Duration }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) if cc.Region == "" { cc.Region = carwings.RegionEurope diff --git a/vehicle/tesla.go b/vehicle/tesla.go index 888fb383e..e2ca03f99 100644 --- a/vehicle/tesla.go +++ b/vehicle/tesla.go @@ -5,6 +5,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" "github.com/jsgoecke/tesla" ) @@ -17,7 +18,7 @@ type Tesla struct { } // NewTeslaFromConfig creates a new Tesla vehicle -func NewTeslaFromConfig(log *api.Logger, other map[string]interface{}) api.Vehicle { +func NewTeslaFromConfig(log *util.Logger, other map[string]interface{}) api.Vehicle { cc := struct { Title string Capacity int64 @@ -26,7 +27,7 @@ func NewTeslaFromConfig(log *api.Logger, other map[string]interface{}) api.Vehic VIN string Cache time.Duration }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) client, err := tesla.NewClient(&tesla.Auth{ ClientID: cc.ClientID, diff --git a/vehicle/vehicle.go b/vehicle/vehicle.go index dc834e33f..7665a0d94 100644 --- a/vehicle/vehicle.go +++ b/vehicle/vehicle.go @@ -5,6 +5,7 @@ import ( "github.com/andig/evcc/api" "github.com/andig/evcc/provider" + "github.com/andig/evcc/util" ) type embed struct { @@ -29,14 +30,14 @@ type Vehicle struct { } // NewConfigurableFromConfig creates a new Vehicle -func NewConfigurableFromConfig(log *api.Logger, other map[string]interface{}) api.Vehicle { +func NewConfigurableFromConfig(log *util.Logger, other map[string]interface{}) api.Vehicle { cc := struct { Title string Capacity int64 Charge provider.Config Cache time.Duration }{} - api.DecodeOther(log, other, &cc) + util.DecodeOther(log, other, &cc) getter := provider.NewFloatGetterFromConfig(log, cc.Charge) if cc.Cache > 0 {