diff --git a/core/unifi/.travis.yml b/core/unifi/.travis.yml index 24c1ed7e..a05c4c9f 100644 --- a/core/unifi/.travis.yml +++ b/core/unifi/.travis.yml @@ -12,3 +12,4 @@ install: - dep ensure script: - golangci-lint run --enable-all -e G402 +- go test ./... diff --git a/core/unifi/types.go b/core/unifi/types.go index 4c3920f0..46dc652f 100644 --- a/core/unifi/types.go +++ b/core/unifi/types.go @@ -54,10 +54,11 @@ type Unifi struct { baseURL string ErrorLog Logger DebugLog Logger + *server } -// Server is the /status endpoint from the Unifi controller. -type Server struct { +// server is the /status endpoint from the Unifi controller. +type server struct { Up FlexBool `json:"up"` ServerVersion string `json:"server_version"` UUID string `json:"uuid"` diff --git a/core/unifi/uap_type.go b/core/unifi/uap_type.go index 842a022a..7858a1f8 100644 --- a/core/unifi/uap_type.go +++ b/core/unifi/uap_type.go @@ -1,6 +1,9 @@ package unifi -import "time" +import ( + "encoding/json" + "time" +) // UAP represents all the data from the Ubiquiti Controller for a Unifi Access Point. type UAP struct { @@ -305,142 +308,7 @@ type UAP struct { UplinkMac string `json:"uplink_mac"` UplinkRemotePort int `json:"uplink_remote_port"` } `json:"last_uplink"` - Stat struct { - SiteID string `json:"site_id"` - O string `json:"o"` - Oid string `json:"oid"` - Ap string `json:"ap"` - Time FlexInt `json:"time"` - Datetime time.Time `json:"datetime"` - GuestWifi0RxPackets FlexInt `json:"guest-wifi0-rx_packets"` - GuestWifi1RxPackets FlexInt `json:"guest-wifi1-rx_packets"` - UserWifi1RxPackets FlexInt `json:"user-wifi1-rx_packets"` - UserWifi0RxPackets FlexInt `json:"user-wifi0-rx_packets"` - UserRxPackets FlexInt `json:"user-rx_packets"` - GuestRxPackets FlexInt `json:"guest-rx_packets"` - Wifi0RxPackets FlexInt `json:"wifi0-rx_packets"` - Wifi1RxPackets FlexInt `json:"wifi1-rx_packets"` - RxPackets FlexInt `json:"rx_packets"` - GuestWifi0RxBytes FlexInt `json:"guest-wifi0-rx_bytes"` - GuestWifi1RxBytes FlexInt `json:"guest-wifi1-rx_bytes"` - UserWifi1RxBytes FlexInt `json:"user-wifi1-rx_bytes"` - UserWifi0RxBytes FlexInt `json:"user-wifi0-rx_bytes"` - UserRxBytes FlexInt `json:"user-rx_bytes"` - GuestRxBytes FlexInt `json:"guest-rx_bytes"` - Wifi0RxBytes FlexInt `json:"wifi0-rx_bytes"` - Wifi1RxBytes FlexInt `json:"wifi1-rx_bytes"` - RxBytes FlexInt `json:"rx_bytes"` - GuestWifi0RxErrors FlexInt `json:"guest-wifi0-rx_errors"` - GuestWifi1RxErrors FlexInt `json:"guest-wifi1-rx_errors"` - UserWifi1RxErrors FlexInt `json:"user-wifi1-rx_errors"` - UserWifi0RxErrors FlexInt `json:"user-wifi0-rx_errors"` - UserRxErrors FlexInt `json:"user-rx_errors"` - GuestRxErrors FlexInt `json:"guest-rx_errors"` - Wifi0RxErrors FlexInt `json:"wifi0-rx_errors"` - Wifi1RxErrors FlexInt `json:"wifi1-rx_errors"` - RxErrors FlexInt `json:"rx_errors"` - GuestWifi0RxDropped FlexInt `json:"guest-wifi0-rx_dropped"` - GuestWifi1RxDropped FlexInt `json:"guest-wifi1-rx_dropped"` - UserWifi1RxDropped FlexInt `json:"user-wifi1-rx_dropped"` - UserWifi0RxDropped FlexInt `json:"user-wifi0-rx_dropped"` - UserRxDropped FlexInt `json:"user-rx_dropped"` - GuestRxDropped FlexInt `json:"guest-rx_dropped"` - Wifi0RxDropped FlexInt `json:"wifi0-rx_dropped"` - Wifi1RxDropped FlexInt `json:"wifi1-rx_dropped"` - RxDropped FlexInt `json:"rx_dropped"` - GuestWifi0RxCrypts FlexInt `json:"guest-wifi0-rx_crypts"` - GuestWifi1RxCrypts FlexInt `json:"guest-wifi1-rx_crypts"` - UserWifi1RxCrypts FlexInt `json:"user-wifi1-rx_crypts"` - UserWifi0RxCrypts FlexInt `json:"user-wifi0-rx_crypts"` - UserRxCrypts FlexInt `json:"user-rx_crypts"` - GuestRxCrypts FlexInt `json:"guest-rx_crypts"` - Wifi0RxCrypts FlexInt `json:"wifi0-rx_crypts"` - Wifi1RxCrypts FlexInt `json:"wifi1-rx_crypts"` - RxCrypts FlexInt `json:"rx_crypts"` - GuestWifi0RxFrags FlexInt `json:"guest-wifi0-rx_frags"` - GuestWifi1RxFrags FlexInt `json:"guest-wifi1-rx_frags"` - UserWifi1RxFrags FlexInt `json:"user-wifi1-rx_frags"` - UserWifi0RxFrags FlexInt `json:"user-wifi0-rx_frags"` - UserRxFrags FlexInt `json:"user-rx_frags"` - GuestRxFrags FlexInt `json:"guest-rx_frags"` - Wifi0RxFrags FlexInt `json:"wifi0-rx_frags"` - Wifi1RxFrags FlexInt `json:"wifi1-rx_frags"` - RxFrags FlexInt `json:"rx_frags"` - GuestWifi0TxPackets FlexInt `json:"guest-wifi0-tx_packets"` - GuestWifi1TxPackets FlexInt `json:"guest-wifi1-tx_packets"` - UserWifi1TxPackets FlexInt `json:"user-wifi1-tx_packets"` - UserWifi0TxPackets FlexInt `json:"user-wifi0-tx_packets"` - UserTxPackets FlexInt `json:"user-tx_packets"` - GuestTxPackets FlexInt `json:"guest-tx_packets"` - Wifi0TxPackets FlexInt `json:"wifi0-tx_packets"` - Wifi1TxPackets FlexInt `json:"wifi1-tx_packets"` - TxPackets FlexInt `json:"tx_packets"` - GuestWifi0TxBytes FlexInt `json:"guest-wifi0-tx_bytes"` - GuestWifi1TxBytes FlexInt `json:"guest-wifi1-tx_bytes"` - UserWifi1TxBytes FlexInt `json:"user-wifi1-tx_bytes"` - UserWifi0TxBytes FlexInt `json:"user-wifi0-tx_bytes"` - UserTxBytes FlexInt `json:"user-tx_bytes"` - GuestTxBytes FlexInt `json:"guest-tx_bytes"` - Wifi0TxBytes FlexInt `json:"wifi0-tx_bytes"` - Wifi1TxBytes FlexInt `json:"wifi1-tx_bytes"` - TxBytes FlexInt `json:"tx_bytes"` - GuestWifi0TxErrors FlexInt `json:"guest-wifi0-tx_errors"` - GuestWifi1TxErrors FlexInt `json:"guest-wifi1-tx_errors"` - UserWifi1TxErrors FlexInt `json:"user-wifi1-tx_errors"` - UserWifi0TxErrors FlexInt `json:"user-wifi0-tx_errors"` - UserTxErrors FlexInt `json:"user-tx_errors"` - GuestTxErrors FlexInt `json:"guest-tx_errors"` - Wifi0TxErrors FlexInt `json:"wifi0-tx_errors"` - Wifi1TxErrors FlexInt `json:"wifi1-tx_errors"` - TxErrors FlexInt `json:"tx_errors"` - GuestWifi0TxDropped FlexInt `json:"guest-wifi0-tx_dropped"` - GuestWifi1TxDropped FlexInt `json:"guest-wifi1-tx_dropped"` - UserWifi1TxDropped FlexInt `json:"user-wifi1-tx_dropped"` - UserWifi0TxDropped FlexInt `json:"user-wifi0-tx_dropped"` - UserTxDropped FlexInt `json:"user-tx_dropped"` - GuestTxDropped FlexInt `json:"guest-tx_dropped"` - Wifi0TxDropped FlexInt `json:"wifi0-tx_dropped"` - Wifi1TxDropped FlexInt `json:"wifi1-tx_dropped"` - TxDropped FlexInt `json:"tx_dropped"` - GuestWifi0TxRetries FlexInt `json:"guest-wifi0-tx_retries"` - GuestWifi1TxRetries FlexInt `json:"guest-wifi1-tx_retries"` - UserWifi1TxRetries FlexInt `json:"user-wifi1-tx_retries"` - UserWifi0TxRetries FlexInt `json:"user-wifi0-tx_retries"` - UserTxRetries FlexInt `json:"user-tx_retries"` - GuestTxRetries FlexInt `json:"guest-tx_retries"` - Wifi0TxRetries FlexInt `json:"wifi0-tx_retries"` - Wifi1TxRetries FlexInt `json:"wifi1-tx_retries"` - TxRetries FlexInt `json:"tx_retries"` - GuestWifi0MacFilterRejections FlexInt `json:"guest-wifi0-mac_filter_rejections"` - GuestWifi1MacFilterRejections FlexInt `json:"guest-wifi1-mac_filter_rejections"` - UserWifi1MacFilterRejections FlexInt `json:"user-wifi1-mac_filter_rejections"` - UserWifi0MacFilterRejections FlexInt `json:"user-wifi0-mac_filter_rejections"` - UserMacFilterRejections FlexInt `json:"user-mac_filter_rejections"` - GuestMacFilterRejections FlexInt `json:"guest-mac_filter_rejections"` - Wifi0MacFilterRejections FlexInt `json:"wifi0-mac_filter_rejections"` - Wifi1MacFilterRejections FlexInt `json:"wifi1-mac_filter_rejections"` - MacFilterRejections FlexInt `json:"mac_filter_rejections"` - GuestWifi0WifiTxAttempts FlexInt `json:"guest-wifi0-wifi_tx_attempts"` - GuestWifi1WifiTxAttempts FlexInt `json:"guest-wifi1-wifi_tx_attempts"` - UserWifi1WifiTxAttempts FlexInt `json:"user-wifi1-wifi_tx_attempts"` - UserWifi0WifiTxAttempts FlexInt `json:"user-wifi0-wifi_tx_attempts"` - UserWifiTxAttempts FlexInt `json:"user-wifi_tx_attempts"` - GuestWifiTxAttempts FlexInt `json:"guest-wifi_tx_attempts"` - Wifi0WifiTxAttempts FlexInt `json:"wifi0-wifi_tx_attempts"` - Wifi1WifiTxAttempts FlexInt `json:"wifi1-wifi_tx_attempts"` - WifiTxAttempts FlexInt `json:"wifi_tx_attempts"` - GuestWifi0WifiTxDropped FlexInt `json:"guest-wifi0-wifi_tx_dropped"` - GuestWifi1WifiTxDropped FlexInt `json:"guest-wifi1-wifi_tx_dropped"` - UserWifi1WifiTxDropped FlexInt `json:"user-wifi1-wifi_tx_dropped"` - UserWifi0WifiTxDropped FlexInt `json:"user-wifi0-wifi_tx_dropped"` - UserWifiTxDropped FlexInt `json:"user-wifi_tx_dropped"` - GuestWifiTxDropped FlexInt `json:"guest-wifi_tx_dropped"` - Wifi0WifiTxDropped FlexInt `json:"wifi0-wifi_tx_dropped"` - Wifi1WifiTxDropped FlexInt `json:"wifi1-wifi_tx_dropped"` - WifiTxDropped FlexInt `json:"wifi_tx_dropped"` - Bytes FlexInt `json:"bytes"` - Duration FlexInt `json:"duration"` - } `json:"stat,omitempty"` + Stat *UAPStat `json:"stat"` TxBytes FlexInt `json:"tx_bytes"` RxBytes FlexInt `json:"rx_bytes"` Bytes FlexInt `json:"bytes"` @@ -451,3 +319,158 @@ type UAP struct { GuestNumSta int `json:"guest-num_sta"` TwoPhaseAdopt FlexBool `json:"two_phase_adopt,omitempty"` } + +// UAPStat holds the "stat" data for an access point. +// This is split out because of a JSON data format change from 5.10 to 5.11. +type UAPStat struct { + *ap +} +type ap struct { + SiteID string `json:"site_id"` + O string `json:"o"` + Oid string `json:"oid"` + Ap string `json:"ap"` + Time FlexInt `json:"time"` + Datetime time.Time `json:"datetime"` + GuestWifi0RxPackets FlexInt `json:"guest-wifi0-rx_packets"` + GuestWifi1RxPackets FlexInt `json:"guest-wifi1-rx_packets"` + UserWifi1RxPackets FlexInt `json:"user-wifi1-rx_packets"` + UserWifi0RxPackets FlexInt `json:"user-wifi0-rx_packets"` + UserRxPackets FlexInt `json:"user-rx_packets"` + GuestRxPackets FlexInt `json:"guest-rx_packets"` + Wifi0RxPackets FlexInt `json:"wifi0-rx_packets"` + Wifi1RxPackets FlexInt `json:"wifi1-rx_packets"` + RxPackets FlexInt `json:"rx_packets"` + GuestWifi0RxBytes FlexInt `json:"guest-wifi0-rx_bytes"` + GuestWifi1RxBytes FlexInt `json:"guest-wifi1-rx_bytes"` + UserWifi1RxBytes FlexInt `json:"user-wifi1-rx_bytes"` + UserWifi0RxBytes FlexInt `json:"user-wifi0-rx_bytes"` + UserRxBytes FlexInt `json:"user-rx_bytes"` + GuestRxBytes FlexInt `json:"guest-rx_bytes"` + Wifi0RxBytes FlexInt `json:"wifi0-rx_bytes"` + Wifi1RxBytes FlexInt `json:"wifi1-rx_bytes"` + RxBytes FlexInt `json:"rx_bytes"` + GuestWifi0RxErrors FlexInt `json:"guest-wifi0-rx_errors"` + GuestWifi1RxErrors FlexInt `json:"guest-wifi1-rx_errors"` + UserWifi1RxErrors FlexInt `json:"user-wifi1-rx_errors"` + UserWifi0RxErrors FlexInt `json:"user-wifi0-rx_errors"` + UserRxErrors FlexInt `json:"user-rx_errors"` + GuestRxErrors FlexInt `json:"guest-rx_errors"` + Wifi0RxErrors FlexInt `json:"wifi0-rx_errors"` + Wifi1RxErrors FlexInt `json:"wifi1-rx_errors"` + RxErrors FlexInt `json:"rx_errors"` + GuestWifi0RxDropped FlexInt `json:"guest-wifi0-rx_dropped"` + GuestWifi1RxDropped FlexInt `json:"guest-wifi1-rx_dropped"` + UserWifi1RxDropped FlexInt `json:"user-wifi1-rx_dropped"` + UserWifi0RxDropped FlexInt `json:"user-wifi0-rx_dropped"` + UserRxDropped FlexInt `json:"user-rx_dropped"` + GuestRxDropped FlexInt `json:"guest-rx_dropped"` + Wifi0RxDropped FlexInt `json:"wifi0-rx_dropped"` + Wifi1RxDropped FlexInt `json:"wifi1-rx_dropped"` + RxDropped FlexInt `json:"rx_dropped"` + GuestWifi0RxCrypts FlexInt `json:"guest-wifi0-rx_crypts"` + GuestWifi1RxCrypts FlexInt `json:"guest-wifi1-rx_crypts"` + UserWifi1RxCrypts FlexInt `json:"user-wifi1-rx_crypts"` + UserWifi0RxCrypts FlexInt `json:"user-wifi0-rx_crypts"` + UserRxCrypts FlexInt `json:"user-rx_crypts"` + GuestRxCrypts FlexInt `json:"guest-rx_crypts"` + Wifi0RxCrypts FlexInt `json:"wifi0-rx_crypts"` + Wifi1RxCrypts FlexInt `json:"wifi1-rx_crypts"` + RxCrypts FlexInt `json:"rx_crypts"` + GuestWifi0RxFrags FlexInt `json:"guest-wifi0-rx_frags"` + GuestWifi1RxFrags FlexInt `json:"guest-wifi1-rx_frags"` + UserWifi1RxFrags FlexInt `json:"user-wifi1-rx_frags"` + UserWifi0RxFrags FlexInt `json:"user-wifi0-rx_frags"` + UserRxFrags FlexInt `json:"user-rx_frags"` + GuestRxFrags FlexInt `json:"guest-rx_frags"` + Wifi0RxFrags FlexInt `json:"wifi0-rx_frags"` + Wifi1RxFrags FlexInt `json:"wifi1-rx_frags"` + RxFrags FlexInt `json:"rx_frags"` + GuestWifi0TxPackets FlexInt `json:"guest-wifi0-tx_packets"` + GuestWifi1TxPackets FlexInt `json:"guest-wifi1-tx_packets"` + UserWifi1TxPackets FlexInt `json:"user-wifi1-tx_packets"` + UserWifi0TxPackets FlexInt `json:"user-wifi0-tx_packets"` + UserTxPackets FlexInt `json:"user-tx_packets"` + GuestTxPackets FlexInt `json:"guest-tx_packets"` + Wifi0TxPackets FlexInt `json:"wifi0-tx_packets"` + Wifi1TxPackets FlexInt `json:"wifi1-tx_packets"` + TxPackets FlexInt `json:"tx_packets"` + GuestWifi0TxBytes FlexInt `json:"guest-wifi0-tx_bytes"` + GuestWifi1TxBytes FlexInt `json:"guest-wifi1-tx_bytes"` + UserWifi1TxBytes FlexInt `json:"user-wifi1-tx_bytes"` + UserWifi0TxBytes FlexInt `json:"user-wifi0-tx_bytes"` + UserTxBytes FlexInt `json:"user-tx_bytes"` + GuestTxBytes FlexInt `json:"guest-tx_bytes"` + Wifi0TxBytes FlexInt `json:"wifi0-tx_bytes"` + Wifi1TxBytes FlexInt `json:"wifi1-tx_bytes"` + TxBytes FlexInt `json:"tx_bytes"` + GuestWifi0TxErrors FlexInt `json:"guest-wifi0-tx_errors"` + GuestWifi1TxErrors FlexInt `json:"guest-wifi1-tx_errors"` + UserWifi1TxErrors FlexInt `json:"user-wifi1-tx_errors"` + UserWifi0TxErrors FlexInt `json:"user-wifi0-tx_errors"` + UserTxErrors FlexInt `json:"user-tx_errors"` + GuestTxErrors FlexInt `json:"guest-tx_errors"` + Wifi0TxErrors FlexInt `json:"wifi0-tx_errors"` + Wifi1TxErrors FlexInt `json:"wifi1-tx_errors"` + TxErrors FlexInt `json:"tx_errors"` + GuestWifi0TxDropped FlexInt `json:"guest-wifi0-tx_dropped"` + GuestWifi1TxDropped FlexInt `json:"guest-wifi1-tx_dropped"` + UserWifi1TxDropped FlexInt `json:"user-wifi1-tx_dropped"` + UserWifi0TxDropped FlexInt `json:"user-wifi0-tx_dropped"` + UserTxDropped FlexInt `json:"user-tx_dropped"` + GuestTxDropped FlexInt `json:"guest-tx_dropped"` + Wifi0TxDropped FlexInt `json:"wifi0-tx_dropped"` + Wifi1TxDropped FlexInt `json:"wifi1-tx_dropped"` + TxDropped FlexInt `json:"tx_dropped"` + GuestWifi0TxRetries FlexInt `json:"guest-wifi0-tx_retries"` + GuestWifi1TxRetries FlexInt `json:"guest-wifi1-tx_retries"` + UserWifi1TxRetries FlexInt `json:"user-wifi1-tx_retries"` + UserWifi0TxRetries FlexInt `json:"user-wifi0-tx_retries"` + UserTxRetries FlexInt `json:"user-tx_retries"` + GuestTxRetries FlexInt `json:"guest-tx_retries"` + Wifi0TxRetries FlexInt `json:"wifi0-tx_retries"` + Wifi1TxRetries FlexInt `json:"wifi1-tx_retries"` + TxRetries FlexInt `json:"tx_retries"` + GuestWifi0MacFilterRejections FlexInt `json:"guest-wifi0-mac_filter_rejections"` + GuestWifi1MacFilterRejections FlexInt `json:"guest-wifi1-mac_filter_rejections"` + UserWifi1MacFilterRejections FlexInt `json:"user-wifi1-mac_filter_rejections"` + UserWifi0MacFilterRejections FlexInt `json:"user-wifi0-mac_filter_rejections"` + UserMacFilterRejections FlexInt `json:"user-mac_filter_rejections"` + GuestMacFilterRejections FlexInt `json:"guest-mac_filter_rejections"` + Wifi0MacFilterRejections FlexInt `json:"wifi0-mac_filter_rejections"` + Wifi1MacFilterRejections FlexInt `json:"wifi1-mac_filter_rejections"` + MacFilterRejections FlexInt `json:"mac_filter_rejections"` + GuestWifi0WifiTxAttempts FlexInt `json:"guest-wifi0-wifi_tx_attempts"` + GuestWifi1WifiTxAttempts FlexInt `json:"guest-wifi1-wifi_tx_attempts"` + UserWifi1WifiTxAttempts FlexInt `json:"user-wifi1-wifi_tx_attempts"` + UserWifi0WifiTxAttempts FlexInt `json:"user-wifi0-wifi_tx_attempts"` + UserWifiTxAttempts FlexInt `json:"user-wifi_tx_attempts"` + GuestWifiTxAttempts FlexInt `json:"guest-wifi_tx_attempts"` + Wifi0WifiTxAttempts FlexInt `json:"wifi0-wifi_tx_attempts"` + Wifi1WifiTxAttempts FlexInt `json:"wifi1-wifi_tx_attempts"` + WifiTxAttempts FlexInt `json:"wifi_tx_attempts"` + GuestWifi0WifiTxDropped FlexInt `json:"guest-wifi0-wifi_tx_dropped"` + GuestWifi1WifiTxDropped FlexInt `json:"guest-wifi1-wifi_tx_dropped"` + UserWifi1WifiTxDropped FlexInt `json:"user-wifi1-wifi_tx_dropped"` + UserWifi0WifiTxDropped FlexInt `json:"user-wifi0-wifi_tx_dropped"` + UserWifiTxDropped FlexInt `json:"user-wifi_tx_dropped"` + GuestWifiTxDropped FlexInt `json:"guest-wifi_tx_dropped"` + Wifi0WifiTxDropped FlexInt `json:"wifi0-wifi_tx_dropped"` + Wifi1WifiTxDropped FlexInt `json:"wifi1-wifi_tx_dropped"` + WifiTxDropped FlexInt `json:"wifi_tx_dropped"` + Bytes FlexInt `json:"bytes"` + Duration FlexInt `json:"duration"` +} + +// UnmarshalJSON unmarshalls 5.10 or 5.11 formatted Access Point Stat data. +func (v *UAPStat) UnmarshalJSON(data []byte) error { + var n struct { + ap `json:"ap"` + } + v.ap = &n.ap + err := json.Unmarshal(data, v.ap) // controller version 5.10. + if err != nil { + return json.Unmarshal(data, &n) // controller version 5.11. + } + return nil +} diff --git a/core/unifi/uap_type_test.go b/core/unifi/uap_type_test.go new file mode 100644 index 00000000..2ad1f982 --- /dev/null +++ b/core/unifi/uap_type_test.go @@ -0,0 +1,53 @@ +package unifi + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUAPUnmarshalJSON(t *testing.T) { + testcontroller511 := `{ + "ap": { + "site_id": "mySite", + "o": "ap", + "oid": "00:00:00:00:00:00", + "ap": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:50:00Z", + "user-wifi1-rx_packets": 6596670, + "user-wifi0-rx_packets": 42659527, + "user-rx_packets": 49294197, + "guest-rx_packets": 0, + "wifi0-rx_packets": 42639527, + "wifi1-rx_packets": 6591670, + "rx_packets": 49299197}}` + + testcontroller510 := `{ + "site_id": "mySite", + "o": "ap", + "oid": "00:00:00:00:00:00", + "ap": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:50:00Z", + "user-wifi1-rx_packets": 6596670, + "user-wifi0-rx_packets": 42659527, + "user-rx_packets": 49294197, + "guest-rx_packets": 0, + "wifi0-rx_packets": 42639527, + "wifi1-rx_packets": 6591670, + "rx_packets": 49299197}` + + t.Parallel() + a := assert.New(t) + + u := &UAPStat{} + err := u.UnmarshalJSON([]byte(testcontroller510)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(49299197), u.RxPackets.Val, "data was not properly unmarshaled") + + u = &UAPStat{} // reset + err = u.UnmarshalJSON([]byte(testcontroller511)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(49299197), u.RxPackets.Val, "data was not properly unmarshaled") +} diff --git a/core/unifi/unifi.go b/core/unifi/unifi.go index 93d28de9..76b53cf8 100644 --- a/core/unifi/unifi.go +++ b/core/unifi/unifi.go @@ -58,16 +58,22 @@ func (u *Unifi) getController(user, pass string) error { return errors.Errorf("authentication failed (user: %s): %s (status: %s)", user, u.baseURL+LoginPath, resp.Status) } - return nil + return errors.Wrap(u.getServer(), "unable to get server version") +} + +// getServer sets the controller's version and UUID. +func (u *Unifi) getServer() error { + var response struct { + Data server `json:"meta"` + } + u.server = &response.Data + return u.GetData(StatusPath, &response) } // GetServer returns the controller's version and UUID. -func (u *Unifi) GetServer() (Server, error) { - var response struct { - Data Server `json:"meta"` - } - err := u.GetData(StatusPath, &response) - return response.Data, err +// This method is deprecated and will go away in a future release, use u.Server* +func (u *Unifi) GetServer() (*server, error) { + return u.server, nil } // GetClients returns a response full of clients' data from the Unifi Controller. diff --git a/core/unifi/usg_type.go b/core/unifi/usg_type.go index 5ba8bc21..166eb5d3 100644 --- a/core/unifi/usg_type.go +++ b/core/unifi/usg_type.go @@ -1,6 +1,9 @@ package unifi -import "time" +import ( + "encoding/json" + "time" +) // USG represents all the data from the Ubiquiti Controller for a Unifi Security Gateway. type USG struct { @@ -230,32 +233,53 @@ type USG struct { MaxSpeed FlexInt `json:"max_speed"` Type string `json:"type"` } `json:"uplink"` - Stat struct { - SiteID string `json:"site_id"` - O string `json:"o"` - Oid string `json:"oid"` - Gw string `json:"gw"` - Time FlexInt `json:"time"` - Datetime time.Time `json:"datetime"` - Duration FlexInt `json:"duration"` - WanRxPackets FlexInt `json:"wan-rx_packets"` - WanRxBytes FlexInt `json:"wan-rx_bytes"` - WanTxPackets FlexInt `json:"wan-tx_packets"` - WanTxBytes FlexInt `json:"wan-tx_bytes"` - LanRxPackets FlexInt `json:"lan-rx_packets"` - LanRxBytes FlexInt `json:"lan-rx_bytes"` - LanTxPackets FlexInt `json:"lan-tx_packets"` - LanTxBytes FlexInt `json:"lan-tx_bytes"` - WanRxDropped FlexInt `json:"wan-rx_dropped"` - LanRxDropped FlexInt `json:"lan-rx_dropped"` - } `json:"stat"` - TxBytes FlexInt `json:"tx_bytes"` - RxBytes FlexInt `json:"rx_bytes"` - Bytes FlexInt `json:"bytes"` - NumSta FlexInt `json:"num_sta"` - UserNumSta FlexInt `json:"user-num_sta"` - GuestNumSta FlexInt `json:"guest-num_sta"` - NumDesktop FlexInt `json:"num_desktop"` - NumMobile FlexInt `json:"num_mobile"` - NumHandheld FlexInt `json:"num_handheld"` + Stat *USGStat `json:"stat"` + TxBytes FlexInt `json:"tx_bytes"` + RxBytes FlexInt `json:"rx_bytes"` + Bytes FlexInt `json:"bytes"` + NumSta FlexInt `json:"num_sta"` + UserNumSta FlexInt `json:"user-num_sta"` + GuestNumSta FlexInt `json:"guest-num_sta"` + NumDesktop FlexInt `json:"num_desktop"` + NumMobile FlexInt `json:"num_mobile"` + NumHandheld FlexInt `json:"num_handheld"` +} + +// USGStat holds the "stat" data for a gateway. +// This is split out because of a JSON data format change from 5.10 to 5.11. +type USGStat struct { + *gw +} + +type gw struct { + SiteID string `json:"site_id"` + O string `json:"o"` + Oid string `json:"oid"` + Gw string `json:"gw"` + Time FlexInt `json:"time"` + Datetime time.Time `json:"datetime"` + Duration FlexInt `json:"duration"` + WanRxPackets FlexInt `json:"wan-rx_packets"` + WanRxBytes FlexInt `json:"wan-rx_bytes"` + WanTxPackets FlexInt `json:"wan-tx_packets"` + WanTxBytes FlexInt `json:"wan-tx_bytes"` + LanRxPackets FlexInt `json:"lan-rx_packets"` + LanRxBytes FlexInt `json:"lan-rx_bytes"` + LanTxPackets FlexInt `json:"lan-tx_packets"` + LanTxBytes FlexInt `json:"lan-tx_bytes"` + WanRxDropped FlexInt `json:"wan-rx_dropped"` + LanRxDropped FlexInt `json:"lan-rx_dropped"` +} + +// UnmarshalJSON unmarshalls 5.10 or 5.11 formatted Gateway Stat data. +func (v *USGStat) UnmarshalJSON(data []byte) error { + var n struct { + gw `json:"gw"` + } + v.gw = &n.gw + err := json.Unmarshal(data, v.gw) // controller version 5.10. + if err != nil { + return json.Unmarshal(data, &n) // controller version 5.11. + } + return nil } diff --git a/core/unifi/usg_type_test.go b/core/unifi/usg_type_test.go new file mode 100644 index 00000000..962dd677 --- /dev/null +++ b/core/unifi/usg_type_test.go @@ -0,0 +1,59 @@ +package unifi + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUSGUnmarshalJSON(t *testing.T) { + testcontroller511 := `{ + "gw": { + "site_id": "mySite", + "o": "gw", + "oid": "00:00:00:00:00:00", + "gw": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:50:00Z", + "bytes": 0, + "duration": 3590568000, + "wan-rx_packets": 299729434558, + "wan-rx_bytes": 299882768958208, + "wan-tx_packets": 249639259523, + "wan-tx_bytes": 169183252492369, + "lan-rx_packets": 78912349453, + "lan-rx_bytes": 37599596992669, + "lan-tx_packets": 12991234992, + "lan-tx_bytes": 11794664098210}}` + + testcontroller510 := `{ + "site_id": "mySite", + "o": "gw", + "oid": "00:00:00:00:00:00", + "gw": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:50:00Z", + "bytes": 0, + "duration": 3590568000, + "wan-rx_packets": 299729434558, + "wan-rx_bytes": 299882768958208, + "wan-tx_packets": 249639259523, + "wan-tx_bytes": 169183252492369, + "lan-rx_packets": 78912349453, + "lan-rx_bytes": 37599596992669, + "lan-tx_packets": 12991234992, + "lan-tx_bytes": 11794664098210}` + + t.Parallel() + a := assert.New(t) + + u := &USGStat{} + err := u.UnmarshalJSON([]byte(testcontroller510)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(37599596992669), u.LanRxBytes.Val, "data was not properly unmarshaled") + + u = &USGStat{} // reset + err = u.UnmarshalJSON([]byte(testcontroller511)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(37599596992669), u.LanRxBytes.Val, "data was not properly unmarshaled") +} diff --git a/core/unifi/usw_type.go b/core/unifi/usw_type.go index c2dc14ad..4ad891cf 100644 --- a/core/unifi/usw_type.go +++ b/core/unifi/usw_type.go @@ -1,6 +1,9 @@ package unifi -import "time" +import ( + "encoding/json" + "time" +) // USW represents all the data from the Ubiquiti Controller for a Unifi Switch. type USW struct { @@ -167,202 +170,223 @@ type USW struct { LastUplink struct { UplinkMac string `json:"uplink_mac"` } `json:"last_uplink"` - UplinkDepth FlexInt `json:"uplink_depth"` - Stat struct { - SiteID string `json:"site_id"` - O string `json:"o"` - Oid string `json:"oid"` - Sw string `json:"sw"` - Time FlexInt `json:"time"` - Datetime time.Time `json:"datetime"` - RxPackets FlexInt `json:"rx_packets"` - RxBytes FlexInt `json:"rx_bytes"` - RxErrors FlexInt `json:"rx_errors"` - RxDropped FlexInt `json:"rx_dropped"` - RxCrypts FlexInt `json:"rx_crypts"` - RxFrags FlexInt `json:"rx_frags"` - TxPackets FlexInt `json:"tx_packets"` - TxBytes FlexInt `json:"tx_bytes"` - TxErrors FlexInt `json:"tx_errors"` - TxDropped FlexInt `json:"tx_dropped"` - TxRetries FlexInt `json:"tx_retries"` - RxMulticast FlexInt `json:"rx_multicast"` - RxBroadcast FlexInt `json:"rx_broadcast"` - TxMulticast FlexInt `json:"tx_multicast"` - TxBroadcast FlexInt `json:"tx_broadcast"` - Bytes FlexInt `json:"bytes"` - Duration FlexInt `json:"duration"` - Port1RxPackets FlexInt `json:"port_1-rx_packets"` - Port1RxBytes FlexInt `json:"port_1-rx_bytes"` - Port1TxPackets FlexInt `json:"port_1-tx_packets"` - Port1TxBytes FlexInt `json:"port_1-tx_bytes"` - Port1TxMulticast FlexInt `json:"port_1-tx_multicast"` - Port1TxBroadcast FlexInt `json:"port_1-tx_broadcast"` - Port3RxPackets FlexInt `json:"port_3-rx_packets"` - Port3RxBytes FlexInt `json:"port_3-rx_bytes"` - Port3TxPackets FlexInt `json:"port_3-tx_packets"` - Port3TxBytes FlexInt `json:"port_3-tx_bytes"` - Port3RxBroadcast FlexInt `json:"port_3-rx_broadcast"` - Port3TxMulticast FlexInt `json:"port_3-tx_multicast"` - Port3TxBroadcast FlexInt `json:"port_3-tx_broadcast"` - Port6RxPackets FlexInt `json:"port_6-rx_packets"` - Port6RxBytes FlexInt `json:"port_6-rx_bytes"` - Port6TxPackets FlexInt `json:"port_6-tx_packets"` - Port6TxBytes FlexInt `json:"port_6-tx_bytes"` - Port6RxMulticast FlexInt `json:"port_6-rx_multicast"` - Port6TxMulticast FlexInt `json:"port_6-tx_multicast"` - Port6TxBroadcast FlexInt `json:"port_6-tx_broadcast"` - Port7RxPackets FlexInt `json:"port_7-rx_packets"` - Port7RxBytes FlexInt `json:"port_7-rx_bytes"` - Port7TxPackets FlexInt `json:"port_7-tx_packets"` - Port7TxBytes FlexInt `json:"port_7-tx_bytes"` - Port7TxMulticast FlexInt `json:"port_7-tx_multicast"` - Port7TxBroadcast FlexInt `json:"port_7-tx_broadcast"` - Port9RxPackets FlexInt `json:"port_9-rx_packets"` - Port9RxBytes FlexInt `json:"port_9-rx_bytes"` - Port9TxPackets FlexInt `json:"port_9-tx_packets"` - Port9TxBytes FlexInt `json:"port_9-tx_bytes"` - Port9TxMulticast FlexInt `json:"port_9-tx_multicast"` - Port9TxBroadcast FlexInt `json:"port_9-tx_broadcast"` - Port10RxPackets FlexInt `json:"port_10-rx_packets"` - Port10RxBytes FlexInt `json:"port_10-rx_bytes"` - Port10TxPackets FlexInt `json:"port_10-tx_packets"` - Port10TxBytes FlexInt `json:"port_10-tx_bytes"` - Port10RxMulticast FlexInt `json:"port_10-rx_multicast"` - Port10TxMulticast FlexInt `json:"port_10-tx_multicast"` - Port10TxBroadcast FlexInt `json:"port_10-tx_broadcast"` - Port11RxPackets FlexInt `json:"port_11-rx_packets"` - Port11RxBytes FlexInt `json:"port_11-rx_bytes"` - Port11TxPackets FlexInt `json:"port_11-tx_packets"` - Port11TxBytes FlexInt `json:"port_11-tx_bytes"` - Port11TxMulticast FlexInt `json:"port_11-tx_multicast"` - Port11TxBroadcast FlexInt `json:"port_11-tx_broadcast"` - Port12RxPackets FlexInt `json:"port_12-rx_packets"` - Port12RxBytes FlexInt `json:"port_12-rx_bytes"` - Port12TxPackets FlexInt `json:"port_12-tx_packets"` - Port12TxBytes FlexInt `json:"port_12-tx_bytes"` - Port12TxMulticast FlexInt `json:"port_12-tx_multicast"` - Port12TxBroadcast FlexInt `json:"port_12-tx_broadcast"` - Port13RxPackets FlexInt `json:"port_13-rx_packets"` - Port13RxBytes FlexInt `json:"port_13-rx_bytes"` - Port13TxPackets FlexInt `json:"port_13-tx_packets"` - Port13TxBytes FlexInt `json:"port_13-tx_bytes"` - Port13RxMulticast FlexInt `json:"port_13-rx_multicast"` - Port13RxBroadcast FlexInt `json:"port_13-rx_broadcast"` - Port13TxMulticast FlexInt `json:"port_13-tx_multicast"` - Port13TxBroadcast FlexInt `json:"port_13-tx_broadcast"` - Port15RxPackets FlexInt `json:"port_15-rx_packets"` - Port15RxBytes FlexInt `json:"port_15-rx_bytes"` - Port15TxPackets FlexInt `json:"port_15-tx_packets"` - Port15TxBytes FlexInt `json:"port_15-tx_bytes"` - Port15RxBroadcast FlexInt `json:"port_15-rx_broadcast"` - Port15TxMulticast FlexInt `json:"port_15-tx_multicast"` - Port15TxBroadcast FlexInt `json:"port_15-tx_broadcast"` - Port16RxPackets FlexInt `json:"port_16-rx_packets"` - Port16RxBytes FlexInt `json:"port_16-rx_bytes"` - Port16TxPackets FlexInt `json:"port_16-tx_packets"` - Port16TxBytes FlexInt `json:"port_16-tx_bytes"` - Port16TxMulticast FlexInt `json:"port_16-tx_multicast"` - Port16TxBroadcast FlexInt `json:"port_16-tx_broadcast"` - Port17RxPackets FlexInt `json:"port_17-rx_packets"` - Port17RxBytes FlexInt `json:"port_17-rx_bytes"` - Port17TxPackets FlexInt `json:"port_17-tx_packets"` - Port17TxBytes FlexInt `json:"port_17-tx_bytes"` - Port17TxMulticast FlexInt `json:"port_17-tx_multicast"` - Port17TxBroadcast FlexInt `json:"port_17-tx_broadcast"` - Port18RxPackets FlexInt `json:"port_18-rx_packets"` - Port18RxBytes FlexInt `json:"port_18-rx_bytes"` - Port18TxPackets FlexInt `json:"port_18-tx_packets"` - Port18TxBytes FlexInt `json:"port_18-tx_bytes"` - Port18RxMulticast FlexInt `json:"port_18-rx_multicast"` - Port18TxMulticast FlexInt `json:"port_18-tx_multicast"` - Port18TxBroadcast FlexInt `json:"port_18-tx_broadcast"` - Port19RxPackets FlexInt `json:"port_19-rx_packets"` - Port19RxBytes FlexInt `json:"port_19-rx_bytes"` - Port19TxPackets FlexInt `json:"port_19-tx_packets"` - Port19TxBytes FlexInt `json:"port_19-tx_bytes"` - Port19TxMulticast FlexInt `json:"port_19-tx_multicast"` - Port19TxBroadcast FlexInt `json:"port_19-tx_broadcast"` - Port21RxPackets FlexInt `json:"port_21-rx_packets"` - Port21RxBytes FlexInt `json:"port_21-rx_bytes"` - Port21TxPackets FlexInt `json:"port_21-tx_packets"` - Port21TxBytes FlexInt `json:"port_21-tx_bytes"` - Port21RxBroadcast FlexInt `json:"port_21-rx_broadcast"` - Port21TxMulticast FlexInt `json:"port_21-tx_multicast"` - Port21TxBroadcast FlexInt `json:"port_21-tx_broadcast"` - Port22RxPackets FlexInt `json:"port_22-rx_packets"` - Port22RxBytes FlexInt `json:"port_22-rx_bytes"` - Port22TxPackets FlexInt `json:"port_22-tx_packets"` - Port22TxBytes FlexInt `json:"port_22-tx_bytes"` - Port22RxMulticast FlexInt `json:"port_22-rx_multicast"` - Port22TxMulticast FlexInt `json:"port_22-tx_multicast"` - Port22TxBroadcast FlexInt `json:"port_22-tx_broadcast"` - Port23RxPackets FlexInt `json:"port_23-rx_packets"` - Port23RxBytes FlexInt `json:"port_23-rx_bytes"` - Port23RxDropped FlexInt `json:"port_23-rx_dropped"` - Port23TxPackets FlexInt `json:"port_23-tx_packets"` - Port23TxBytes FlexInt `json:"port_23-tx_bytes"` - Port23RxMulticast FlexInt `json:"port_23-rx_multicast"` - Port23RxBroadcast FlexInt `json:"port_23-rx_broadcast"` - Port23TxMulticast FlexInt `json:"port_23-tx_multicast"` - Port23TxBroadcast FlexInt `json:"port_23-tx_broadcast"` - Port24RxPackets FlexInt `json:"port_24-rx_packets"` - Port24RxBytes FlexInt `json:"port_24-rx_bytes"` - Port24TxPackets FlexInt `json:"port_24-tx_packets"` - Port24TxBytes FlexInt `json:"port_24-tx_bytes"` - Port24RxMulticast FlexInt `json:"port_24-rx_multicast"` - Port24TxMulticast FlexInt `json:"port_24-tx_multicast"` - Port24TxBroadcast FlexInt `json:"port_24-tx_broadcast"` - Port1RxMulticast FlexInt `json:"port_1-rx_multicast"` - Port3RxDropped FlexInt `json:"port_3-rx_dropped"` - Port3RxMulticast FlexInt `json:"port_3-rx_multicast"` - Port6RxDropped FlexInt `json:"port_6-rx_dropped"` - Port7RxDropped FlexInt `json:"port_7-rx_dropped"` - Port7RxMulticast FlexInt `json:"port_7-rx_multicast"` - Port9RxDropped FlexInt `json:"port_9-rx_dropped"` - Port9RxMulticast FlexInt `json:"port_9-rx_multicast"` - Port9RxBroadcast FlexInt `json:"port_9-rx_broadcast"` - Port10RxBroadcast FlexInt `json:"port_10-rx_broadcast"` - Port12RxDropped FlexInt `json:"port_12-rx_dropped"` - Port12RxMulticast FlexInt `json:"port_12-rx_multicast"` - Port13RxDropped FlexInt `json:"port_13-rx_dropped"` - Port17RxDropped FlexInt `json:"port_17-rx_dropped"` - Port17RxMulticast FlexInt `json:"port_17-rx_multicast"` - Port17RxBroadcast FlexInt `json:"port_17-rx_broadcast"` - Port19RxDropped FlexInt `json:"port_19-rx_dropped"` - Port19RxMulticast FlexInt `json:"port_19-rx_multicast"` - Port19RxBroadcast FlexInt `json:"port_19-rx_broadcast"` - Port21RxDropped FlexInt `json:"port_21-rx_dropped"` - Port21RxMulticast FlexInt `json:"port_21-rx_multicast"` - Port7RxBroadcast FlexInt `json:"port_7-rx_broadcast"` - Port18RxBroadcast FlexInt `json:"port_18-rx_broadcast"` - Port16RxMulticast FlexInt `json:"port_16-rx_multicast"` - Port15RxDropped FlexInt `json:"port_15-rx_dropped"` - Port15RxMulticast FlexInt `json:"port_15-rx_multicast"` - Port16RxBroadcast FlexInt `json:"port_16-rx_broadcast"` - Port11RxBroadcast FlexInt `json:"port_11-rx_broadcast"` - Port12RxBroadcast FlexInt `json:"port_12-rx_broadcast"` - Port6RxBroadcast FlexInt `json:"port_6-rx_broadcast"` - Port24RxBroadcast FlexInt `json:"port_24-rx_broadcast"` - Port22RxBroadcast FlexInt `json:"port_22-rx_broadcast"` - Port10TxDropped FlexInt `json:"port_10-tx_dropped"` - Port16TxDropped FlexInt `json:"port_16-tx_dropped"` - Port1RxBroadcast FlexInt `json:"port_1-rx_broadcast"` - Port4RxPackets FlexInt `json:"port_4-rx_packets"` - Port4RxBytes FlexInt `json:"port_4-rx_bytes"` - Port4RxDropped FlexInt `json:"port_4-rx_dropped"` - Port4TxPackets FlexInt `json:"port_4-tx_packets"` - Port4TxBytes FlexInt `json:"port_4-tx_bytes"` - Port4TxDropped FlexInt `json:"port_4-tx_dropped"` - Port4RxMulticast FlexInt `json:"port_4-rx_multicast"` - Port4RxBroadcast FlexInt `json:"port_4-rx_broadcast"` - Port4TxMulticast FlexInt `json:"port_4-tx_multicast"` - Port4TxBroadcast FlexInt `json:"port_4-tx_broadcast"` - } `json:"stat"` - TxBytes FlexInt `json:"tx_bytes"` - RxBytes FlexInt `json:"rx_bytes"` - Bytes FlexInt `json:"bytes"` - NumSta FlexInt `json:"num_sta"` - UserNumSta FlexInt `json:"user-num_sta"` - GuestNumSta FlexInt `json:"guest-num_sta"` + UplinkDepth FlexInt `json:"uplink_depth"` + Stat *USWStat `json:"stat"` + TxBytes FlexInt `json:"tx_bytes"` + RxBytes FlexInt `json:"rx_bytes"` + Bytes FlexInt `json:"bytes"` + NumSta FlexInt `json:"num_sta"` + UserNumSta FlexInt `json:"user-num_sta"` + GuestNumSta FlexInt `json:"guest-num_sta"` +} + +// USWStat holds the "stat" data for a switch. +// This is split out because of a JSON data format change from 5.10 to 5.11. +type USWStat struct { + *sw +} + +type sw struct { + SiteID string `json:"site_id"` + O string `json:"o"` + Oid string `json:"oid"` + Sw string `json:"sw"` + Time FlexInt `json:"time"` + Datetime time.Time `json:"datetime"` + RxPackets FlexInt `json:"rx_packets"` + RxBytes FlexInt `json:"rx_bytes"` + RxErrors FlexInt `json:"rx_errors"` + RxDropped FlexInt `json:"rx_dropped"` + RxCrypts FlexInt `json:"rx_crypts"` + RxFrags FlexInt `json:"rx_frags"` + TxPackets FlexInt `json:"tx_packets"` + TxBytes FlexInt `json:"tx_bytes"` + TxErrors FlexInt `json:"tx_errors"` + TxDropped FlexInt `json:"tx_dropped"` + TxRetries FlexInt `json:"tx_retries"` + RxMulticast FlexInt `json:"rx_multicast"` + RxBroadcast FlexInt `json:"rx_broadcast"` + TxMulticast FlexInt `json:"tx_multicast"` + TxBroadcast FlexInt `json:"tx_broadcast"` + Bytes FlexInt `json:"bytes"` + Duration FlexInt `json:"duration"` + Port1RxPackets FlexInt `json:"port_1-rx_packets"` + Port1RxBytes FlexInt `json:"port_1-rx_bytes"` + Port1TxPackets FlexInt `json:"port_1-tx_packets"` + Port1TxBytes FlexInt `json:"port_1-tx_bytes"` + Port1TxMulticast FlexInt `json:"port_1-tx_multicast"` + Port1TxBroadcast FlexInt `json:"port_1-tx_broadcast"` + Port3RxPackets FlexInt `json:"port_3-rx_packets"` + Port3RxBytes FlexInt `json:"port_3-rx_bytes"` + Port3TxPackets FlexInt `json:"port_3-tx_packets"` + Port3TxBytes FlexInt `json:"port_3-tx_bytes"` + Port3RxBroadcast FlexInt `json:"port_3-rx_broadcast"` + Port3TxMulticast FlexInt `json:"port_3-tx_multicast"` + Port3TxBroadcast FlexInt `json:"port_3-tx_broadcast"` + Port6RxPackets FlexInt `json:"port_6-rx_packets"` + Port6RxBytes FlexInt `json:"port_6-rx_bytes"` + Port6TxPackets FlexInt `json:"port_6-tx_packets"` + Port6TxBytes FlexInt `json:"port_6-tx_bytes"` + Port6RxMulticast FlexInt `json:"port_6-rx_multicast"` + Port6TxMulticast FlexInt `json:"port_6-tx_multicast"` + Port6TxBroadcast FlexInt `json:"port_6-tx_broadcast"` + Port7RxPackets FlexInt `json:"port_7-rx_packets"` + Port7RxBytes FlexInt `json:"port_7-rx_bytes"` + Port7TxPackets FlexInt `json:"port_7-tx_packets"` + Port7TxBytes FlexInt `json:"port_7-tx_bytes"` + Port7TxMulticast FlexInt `json:"port_7-tx_multicast"` + Port7TxBroadcast FlexInt `json:"port_7-tx_broadcast"` + Port9RxPackets FlexInt `json:"port_9-rx_packets"` + Port9RxBytes FlexInt `json:"port_9-rx_bytes"` + Port9TxPackets FlexInt `json:"port_9-tx_packets"` + Port9TxBytes FlexInt `json:"port_9-tx_bytes"` + Port9TxMulticast FlexInt `json:"port_9-tx_multicast"` + Port9TxBroadcast FlexInt `json:"port_9-tx_broadcast"` + Port10RxPackets FlexInt `json:"port_10-rx_packets"` + Port10RxBytes FlexInt `json:"port_10-rx_bytes"` + Port10TxPackets FlexInt `json:"port_10-tx_packets"` + Port10TxBytes FlexInt `json:"port_10-tx_bytes"` + Port10RxMulticast FlexInt `json:"port_10-rx_multicast"` + Port10TxMulticast FlexInt `json:"port_10-tx_multicast"` + Port10TxBroadcast FlexInt `json:"port_10-tx_broadcast"` + Port11RxPackets FlexInt `json:"port_11-rx_packets"` + Port11RxBytes FlexInt `json:"port_11-rx_bytes"` + Port11TxPackets FlexInt `json:"port_11-tx_packets"` + Port11TxBytes FlexInt `json:"port_11-tx_bytes"` + Port11TxMulticast FlexInt `json:"port_11-tx_multicast"` + Port11TxBroadcast FlexInt `json:"port_11-tx_broadcast"` + Port12RxPackets FlexInt `json:"port_12-rx_packets"` + Port12RxBytes FlexInt `json:"port_12-rx_bytes"` + Port12TxPackets FlexInt `json:"port_12-tx_packets"` + Port12TxBytes FlexInt `json:"port_12-tx_bytes"` + Port12TxMulticast FlexInt `json:"port_12-tx_multicast"` + Port12TxBroadcast FlexInt `json:"port_12-tx_broadcast"` + Port13RxPackets FlexInt `json:"port_13-rx_packets"` + Port13RxBytes FlexInt `json:"port_13-rx_bytes"` + Port13TxPackets FlexInt `json:"port_13-tx_packets"` + Port13TxBytes FlexInt `json:"port_13-tx_bytes"` + Port13RxMulticast FlexInt `json:"port_13-rx_multicast"` + Port13RxBroadcast FlexInt `json:"port_13-rx_broadcast"` + Port13TxMulticast FlexInt `json:"port_13-tx_multicast"` + Port13TxBroadcast FlexInt `json:"port_13-tx_broadcast"` + Port15RxPackets FlexInt `json:"port_15-rx_packets"` + Port15RxBytes FlexInt `json:"port_15-rx_bytes"` + Port15TxPackets FlexInt `json:"port_15-tx_packets"` + Port15TxBytes FlexInt `json:"port_15-tx_bytes"` + Port15RxBroadcast FlexInt `json:"port_15-rx_broadcast"` + Port15TxMulticast FlexInt `json:"port_15-tx_multicast"` + Port15TxBroadcast FlexInt `json:"port_15-tx_broadcast"` + Port16RxPackets FlexInt `json:"port_16-rx_packets"` + Port16RxBytes FlexInt `json:"port_16-rx_bytes"` + Port16TxPackets FlexInt `json:"port_16-tx_packets"` + Port16TxBytes FlexInt `json:"port_16-tx_bytes"` + Port16TxMulticast FlexInt `json:"port_16-tx_multicast"` + Port16TxBroadcast FlexInt `json:"port_16-tx_broadcast"` + Port17RxPackets FlexInt `json:"port_17-rx_packets"` + Port17RxBytes FlexInt `json:"port_17-rx_bytes"` + Port17TxPackets FlexInt `json:"port_17-tx_packets"` + Port17TxBytes FlexInt `json:"port_17-tx_bytes"` + Port17TxMulticast FlexInt `json:"port_17-tx_multicast"` + Port17TxBroadcast FlexInt `json:"port_17-tx_broadcast"` + Port18RxPackets FlexInt `json:"port_18-rx_packets"` + Port18RxBytes FlexInt `json:"port_18-rx_bytes"` + Port18TxPackets FlexInt `json:"port_18-tx_packets"` + Port18TxBytes FlexInt `json:"port_18-tx_bytes"` + Port18RxMulticast FlexInt `json:"port_18-rx_multicast"` + Port18TxMulticast FlexInt `json:"port_18-tx_multicast"` + Port18TxBroadcast FlexInt `json:"port_18-tx_broadcast"` + Port19RxPackets FlexInt `json:"port_19-rx_packets"` + Port19RxBytes FlexInt `json:"port_19-rx_bytes"` + Port19TxPackets FlexInt `json:"port_19-tx_packets"` + Port19TxBytes FlexInt `json:"port_19-tx_bytes"` + Port19TxMulticast FlexInt `json:"port_19-tx_multicast"` + Port19TxBroadcast FlexInt `json:"port_19-tx_broadcast"` + Port21RxPackets FlexInt `json:"port_21-rx_packets"` + Port21RxBytes FlexInt `json:"port_21-rx_bytes"` + Port21TxPackets FlexInt `json:"port_21-tx_packets"` + Port21TxBytes FlexInt `json:"port_21-tx_bytes"` + Port21RxBroadcast FlexInt `json:"port_21-rx_broadcast"` + Port21TxMulticast FlexInt `json:"port_21-tx_multicast"` + Port21TxBroadcast FlexInt `json:"port_21-tx_broadcast"` + Port22RxPackets FlexInt `json:"port_22-rx_packets"` + Port22RxBytes FlexInt `json:"port_22-rx_bytes"` + Port22TxPackets FlexInt `json:"port_22-tx_packets"` + Port22TxBytes FlexInt `json:"port_22-tx_bytes"` + Port22RxMulticast FlexInt `json:"port_22-rx_multicast"` + Port22TxMulticast FlexInt `json:"port_22-tx_multicast"` + Port22TxBroadcast FlexInt `json:"port_22-tx_broadcast"` + Port23RxPackets FlexInt `json:"port_23-rx_packets"` + Port23RxBytes FlexInt `json:"port_23-rx_bytes"` + Port23RxDropped FlexInt `json:"port_23-rx_dropped"` + Port23TxPackets FlexInt `json:"port_23-tx_packets"` + Port23TxBytes FlexInt `json:"port_23-tx_bytes"` + Port23RxMulticast FlexInt `json:"port_23-rx_multicast"` + Port23RxBroadcast FlexInt `json:"port_23-rx_broadcast"` + Port23TxMulticast FlexInt `json:"port_23-tx_multicast"` + Port23TxBroadcast FlexInt `json:"port_23-tx_broadcast"` + Port24RxPackets FlexInt `json:"port_24-rx_packets"` + Port24RxBytes FlexInt `json:"port_24-rx_bytes"` + Port24TxPackets FlexInt `json:"port_24-tx_packets"` + Port24TxBytes FlexInt `json:"port_24-tx_bytes"` + Port24RxMulticast FlexInt `json:"port_24-rx_multicast"` + Port24TxMulticast FlexInt `json:"port_24-tx_multicast"` + Port24TxBroadcast FlexInt `json:"port_24-tx_broadcast"` + Port1RxMulticast FlexInt `json:"port_1-rx_multicast"` + Port3RxDropped FlexInt `json:"port_3-rx_dropped"` + Port3RxMulticast FlexInt `json:"port_3-rx_multicast"` + Port6RxDropped FlexInt `json:"port_6-rx_dropped"` + Port7RxDropped FlexInt `json:"port_7-rx_dropped"` + Port7RxMulticast FlexInt `json:"port_7-rx_multicast"` + Port9RxDropped FlexInt `json:"port_9-rx_dropped"` + Port9RxMulticast FlexInt `json:"port_9-rx_multicast"` + Port9RxBroadcast FlexInt `json:"port_9-rx_broadcast"` + Port10RxBroadcast FlexInt `json:"port_10-rx_broadcast"` + Port12RxDropped FlexInt `json:"port_12-rx_dropped"` + Port12RxMulticast FlexInt `json:"port_12-rx_multicast"` + Port13RxDropped FlexInt `json:"port_13-rx_dropped"` + Port17RxDropped FlexInt `json:"port_17-rx_dropped"` + Port17RxMulticast FlexInt `json:"port_17-rx_multicast"` + Port17RxBroadcast FlexInt `json:"port_17-rx_broadcast"` + Port19RxDropped FlexInt `json:"port_19-rx_dropped"` + Port19RxMulticast FlexInt `json:"port_19-rx_multicast"` + Port19RxBroadcast FlexInt `json:"port_19-rx_broadcast"` + Port21RxDropped FlexInt `json:"port_21-rx_dropped"` + Port21RxMulticast FlexInt `json:"port_21-rx_multicast"` + Port7RxBroadcast FlexInt `json:"port_7-rx_broadcast"` + Port18RxBroadcast FlexInt `json:"port_18-rx_broadcast"` + Port16RxMulticast FlexInt `json:"port_16-rx_multicast"` + Port15RxDropped FlexInt `json:"port_15-rx_dropped"` + Port15RxMulticast FlexInt `json:"port_15-rx_multicast"` + Port16RxBroadcast FlexInt `json:"port_16-rx_broadcast"` + Port11RxBroadcast FlexInt `json:"port_11-rx_broadcast"` + Port12RxBroadcast FlexInt `json:"port_12-rx_broadcast"` + Port6RxBroadcast FlexInt `json:"port_6-rx_broadcast"` + Port24RxBroadcast FlexInt `json:"port_24-rx_broadcast"` + Port22RxBroadcast FlexInt `json:"port_22-rx_broadcast"` + Port10TxDropped FlexInt `json:"port_10-tx_dropped"` + Port16TxDropped FlexInt `json:"port_16-tx_dropped"` + Port1RxBroadcast FlexInt `json:"port_1-rx_broadcast"` + Port4RxPackets FlexInt `json:"port_4-rx_packets"` + Port4RxBytes FlexInt `json:"port_4-rx_bytes"` + Port4RxDropped FlexInt `json:"port_4-rx_dropped"` + Port4TxPackets FlexInt `json:"port_4-tx_packets"` + Port4TxBytes FlexInt `json:"port_4-tx_bytes"` + Port4TxDropped FlexInt `json:"port_4-tx_dropped"` + Port4RxMulticast FlexInt `json:"port_4-rx_multicast"` + Port4RxBroadcast FlexInt `json:"port_4-rx_broadcast"` + Port4TxMulticast FlexInt `json:"port_4-tx_multicast"` + Port4TxBroadcast FlexInt `json:"port_4-tx_broadcast"` +} + +// UnmarshalJSON unmarshalls 5.10 or 5.11 formatted Switch Stat data. +func (v *USWStat) UnmarshalJSON(data []byte) error { + var n struct { + sw `json:"sw"` + } + v.sw = &n.sw + err := json.Unmarshal(data, v.sw) // controller version 5.10. + if err != nil { + return json.Unmarshal(data, &n) // controller version 5.11. + } + return nil } diff --git a/core/unifi/usw_type_test.go b/core/unifi/usw_type_test.go new file mode 100644 index 00000000..a8220271 --- /dev/null +++ b/core/unifi/usw_type_test.go @@ -0,0 +1,93 @@ +package unifi + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUSWUnmarshalJSON(t *testing.T) { + testcontroller511 := `{ + "sw": { + "site_id": "mySite", + "o": "sw", + "oid": "00:00:00:00:00:00", + "sw": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:40:00Z", + "rx_packets": 321, + "rx_bytes": 321, + "rx_errors": 123, + "rx_dropped": 123, + "rx_crypts": 123, + "rx_frags": 123, + "tx_packets": 123, + "tx_bytes": 123, + "tx_errors": 0, + "tx_dropped": 0, + "tx_retries": 0, + "rx_multicast": 123, + "rx_broadcast": 123, + "tx_multicast": 123, + "tx_broadcast": 123, + "bytes": 123, + "duration": 123, + "port_1-tx_packets": 123, + "port_1-tx_bytes": 123, + "port_1-tx_multicast": 123, + "port_1-tx_broadcast": 123, + "port_1-rx_packets": 123, + "port_1-rx_bytes": 123, + "port_1-rx_dropped": 123, + "port_1-rx_multicast": 123, + "port_1-rx_broadcast": 123, + "port_1-rx_errors": 123}}` + + testcontroller510 := `{ + "site_id": "mySite", + "o": "sw", + "oid": "00:00:00:00:00:00", + "sw": "00:00:00:00:00:00", + "time": 1577742600000, + "datetime": "2019-12-30T09:40:00Z", + "rx_packets": 321, + "rx_bytes": 321, + "rx_errors": 123, + "rx_dropped": 123, + "rx_crypts": 123, + "rx_frags": 123, + "tx_packets": 123, + "tx_bytes": 123, + "tx_errors": 0, + "tx_dropped": 0, + "tx_retries": 0, + "rx_multicast": 123, + "rx_broadcast": 123, + "tx_multicast": 123, + "tx_broadcast": 123, + "bytes": 123, + "duration": 123, + "port_1-tx_packets": 123, + "port_1-tx_bytes": 123, + "port_1-tx_multicast": 123, + "port_1-tx_broadcast": 123, + "port_1-rx_packets": 123, + "port_1-rx_bytes": 123, + "port_1-rx_dropped": 123, + "port_1-rx_multicast": 123, + "port_1-rx_broadcast": 123, + "port_1-rx_errors": 123}` + + t.Parallel() + a := assert.New(t) + + u := &USWStat{} + err := u.UnmarshalJSON([]byte(testcontroller510)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(123), u.RxMulticast.Val, "data was not properly unmarshaled") + + u = &USWStat{} // reset + err = u.UnmarshalJSON([]byte(testcontroller511)) + a.Nil(err, "must be no error unmarshaling test strings") + a.Equal(float64(123), u.RxMulticast.Val, "data was not properly unmarshaled") +}