From f79b8a164df3f6f0c72a09afc3a875c2a75c44b5 Mon Sep 17 00:00:00 2001 From: andig Date: Tue, 15 Mar 2022 21:43:54 +0000 Subject: [PATCH] LG ESS: cleanup code and require paramters on all instantiations --- meter/lgpcs/lgpcs.go | 45 ++++++++++++++++++++++---------------------- util/net.go | 3 +++ util/net_test.go | 7 +++++++ 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/meter/lgpcs/lgpcs.go b/meter/lgpcs/lgpcs.go index 871acee5c..f3f8eaecf 100644 --- a/meter/lgpcs/lgpcs.go +++ b/meter/lgpcs/lgpcs.go @@ -47,58 +47,57 @@ type Com struct { cachedData func() (interface{}, error) } -var once sync.Once -var instance *Com +var ( + once sync.Once + mu sync.Mutex + instance *Com +) // GetInstance implements the singleton pattern to handle the access via the authkey to the PCS of the LG ESS HOME system func GetInstance(uri, password string, cache time.Duration) (*Com, error) { - const emptyUri = "https:" uri = util.DefaultScheme(strings.TrimSuffix(uri, "/"), "https") + var err error once.Do(func() { log := util.NewLogger("lgess") - instance = &Com{ + inst := &Com{ Helper: request.NewHelper(log), uri: uri, password: password, } // ignore the self signed certificate - instance.Client.Transport = request.NewTripper(log, transport.Insecure()) + inst.Client.Transport = request.NewTripper(log, transport.Insecure()) // caches the data access for the "cache" time duration // sends a new request to the pcs if the cache is expired and Data() requested - instance.cachedData = provider.NewCached(func() (interface{}, error) { - return instance.refreshData() + inst.cachedData = provider.NewCached(func() (interface{}, error) { + return inst.refreshData() }, cache).InterfaceGetter() + + // do first login if no authKey exists and uri and password exist + if inst.authKey == "" && inst.uri != "" && inst.password != "" { + err = instance.Login() + } + + mu.Lock() + instance = inst + mu.Unlock() }) - // it is sufficient to provide the uri once ... if not provided yet set uri now - if instance.uri == emptyUri { - instance.uri = uri - } + mu.Lock() + defer mu.Unlock() // check if different uris are provided - if uri != emptyUri && instance.uri != uri { + if uri != "" && instance.uri != uri { return nil, fmt.Errorf("uri mismatch: %s vs %s", instance.uri, uri) } - // it is sufficient to provide the password once ... if not provided yet set password now - if instance.password == "" { - instance.password = password - } - // check if different passwords are provided if password != "" && instance.password != password { return nil, errors.New("password mismatch") } - // do first login if no authKey exists and uri and password exist - var err error - if instance.authKey == "" && instance.uri != emptyUri && instance.password != "" { - err = instance.Login() - } - return instance, err } diff --git a/util/net.go b/util/net.go index f61a9509f..74d56dbdf 100644 --- a/util/net.go +++ b/util/net.go @@ -28,6 +28,9 @@ func DefaultScheme(uri string, scheme string) string { } switch { + case u.String() == "": + return "" + case u.Scheme == "": // scheme missing u.Scheme = scheme diff --git a/util/net_test.go b/util/net_test.go index b1b23c442..0e12ee129 100644 --- a/util/net_test.go +++ b/util/net_test.go @@ -38,3 +38,10 @@ func TestDefaultScheme(t *testing.T) { t.Errorf("expected %s, got %s", expect, uri) } } +func TestDefaultSchemeWithEmptyUri(t *testing.T) { + expect := "" + + if uri := DefaultScheme("", "http"); uri != expect { + t.Errorf("expected %s, got %s", expect, uri) + } +}