Merge pull request #32 from golift/dn2_updates

Add DPI data
This commit is contained in:
David Newhall II 2019-12-27 20:42:53 -08:00 committed by GitHub
commit 92b79d50c5
12 changed files with 2592 additions and 224 deletions

View File

@ -1,15 +1,11 @@
language: go language: go
go: go:
- 1.12.x - 1.13.x
before_install: before_install:
- mkdir -p $GOPATH/bin
# Download the `dep` binary to bin folder in $GOPATH
- curl -sLo $GOPATH/bin/dep https://github.com/golang/dep/releases/download/v0.5.3/dep-linux-amd64
- chmod +x $GOPATH/bin/dep
# download super-linter: golangci-lint # download super-linter: golangci-lint
- curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin latest - curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin latest
install: install:
- dep ensure - go mod vendor
script: script:
- golangci-lint run --enable-all -e G402 - golangci-lint run --enable-all -e G402 -D gochecknoglobals
- go test ./... - go test ./...

41
core/unifi/Gopkg.lock generated
View File

@ -1,41 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
[[projects]]
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = "UT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:8548c309c65a85933a625be5e7d52b6ac927ca30c56869fae58123b8a77a75e1"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = "UT"
revision = "221dbe5ed46703ee255b1da0dec05086f5035f62"
version = "v1.4.0"
[[projects]]
digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
version = "v2.2.2"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = ["github.com/stretchr/testify/assert"]
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -1,3 +0,0 @@
[prune]
go-tests = true
unused-packages = true

View File

