From cbbf677532614de97204a5a707e08ff9bbf6ae46 Mon Sep 17 00:00:00 2001 From: DN2 Date: Thu, 10 Jan 2019 00:53:58 -0800 Subject: [PATCH 1/5] A start. --- core/poller/unidev/unidev.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/core/poller/unidev/unidev.go b/core/poller/unidev/unidev.go index f9399263..c7ce4094 100644 --- a/core/poller/unidev/unidev.go +++ b/core/poller/unidev/unidev.go @@ -3,6 +3,7 @@ package unidev import ( "bytes" "crypto/tls" + "log" "net/http" "net/http/cookiejar" @@ -29,6 +30,9 @@ type AuthedReq struct { baseURL string } +// StringInt is used to unmarshal quoted integers in JSON responses. +type StringInt int + // AuthController creates a http.Client with authenticated cookies. // Used to make additional, authenticated requests to the APIs. func AuthController(user, pass, url string) (*AuthedReq, error) { @@ -41,11 +45,20 @@ func AuthController(user, pass, url string) (*AuthedReq, error) { Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}, Jar: jar, }, url} - if req, err := authReq.UniReq(LoginPath, json); err != nil { + req, err := authReq.UniReq(LoginPath, json) + if err != nil { return nil, errors.Wrap(err, "UniReq(LoginPath, json)") - } else if resp, err := authReq.Do(req); err != nil { + } + resp, err := authReq.Do(req) + if err != nil { return nil, errors.Wrap(err, "authReq.Do(req)") - } else if resp.StatusCode != http.StatusOK { + } + defer func() { + if err := resp.Body.Close(); err != nil { + log.Println("resp.Body.Close():", err) // Not fatal. Just log it. + } + }() + if resp.StatusCode != http.StatusOK { return nil, errors.Errorf("authentication failed (%v): %v (status: %v/%v)", user, url+LoginPath, resp.StatusCode, resp.Status) } From 016a39b9c30494c1e062634522d26926d173e37b Mon Sep 17 00:00:00 2001 From: DN2 Date: Thu, 10 Jan 2019 01:24:44 -0800 Subject: [PATCH 2/5] Move FlexInt into main file, add small test. --- core/poller/unidev/uap.go | 4 ++-- core/poller/unidev/uap_type.go | 31 ------------------------------- core/poller/unidev/unidev.go | 26 ++++++++++++++++++++++++-- core/poller/unidev/unidev_test.go | 23 +++++++++++++++++++++++ 4 files changed, 49 insertions(+), 35 deletions(-) create mode 100644 core/poller/unidev/unidev_test.go diff --git a/core/poller/unidev/uap.go b/core/poller/unidev/uap.go index 195ce613..c3e0dc76 100644 --- a/core/poller/unidev/uap.go +++ b/core/poller/unidev/uap.go @@ -181,7 +181,7 @@ func (u UAP) Points() ([]*influx.Point, error) { "device_mac": u.Mac, "name": p.Name, "wlangroup_id": p.WlangroupID, - "channel": strconv.Itoa(p.Channel.Value), + "channel": strconv.Itoa(int(p.Channel)), "radio": p.Radio, } fields := map[string]interface{}{ @@ -196,7 +196,7 @@ func (u UAP) Points() ([]*influx.Point, error) { "min_txpower": p.MinTxpower, "nss": p.Nss, "radio_caps": p.RadioCaps, - "tx_power": p.TxPower.Value, + "tx_power": p.TxPower, "tx_power_mode": p.TxPowerMode, } diff --git a/core/poller/unidev/uap_type.go b/core/poller/unidev/uap_type.go index 59688a51..fd928114 100644 --- a/core/poller/unidev/uap_type.go +++ b/core/poller/unidev/uap_type.go @@ -1,36 +1,5 @@ package unidev -import ( - "encoding/json" - "errors" - "strconv" -) - -// FlexInt provides a container and unmarshalling for fields that may be -// numbers or strings in the Unifi API -type FlexInt struct { - Value int -} - -func (this FlexInt) UnmarshalJSON(b []byte) error { - var unk interface{} - err := json.Unmarshal(b, &unk) - if err != nil { - return err - } - switch i := unk.(type) { - case float64: - this.Value = int(i) - return nil - case string: - this.Value, err = strconv.Atoi(i) - return err - default: - return errors.New("Cannot unmarshal to FlexInt") - } - -} - // UAP is a Unifi Access Point. type UAP struct { /* This was auto generated and then slowly edited by hand diff --git a/core/poller/unidev/unidev.go b/core/poller/unidev/unidev.go index c7ce4094..a5992836 100644 --- a/core/poller/unidev/unidev.go +++ b/core/poller/unidev/unidev.go @@ -3,9 +3,11 @@ package unidev import ( "bytes" "crypto/tls" + "encoding/json" "log" "net/http" "net/http/cookiejar" + "strconv" influx "github.com/influxdata/influxdb/client/v2" "github.com/pkg/errors" @@ -30,8 +32,28 @@ type AuthedReq struct { baseURL string } -// StringInt is used to unmarshal quoted integers in JSON responses. -type StringInt int +// FlexInt provides a container and unmarshalling for fields that may be +// numbers or strings in the Unifi API +type FlexInt int + +// UnmarshalJSON converts a string or number to an integer. +func (value *FlexInt) UnmarshalJSON(b []byte) error { + var unk interface{} + if err := json.Unmarshal(b, &unk); err != nil { + return err + } + switch i := unk.(type) { + case float64: + *value = FlexInt(i) + return nil + case string: + j, err := strconv.Atoi(i) + *value = FlexInt(j) + return err + default: + return errors.New("Cannot unmarshal to FlexInt") + } +} // AuthController creates a http.Client with authenticated cookies. // Used to make additional, authenticated requests to the APIs. diff --git a/core/poller/unidev/unidev_test.go b/core/poller/unidev/unidev_test.go new file mode 100644 index 00000000..5c4986f9 --- /dev/null +++ b/core/poller/unidev/unidev_test.go @@ -0,0 +1,23 @@ +package unidev + +import ( + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestFlexInt(t *testing.T) { + t.Parallel() + a := assert.New(t) + five := []byte(`{"channel": "5"}`) + seven := []byte(`{"channel": 7}`) + type reply struct { + Channel FlexInt `json:"channel"` + } + var r reply + a.Nil(json.Unmarshal(five, &r)) + a.EqualValues(FlexInt(5), r.Channel) + a.Nil(json.Unmarshal(seven, &r)) + a.EqualValues(FlexInt(7), r.Channel) +} From b9e9bc37b0f9a20ec167d2e445b2df5ad931f0c6 Mon Sep 17 00:00:00 2001 From: DN2 Date: Thu, 10 Jan 2019 01:32:17 -0800 Subject: [PATCH 3/5] Check for normal string and accept it. --- core/poller/unidev/unidev.go | 5 +++-- core/poller/unidev/unidev_test.go | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/core/poller/unidev/unidev.go b/core/poller/unidev/unidev.go index a5992836..3f8d9e40 100644 --- a/core/poller/unidev/unidev.go +++ b/core/poller/unidev/unidev.go @@ -47,9 +47,10 @@ func (value *FlexInt) UnmarshalJSON(b []byte) error { *value = FlexInt(i) return nil case string: - j, err := strconv.Atoi(i) + // If it's a string like the word "auto" just set the integer to 0 and proceed. + j, _ := strconv.Atoi(i) *value = FlexInt(j) - return err + return nil default: return errors.New("Cannot unmarshal to FlexInt") } diff --git a/core/poller/unidev/unidev_test.go b/core/poller/unidev/unidev_test.go index 5c4986f9..7f077978 100644 --- a/core/poller/unidev/unidev_test.go +++ b/core/poller/unidev/unidev_test.go @@ -12,6 +12,7 @@ func TestFlexInt(t *testing.T) { a := assert.New(t) five := []byte(`{"channel": "5"}`) seven := []byte(`{"channel": 7}`) + auto := []byte(`{"channel": "auto"}`) type reply struct { Channel FlexInt `json:"channel"` } @@ -20,4 +21,6 @@ func TestFlexInt(t *testing.T) { a.EqualValues(FlexInt(5), r.Channel) a.Nil(json.Unmarshal(seven, &r)) a.EqualValues(FlexInt(7), r.Channel) + a.NotNil(json.Unmarshal(auto, &r)) + a.EqualValues(FlexInt(0), r.Channel) } From 98e5df622ef65a6aaecdff2c3f4093c8e5d79f44 Mon Sep 17 00:00:00 2001 From: DN2 Date: Thu, 10 Jan 2019 01:34:35 -0800 Subject: [PATCH 4/5] Fix the error test. --- core/poller/unidev/unidev_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/poller/unidev/unidev_test.go b/core/poller/unidev/unidev_test.go index 7f077978..e69a4ffd 100644 --- a/core/poller/unidev/unidev_test.go +++ b/core/poller/unidev/unidev_test.go @@ -21,6 +21,6 @@ func TestFlexInt(t *testing.T) { a.EqualValues(FlexInt(5), r.Channel) a.Nil(json.Unmarshal(seven, &r)) a.EqualValues(FlexInt(7), r.Channel) - a.NotNil(json.Unmarshal(auto, &r)) + a.Nil(json.Unmarshal(auto, &r), "a regular string must not produce an unmarshal error") a.EqualValues(FlexInt(0), r.Channel) } From a7f74b270a15a1611048e7728921b6560ab70b18 Mon Sep 17 00:00:00 2001 From: DN2 Date: Thu, 10 Jan 2019 01:35:39 -0800 Subject: [PATCH 5/5] make the test smaller, because why not. --- core/poller/unidev/unidev_test.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/poller/unidev/unidev_test.go b/core/poller/unidev/unidev_test.go index e69a4ffd..ed6cf005 100644 --- a/core/poller/unidev/unidev_test.go +++ b/core/poller/unidev/unidev_test.go @@ -10,17 +10,15 @@ import ( func TestFlexInt(t *testing.T) { t.Parallel() a := assert.New(t) - five := []byte(`{"channel": "5"}`) - seven := []byte(`{"channel": 7}`) - auto := []byte(`{"channel": "auto"}`) type reply struct { Channel FlexInt `json:"channel"` } var r reply - a.Nil(json.Unmarshal(five, &r)) + a.Nil(json.Unmarshal([]byte(`{"channel": "5"}`), &r)) a.EqualValues(FlexInt(5), r.Channel) - a.Nil(json.Unmarshal(seven, &r)) + a.Nil(json.Unmarshal([]byte(`{"channel": 7}`), &r)) a.EqualValues(FlexInt(7), r.Channel) - a.Nil(json.Unmarshal(auto, &r), "a regular string must not produce an unmarshal error") + a.Nil(json.Unmarshal([]byte(`{"channel": "auto"}`), &r), + "a regular string must not produce an unmarshal error") a.EqualValues(FlexInt(0), r.Channel) }