@ -5,9 +5,13 @@ an authenticated http Client you may use to query the device for data. Also
contains some built-in methods for de-serializing common client and device contains some built-in methods for de-serializing common client and device
data. The data is provided in a large struct you can consume in your application. data. The data is provided in a large struct you can consume in your application.
If more features are requested, I'll certainly consider them. Do you need to do This library is designed to PULL data FROM the controller. It has no methods that
more than just collect data? [Let me know](https://github.com/golift/unifi/issues/new)! update settings or change things on the controller.
Pull requests and feedback are welcomed! [Someone expressed interest](https://github.com/golift/unifi/issues/31) in
adding methods to update data, and I'm okay with that. I'll even help add them.
[Tell me what you want to do](https://github.com/golift/unifi/issues/new), and we'll make it happen.
Pull requests, feature requests, code reviews and feedback are welcomed!
Here's a working example: Here's a working example:
```golang ```golang

View File

@ -1,6 +1,8 @@
package unifi package unifi
import "fmt" import (
"fmt"
)
// GetClients returns a response full of clients' data from the UniFi Controller. // GetClients returns a response full of clients' data from the UniFi Controller.
func (u *Unifi) GetClients(sites Sites) (Clients, error) { func (u *Unifi) GetClients(sites Sites) (Clients, error) {
@ -34,6 +36,32 @@ func (u *Unifi) GetClients(sites Sites) (Clients, error) {
return data, nil return data, nil
} }
// GetClientsDPI garners dpi data for clients.
func (u *Unifi) GetClientsDPI(sites Sites) ([]*DPITable, error) {
var data []*DPITable
for _, site := range sites {
u.DebugLog("Polling Controller, retreiving Client DPI data, site %s (%s) ", site.Name, site.Desc)
var response struct {
Data []*DPITable `json:"data"`
}
clientDPIpath := fmt.Sprintf(APIClientDPI, site.Name)
if err := u.GetData(clientDPIpath, &response, `{"type":"by_app"}`); err != nil {
return nil, err
}
for _, d := range response.Data {
d.SourceName = site.SourceName
d.SiteName = site.SiteName
data = append(data, d)
}
}
return data, nil
}
// Clients contains a list that contains all of the unifi clients from a controller. // Clients contains a list that contains all of the unifi clients from a controller.
type Clients []*Client type Clients []*Client
@ -55,15 +83,6 @@ type Client struct {
DevVendor FlexInt `json:"dev_vendor,omitempty"` DevVendor FlexInt `json:"dev_vendor,omitempty"`
DhcpendTime int `json:"dhcpend_time,omitempty"` DhcpendTime int `json:"dhcpend_time,omitempty"`
Satisfaction FlexInt `json:"satisfaction,omitempty"` Satisfaction FlexInt `json:"satisfaction,omitempty"`
DpiStats struct {
App FlexInt
Cat FlexInt
RxBytes FlexInt
RxPackets FlexInt
TxBytes FlexInt
TxPackets FlexInt
} `json:"dpi_stats"`
DpiStatsLastUpdated int64 `json:"dpi_stats_last_updated"`
Essid string `json:"essid"` Essid string `json:"essid"`
FirstSeen int64 `json:"first_seen"` FirstSeen int64 `json:"first_seen"`
FixedIP string `json:"fixed_ip"` FixedIP string `json:"fixed_ip"`

2366
core/unifi/dpi.go Normal file

File diff suppressed because it is too large Load Diff

9
core/unifi/go.mod Normal file
View File

@ -0,0 +1,9 @@
module golift.io/unifi
go 1.13
require (
github.com/davecgh/go-spew v1.1.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/testify v1.4.0
)

11
core/unifi/go.sum Normal file
View File

@ -0,0 +1,11 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

View File

@ -1,6 +1,9 @@
package unifi package unifi
import "strings" import (
"fmt"
"strings"
)
// GetSites returns a list of configured sites on the UniFi controller. // GetSites returns a list of configured sites on the UniFi controller.
func (u *Unifi) GetSites() (Sites, error) { func (u *Unifi) GetSites() (Sites, error) {
@ -29,6 +32,36 @@ func (u *Unifi) GetSites() (Sites, error) {
return response.Data, nil return response.Data, nil
} }
// GetSiteDPI garners dpi data for sites.
func (u *Unifi) GetSiteDPI(sites Sites) ([]*DPITable, error) {
data := []*DPITable{}
for _, site := range sites {
u.DebugLog("Polling Controller, retreiving Site DPI data, site %s (%s) ", site.Name, site.Desc)
var response struct {
Data []*DPITable `json:"data"`
}
siteDPIpath := fmt.Sprintf(APISiteDPI, site.Name)
if err := u.GetData(siteDPIpath, &response, `{"type":"by_app"}`); err != nil {
return nil, err
}
if l := len(response.Data); l > 1 {
return nil, fmt.Errorf("dpi data table contains more than 1 item; please open a bug report")
} else if l != 1 {
continue
}
response.Data[0].SourceName = site.SourceName
response.Data[0].SiteName = site.SiteName
data = append(data, response.Data[0])
}
return data, nil
}
// Sites is a struct to match Devices and Clients. // Sites is a struct to match Devices and Clients.
type Sites []*Site type Sites []*Site

View File

@ -15,6 +15,10 @@ const (
APIStatusPath string = "/status" APIStatusPath string = "/status"
// APISiteList is the path to the api site list. // APISiteList is the path to the api site list.
APISiteList string = "/api/stat/sites" APISiteList string = "/api/stat/sites"
// APISiteDPI is site DPI data.
APISiteDPI string = "/api/s/%s/stat/sitedpi"
// APISiteDPI is site DPI data.
APIClientDPI string = "/api/s/%s/stat/stadpi"
// APIClientPath is Unifi Clients API Path // APIClientPath is Unifi Clients API Path
APIClientPath string = "/api/s/%s/stat/sta" APIClientPath string = "/api/s/%s/stat/sta"
// APIDevicePath is where we get data about Unifi devices. // APIDevicePath is where we get data about Unifi devices.

View File

@ -167,7 +167,6 @@ type NetworkTable []struct {
IsGuest FlexBool `json:"is_guest"` IsGuest FlexBool `json:"is_guest"`
IP string `json:"ip"` IP string `json:"ip"`
Up FlexBool `json:"up"` Up FlexBool `json:"up"`
DPIStatsTable DPIStatsTable `json:"dpistats_table,omitempty"`
NumSta FlexInt `json:"num_sta"` NumSta FlexInt `json:"num_sta"`
RxBytes FlexInt `json:"rx_bytes"` RxBytes FlexInt `json:"rx_bytes"`
RxPackets FlexInt `json:"rx_packets"` RxPackets FlexInt `json:"rx_packets"`
@ -175,35 +174,6 @@ type NetworkTable []struct {
TxPackets FlexInt `json:"tx_packets"` TxPackets FlexInt `json:"tx_packets"`
} }
// DPIStatsTable is the Deep Packet Inspection data for each "network"
type DPIStatsTable struct {
LastUpdated FlexInt `json:"last_updated"`
ByCat []struct {
Cat FlexInt `json:"cat"`
Apps []FlexInt `json:"apps"`
RxBytes FlexInt `json:"rx_bytes"`
TxBytes FlexInt `json:"tx_bytes"`
RxPackets FlexInt `json:"rx_packets"`
TxPackets FlexInt `json:"tx_packets"`
} `json:"by_cat"`
ByApp []struct {
App FlexInt `json:"app"`
Cat FlexInt `json:"cat"`
Clients []struct {
Mac string `json:"mac"`
RxBytes FlexInt `json:"rx_bytes"`
TxBytes FlexInt `json:"tx_bytes"`
RxPackets FlexInt `json:"rx_packets"`
TxPackets FlexInt `json:"tx_packets"`
} `json:"clients"`
KnownClients FlexInt `json:"known_clients"`
RxBytes FlexInt `json:"rx_bytes"`
TxBytes FlexInt `json:"tx_bytes"`
RxPackets FlexInt `json:"rx_packets"`
TxPackets FlexInt `json:"tx_packets"`
} `json:"by_app"`
}
// UDMStat holds the "stat" data for a dream machine. // UDMStat holds the "stat" data for a dream machine.
// A dream machine is a USG + USW + Controller // A dream machine is a USG + USW + Controller
type UDMStat struct { type UDMStat struct {

View File

@ -97,10 +97,10 @@ func (u *Unifi) GetServerData() error {
} }
// GetData makes a unifi request and unmarshals the response into a provided pointer. // GetData makes a unifi request and unmarshals the response into a provided pointer.
func (u *Unifi) GetData(apiPath string, v interface{}) error { func (u *Unifi) GetData(apiPath string, v interface{}, params ...string) error {
start := time.Now() start := time.Now()
body, err := u.GetJSON(apiPath) body, err := u.GetJSON(apiPath, params...)
if err != nil { if err != nil {
return err return err
} }
@ -134,8 +134,8 @@ func (u *Unifi) UniReq(apiPath string, params string) (req *http.Request, err er
} }
// GetJSON returns the raw JSON from a path. This is useful for debugging. // GetJSON returns the raw JSON from a path. This is useful for debugging.
func (u *Unifi) GetJSON(apiPath string) ([]byte, error) { func (u *Unifi) GetJSON(apiPath string, params ...string) ([]byte, error) {
req, err := u.UniReq(apiPath, "") req, err := u.UniReq(apiPath, strings.Join(params, " "))
if err != nil { if err != nil {
return []byte{}, err return []byte{}, err
} }