add v4 folder
This commit is contained in:
parent
92b79d50c5
commit
115ee799a3
|
|
@ -0,0 +1,23 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2019 Go Lift - Building Strong Go Tools
|
||||||
|
Copyright (c) 2018 David Newhall II
|
||||||
|
Copyright (c) 2016 Garrett Bjerkhoel
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Go Library: `unifi`
|
||||||
|
|
||||||
|
It connects to a Unifi Controller, given a url, username and password. Returns
|
||||||
|
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
|
||||||
|
data. The data is provided in a large struct you can consume in your application.
|
||||||
|
|
||||||
|
This library is designed to PULL data FROM the controller. It has no methods that
|
||||||
|
update settings or change things on the controller.
|
||||||
|
[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:
|
||||||
|
```golang
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "log"
|
||||||
|
import "golift.io/unifi"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
c := *unifi.Config{
|
||||||
|
User: "admin",
|
||||||
|
Pass: "superSecret1234",
|
||||||
|
URL: "https://127.0.0.1:8443/",
|
||||||
|
// Log with log.Printf or make your own interface that accepts (msg, fmt)
|
||||||
|
ErrorLog: log.Printf,
|
||||||
|
DebugLog: log.Printf,
|
||||||
|
}
|
||||||
|
uni, err := unifi.NewUnifi(c)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sites, err := uni.GetSites()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error:", err)
|
||||||
|
}
|
||||||
|
clients, err := uni.GetClients(sites)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error:", err)
|
||||||
|
}
|
||||||
|
devices, err := uni.GetDevices(sites)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Error:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(len(sites), "Unifi Sites Found: ", sites)
|
||||||
|
log.Println(len(clients), "Clients connected:")
|
||||||
|
for i, client := range clients {
|
||||||
|
log.Println(i+1, client.ID, client.Hostname, client.IP, client.Name, client.LastSeen)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println(len(devices.USWs), "Unifi Switches Found")
|
||||||
|
log.Println(len(devices.USGs), "Unifi Gateways Found")
|
||||||
|
|
||||||
|
log.Println(len(devices.UAPs), "Unifi Wireless APs Found:")
|
||||||
|
for i, uap := range devices.UAPs {
|
||||||
|
log.Println(i+1, uap.Name, uap.IP)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetClients returns a response full of clients' data from the UniFi Controller.
|
||||||
|
func (u *Unifi) GetClients(sites Sites) (Clients, error) {
|
||||||
|
data := make([]*Client, 0)
|
||||||
|
|
||||||
|
for _, site := range sites {
|
||||||
|
var response struct {
|
||||||
|
Data []*Client `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
u.DebugLog("Polling Controller, retreiving UniFi Clients, site %s (%s) ", site.Name, site.Desc)
|
||||||
|
|
||||||
|
clientPath := fmt.Sprintf(APIClientPath, site.Name)
|
||||||
|
if err := u.GetData(clientPath, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, d := range response.Data {
|
||||||
|
// Add special SourceName value.
|
||||||
|
response.Data[i].SourceName = u.URL
|
||||||
|
// Add the special "Site Name" to each client. This becomes a Grafana filter somewhere.
|
||||||
|
response.Data[i].SiteName = site.Desc + " (" + site.Name + ")"
|
||||||
|
// Fix name and hostname fields. Sometimes one or the other is blank.
|
||||||
|
response.Data[i].Hostname = pick(d.Hostname, d.Name, d.Mac)
|
||||||
|
response.Data[i].Name = pick(d.Name, d.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, response.Data...)
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
type Clients []*Client
|
||||||
|
|
||||||
|
// Client defines all the data a connected-network client contains.
|
||||||
|
type Client struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
Anomalies int64 `json:"anomalies,omitempty"`
|
||||||
|
ApMac string `json:"ap_mac"`
|
||||||
|
ApName string `json:"-"`
|
||||||
|
AssocTime int64 `json:"assoc_time"`
|
||||||
|
Blocked bool `json:"blocked,omitempty"`
|
||||||
|
Bssid string `json:"bssid"`
|
||||||
|
BytesR int64 `json:"bytes-r"`
|
||||||
|
Ccq int64 `json:"ccq"`
|
||||||
|
Channel FlexInt `json:"channel"`
|
||||||
|
DevCat FlexInt `json:"dev_cat"`
|
||||||
|
DevFamily FlexInt `json:"dev_family"`
|
||||||
|
DevID FlexInt `json:"dev_id"`
|
||||||
|
DevVendor FlexInt `json:"dev_vendor,omitempty"`
|
||||||
|
DhcpendTime int `json:"dhcpend_time,omitempty"`
|
||||||
|
Satisfaction FlexInt `json:"satisfaction,omitempty"`
|
||||||
|
Essid string `json:"essid"`
|
||||||
|
FirstSeen int64 `json:"first_seen"`
|
||||||
|
FixedIP string `json:"fixed_ip"`
|
||||||
|
GwMac string `json:"gw_mac"`
|
||||||
|
GwName string `json:"-"`
|
||||||
|
Hostname string `json:"hostname"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
IdleTime int64 `json:"idle_time"`
|
||||||
|
Is11R FlexBool `json:"is_11r"`
|
||||||
|
IsGuest FlexBool `json:"is_guest"`
|
||||||
|
IsGuestByUAP FlexBool `json:"_is_guest_by_uap"`
|
||||||
|
IsGuestByUGW FlexBool `json:"_is_guest_by_ugw"`
|
||||||
|
IsGuestByUSW FlexBool `json:"_is_guest_by_usw"`
|
||||||
|
IsWired FlexBool `json:"is_wired"`
|
||||||
|
LastSeen int64 `json:"last_seen"`
|
||||||
|
LastSeenByUAP int64 `json:"_last_seen_by_uap"`
|
||||||
|
LastSeenByUGW int64 `json:"_last_seen_by_ugw"`
|
||||||
|
LastSeenByUSW int64 `json:"_last_seen_by_usw"`
|
||||||
|
LatestAssocTime int64 `json:"latest_assoc_time"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Network string `json:"network"`
|
||||||
|
NetworkID string `json:"network_id"`
|
||||||
|
Noise int64 `json:"noise"`
|
||||||
|
Note string `json:"note"`
|
||||||
|
Noted FlexBool `json:"noted"`
|
||||||
|
OsClass FlexInt `json:"os_class"`
|
||||||
|
OsName FlexInt `json:"os_name"`
|
||||||
|
Oui string `json:"oui"`
|
||||||
|
PowersaveEnabled FlexBool `json:"powersave_enabled"`
|
||||||
|
QosPolicyApplied FlexBool `json:"qos_policy_applied"`
|
||||||
|
Radio string `json:"radio"`
|
||||||
|
RadioName string `json:"radio_name"`
|
||||||
|
RadioProto string `json:"radio_proto"`
|
||||||
|
RadioDescription string `json:"-"`
|
||||||
|
RoamCount int64 `json:"roam_count"`
|
||||||
|
Rssi int64 `json:"rssi"`
|
||||||
|
RxBytes int64 `json:"rx_bytes"`
|
||||||
|
RxBytesR int64 `json:"rx_bytes-r"`
|
||||||
|
RxPackets int64 `json:"rx_packets"`
|
||||||
|
RxRate int64 `json:"rx_rate"`
|
||||||
|
Signal int64 `json:"signal"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
SwDepth int `json:"sw_depth"`
|
||||||
|
SwMac string `json:"sw_mac"`
|
||||||
|
SwName string `json:"-"`
|
||||||
|
SwPort FlexInt `json:"sw_port"`
|
||||||
|
TxBytes int64 `json:"tx_bytes"`
|
||||||
|
TxBytesR int64 `json:"tx_bytes-r"`
|
||||||
|
TxPackets int64 `json:"tx_packets"`
|
||||||
|
TxRetries int64 `json:"tx_retries"`
|
||||||
|
TxPower int64 `json:"tx_power"`
|
||||||
|
TxRate int64 `json:"tx_rate"`
|
||||||
|
Uptime int64 `json:"uptime"`
|
||||||
|
UptimeByUAP int64 `json:"_uptime_by_uap"`
|
||||||
|
UptimeByUGW int64 `json:"_uptime_by_ugw"`
|
||||||
|
UptimeByUSW int64 `json:"_uptime_by_usw"`
|
||||||
|
UseFixedIP FlexBool `json:"use_fixedip"`
|
||||||
|
UserGroupID string `json:"usergroup_id"`
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
Vlan FlexInt `json:"vlan"`
|
||||||
|
WifiTxAttempts int64 `json:"wifi_tx_attempts"`
|
||||||
|
WiredRxBytes int64 `json:"wired-rx_bytes"`
|
||||||
|
WiredRxBytesR int64 `json:"wired-rx_bytes-r"`
|
||||||
|
WiredRxPackets int64 `json:"wired-rx_packets"`
|
||||||
|
WiredTxBytes int64 `json:"wired-tx_bytes"`
|
||||||
|
WiredTxBytesR int64 `json:"wired-tx_bytes-r"`
|
||||||
|
WiredTxPackets int64 `json:"wired-tx_packets"`
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetDevices returns a response full of devices' data from the UniFi Controller.
|
||||||
|
func (u *Unifi) GetDevices(sites Sites) (*Devices, error) {
|
||||||
|
devices := new(Devices)
|
||||||
|
|
||||||
|
for _, site := range sites {
|
||||||
|
var response struct {
|
||||||
|
Data []json.RawMessage `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
devicePath := fmt.Sprintf(APIDevicePath, site.Name)
|
||||||
|
if err := u.GetData(devicePath, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
loopDevices := u.parseDevices(response.Data, site.SiteName)
|
||||||
|
devices.UAPs = append(devices.UAPs, loopDevices.UAPs...)
|
||||||
|
devices.USGs = append(devices.USGs, loopDevices.USGs...)
|
||||||
|
devices.USWs = append(devices.USWs, loopDevices.USWs...)
|
||||||
|
devices.UDMs = append(devices.UDMs, loopDevices.UDMs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseDevices parses the raw JSON from the Unifi Controller into device structures.
|
||||||
|
func (u *Unifi) parseDevices(data []json.RawMessage, siteName string) *Devices {
|
||||||
|
devices := new(Devices)
|
||||||
|
|
||||||
|
for _, r := range data {
|
||||||
|
// Loop each item in the raw JSON message, detect its type and unmarshal it.
|
||||||
|
assetType := "<type key missing>"
|
||||||
|
|
||||||
|
if o := make(map[string]interface{}); u.unmarshalDevice("map", r, &o) != nil {
|
||||||
|
continue
|
||||||
|
} else if t, ok := o["type"].(string); ok {
|
||||||
|
assetType = t
|
||||||
|
}
|
||||||
|
|
||||||
|
u.DebugLog("Unmarshalling Device Type: %v, site %s ", assetType, siteName)
|
||||||
|
// Choose which type to unmarshal into based on the "type" json key.
|
||||||
|
|
||||||
|
switch assetType { // Unmarshal again into the correct type..
|
||||||
|
case "uap":
|
||||||
|
dev := &UAP{SiteName: siteName, SourceName: u.URL}
|
||||||
|
if u.unmarshalDevice(assetType, r, dev) == nil {
|
||||||
|
dev.Name = pick(dev.Name, dev.Mac)
|
||||||
|
devices.UAPs = append(devices.UAPs, dev)
|
||||||
|
}
|
||||||
|
case "ugw", "usg": // in case they ever fix the name in the api.
|
||||||
|
dev := &USG{SiteName: siteName, SourceName: u.URL}
|
||||||
|
if u.unmarshalDevice(assetType, r, dev) == nil {
|
||||||
|
dev.Name = pick(dev.Name, dev.Mac)
|
||||||
|
devices.USGs = append(devices.USGs, dev)
|
||||||
|
}
|
||||||
|
case "usw":
|
||||||
|
dev := &USW{SiteName: siteName, SourceName: u.URL}
|
||||||
|
if u.unmarshalDevice(assetType, r, dev) == nil {
|
||||||
|
dev.Name = pick(dev.Name, dev.Mac)
|
||||||
|
devices.USWs = append(devices.USWs, dev)
|
||||||
|
}
|
||||||
|
case "udm":
|
||||||
|
dev := &UDM{SiteName: siteName, SourceName: u.URL}
|
||||||
|
if u.unmarshalDevice(assetType, r, dev) == nil {
|
||||||
|
dev.Name = pick(dev.Name, dev.Mac)
|
||||||
|
devices.UDMs = append(devices.UDMs, dev)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
u.ErrorLog("unknown asset type - %v - skipping", assetType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmarshalDevice handles logging for the unmarshal operations in parseDevices().
|
||||||
|
func (u *Unifi) unmarshalDevice(dev string, data json.RawMessage, v interface{}) (err error) {
|
||||||
|
if err = json.Unmarshal(data, v); err != nil {
|
||||||
|
u.ErrorLog("json.Unmarshal(%v): %v", dev, err)
|
||||||
|
u.ErrorLog("Enable Debug Logging to output the failed payload.")
|
||||||
|
|
||||||
|
json, err := data.MarshalJSON()
|
||||||
|
u.DebugLog("Failed Payload: %s (marshal err: %v)", json, err)
|
||||||
|
u.DebugLog("The above payload can prove useful during torubleshooting when you open an Issue:")
|
||||||
|
u.DebugLog("==- https://github.com/golift/unifi/issues/new -==")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// pick returns the first non empty string in a list.
|
||||||
|
// used in a few places around this library.
|
||||||
|
func pick(strings ...string) string {
|
||||||
|
for _, s := range strings {
|
||||||
|
if s != "" {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Usage:
|
||||||
|
# ./convert.sh <file> [prefix]
|
||||||
|
# <file> should contain a go struct, like uap_type.go
|
||||||
|
# It converts the go struct to an influx thing, like you see in uap_influx.go.
|
||||||
|
# [prefix] is optional. I used it to do all the stat_ uap metrics.
|
||||||
|
# Very crude, just helps skip a lot of copy/paste.
|
||||||
|
#
|
||||||
|
path=$1
|
||||||
|
pre=$2
|
||||||
|
|
||||||
|
# Reads in the file one line at a time.
|
||||||
|
while IFS='' read -r line; do
|
||||||
|
# Split each piece of the file out.
|
||||||
|
name=$(echo "${line}" | awk '{print $1}')
|
||||||
|
type=$(echo "${line}" | awk '{print $2}')
|
||||||
|
json=$(echo "${line}" | awk '{print $3}')
|
||||||
|
json=$(echo "${json}" | cut -d\" -f2)
|
||||||
|
|
||||||
|
# Don't print junk lines. (it still prints some junk lines)
|
||||||
|
if [ "$json" != "" ]; then
|
||||||
|
# Add a .Val suffix if this is a FlexInt or FlexBool.
|
||||||
|
[[ "$type" = Flex* ]] && suf=.Val
|
||||||
|
echo "\"${pre}${json}\": u.Stat.${name}${suf},"
|
||||||
|
fi
|
||||||
|
done < ${path}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
"_id": "5d2416c78f0385ccf1c6df44",
|
||||||
|
"archived": false,
|
||||||
|
"timestamp": 1562646211,
|
||||||
|
"flow_id": 1591464006222389,
|
||||||
|
"in_iface": "eth1",
|
||||||
|
"event_type": "alert",
|
||||||
|
"src_ip": "196.196.244.84",
|
||||||
|
"src_mac": "f0:9f:c2:c4:bb:f1",
|
||||||
|
"src_port": 51413,
|
||||||
|
"dest_ip": "192.168.3.2",
|
||||||
|
"dst_mac": "40:a8:f0:68:c3:58",
|
||||||
|
"dest_port": 36881,
|
||||||
|
"proto": "UDP",
|
||||||
|
"app_proto": "failed",
|
||||||
|
"host": "f0:22:22:22:22:22",
|
||||||
|
"usgip": "11.22.33.44",
|
||||||
|
"unique_alertid": "1341902566-2019-07-08T21:23:31.229941-0700",
|
||||||
|
"srcipCountry": "SE",
|
||||||
|
"dstipCountry": false,
|
||||||
|
"usgipCountry": "US",
|
||||||
|
"srcipGeo": {
|
||||||
|
"continent_code": "EU",
|
||||||
|
"country_code": "SE",
|
||||||
|
"country_code3": "SWE",
|
||||||
|
"country_name": "Sweden",
|
||||||
|
"region": "26",
|
||||||
|
"city": "Stockholm",
|
||||||
|
"postal_code": "168 65",
|
||||||
|
"latitude": 59.349998474121094,
|
||||||
|
"longitude": 17.91670036315918,
|
||||||
|
"dma_code": 0,
|
||||||
|
"area_code": 0
|
||||||
|
},
|
||||||
|
"dstipGeo": false,
|
||||||
|
"usgipGeo": {
|
||||||
|
"continent_code": "NA",
|
||||||
|
"country_code": "US",
|
||||||
|
"country_code3": "USA",
|
||||||
|
"country_name": "United States",
|
||||||
|
"region": "CA",
|
||||||
|
"city": "Other",
|
||||||
|
"postal_code": "99999",
|
||||||
|
"latitude": 99.139400482177734,
|
||||||
|
"longitude": -99.39669799804688,
|
||||||
|
"dma_code": 862,
|
||||||
|
"area_code": 999
|
||||||
|
},
|
||||||
|
"srcipASN": "AS42607 Internet Carrier Limited",
|
||||||
|
"dstipASN": "",
|
||||||
|
"usgipASN": "AS7922 Comcast Cable Communications, LLC",
|
||||||
|
"catname": "spamhaus",
|
||||||
|
"inner_alert_action": "allowed",
|
||||||
|
"inner_alert_gid": 1,
|
||||||
|
"inner_alert_signature_id": 2400022,
|
||||||
|
"inner_alert_rev": 2673,
|
||||||
|
"inner_alert_signature": "ET DROP Spamhaus DROP Listed Traffic Inbound group 23",
|
||||||
|
"inner_alert_category": "Misc Attack",
|
||||||
|
"inner_alert_severity": 2,
|
||||||
|
"key": "EVT_IPS_IpsAlert",
|
||||||
|
"subsystem": "www",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"time": 1562646211000,
|
||||||
|
"datetime": "2019-07-09T04:23:31Z",
|
||||||
|
"msg": "IPS Alert 2: Misc Attack. Signature ET DROP Spamhaus DROP Listed Traffic Inbound group 23. From: 196.196.244.84:51413, to: 192.168.3.2:36881, protocol: UDP"
|
||||||
|
},
|
||||||
|
|
@ -0,0 +1,738 @@
|
||||||
|
{
|
||||||
|
"_id": "574e8bde4566ffb914a26853",
|
||||||
|
"adopted": true,
|
||||||
|
"antenna_table": [
|
||||||
|
{
|
||||||
|
"default": true,
|
||||||
|
"id": 4,
|
||||||
|
"name": "Combined",
|
||||||
|
"wifi0_gain": 3,
|
||||||
|
"wifi1_gain": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bandsteering_mode": "prefer_5g",
|
||||||
|
"board_rev": 18,
|
||||||
|
"cfgversion": "08cd8d6b71ebe82f",
|
||||||
|
"config_network": {
|
||||||
|
"type": "dhcp",
|
||||||
|
"ip": "10.1.10.67"
|
||||||
|
},
|
||||||
|
"countrycode_table": [
|
||||||
|
840,
|
||||||
|
124,
|
||||||
|
630
|
||||||
|
],
|
||||||
|
"ethernet_table": [
|
||||||
|
{
|
||||||
|
"mac": "80:22:a8:22:ae:22",
|
||||||
|
"num_port": 2,
|
||||||
|
"name": "eth0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fw_caps": 4128063,
|
||||||
|
"has_eth1": false,
|
||||||
|
"has_speaker": false,
|
||||||
|
"inform_ip": "192.168.3.1",
|
||||||
|
"inform_url": "http://unifi:8080/inform",
|
||||||
|
"ip": "192.168.1.8",
|
||||||
|
"led_override": "default",
|
||||||
|
"mac": "80:22:22:22:22:22",
|
||||||
|
"mesh_sta_vap_enabled": true,
|
||||||
|
"model": "U7PG2",
|
||||||
|
"name": "wap-lower",
|
||||||
|
"outdoor_mode_override": "default",
|
||||||
|
"port_table": [
|
||||||
|
{
|
||||||
|
"port_idx": 1,
|
||||||
|
"op_mode": "switch",
|
||||||
|
"portconf_id": "574e869d4566ffb914a26845",
|
||||||
|
"attr_no_edit": true,
|
||||||
|
"media": "GE",
|
||||||
|
"name": "Main",
|
||||||
|
"poe_caps": 0,
|
||||||
|
"port_poe": false,
|
||||||
|
"tx_bytes-r": 0,
|
||||||
|
"rx_bytes-r": 0,
|
||||||
|
"bytes-r": 0,
|
||||||
|
"port_delta": {
|
||||||
|
"time_delta": 21
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"masked": false,
|
||||||
|
"aggregated_by": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"port_idx": 2,
|
||||||
|
"op_mode": "switch",
|
||||||
|
"portconf_id": "574e869d4566ffb914a26845",
|
||||||
|
"media": "GE",
|
||||||
|
"name": "Secondary",
|
||||||
|
"poe_caps": 0,
|
||||||
|
"port_poe": false,
|
||||||
|
"tx_bytes-r": 0,
|
||||||
|
"rx_bytes-r": 0,
|
||||||
|
"bytes-r": 0,
|
||||||
|
"port_delta": {
|
||||||
|
"time_delta": 21
|
||||||
|
},
|
||||||
|
"enable": true,
|
||||||
|
"masked": false,
|
||||||
|
"aggregated_by": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"radio_table": [
|
||||||
|
{
|
||||||
|
"radio": "ng",
|
||||||
|
"name": "wifi0",
|
||||||
|
"channel": "auto",
|
||||||
|
"ht": "40",
|
||||||
|
"tx_power_mode": "auto",
|
||||||
|
"tx_power": "0",
|
||||||
|
"max_txpower": 22,
|
||||||
|
"min_txpower": 6,
|
||||||
|
"nss": 3,
|
||||||
|
"min_rssi_enabled": false,
|
||||||
|
"builtin_antenna": true,
|
||||||
|
"builtin_ant_gain": 3,
|
||||||
|
"current_antenna_gain": 0,
|
||||||
|
"radio_caps": 16420,
|
||||||
|
"wlangroup_id": "574e869d4566ffb914a26843"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"radio": "na",
|
||||||
|
"name": "wifi1",
|
||||||
|
"channel": "auto",
|
||||||
|
"ht": "80",
|
||||||
|
"tx_power_mode": "high",
|
||||||
|
"tx_power": "0",
|
||||||
|
"max_txpower": 22,
|
||||||
|
"min_txpower": 6,
|
||||||
|
"nss": 3,
|
||||||
|
"min_rssi_enabled": false,
|
||||||
|
"is_11ac": true,
|
||||||
|
"has_dfs": true,
|
||||||
|
"has_fccdfs": true,
|
||||||
|
"builtin_antenna": true,
|
||||||
|
"builtin_ant_gain": 3,
|
||||||
|
"current_antenna_gain": 0,
|
||||||
|
"radio_caps": 50479140,
|
||||||
|
"wlangroup_id": "574e869d4566ffb914a26843"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scan_radio_table": [],
|
||||||
|
"serial": "xxxyyyzzz",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"type": "uap",
|
||||||
|
"version": "4.0.42.10433",
|
||||||
|
"vwire_table": [],
|
||||||
|
"wifi_caps": 49141,
|
||||||
|
"wlangroup_id_na": "574e869d4566ffb914a26843",
|
||||||
|
"wlangroup_id_ng": "574e869d4566ffb914a26843",
|
||||||
|
"required_version": "3.4.1",
|
||||||
|
"hw_caps": 0,
|
||||||
|
"unsupported": false,
|
||||||
|
"unsupported_reason": 0,
|
||||||
|
"sys_error_caps": 0,
|
||||||
|
"has_fan": false,
|
||||||
|
"has_temperature": false,
|
||||||
|
"device_id": "574e8bde4566ffb914a26853",
|
||||||
|
"state": 1,
|
||||||
|
"last_seen": 1562225381,
|
||||||
|
"upgradable": false,
|
||||||
|
"adoptable_when_upgraded": false,
|
||||||
|
"rollupgrade": false,
|
||||||
|
"known_cfgversion": "08cd8d6b71ebe82f",
|
||||||
|
"uptime": 3105845,
|
||||||
|
"_uptime": 3105845,
|
||||||
|
"locating": false,
|
||||||
|
"connect_request_ip": "192.168.1.8",
|
||||||
|
"connect_request_port": "43913",
|
||||||
|
"sys_stats": {
|
||||||
|
"loadavg_1": "0.04",
|
||||||
|
"loadavg_15": "0.14",
|
||||||
|
"loadavg_5": "0.10",
|
||||||
|
"mem_buffer": 0,
|
||||||
|
"mem_total": 128622592,
|
||||||
|
"mem_used": 67178496
|
||||||
|
},
|
||||||
|
"system-stats": {
|
||||||
|
"cpu": "24.7",
|
||||||
|
"mem": "52.2",
|
||||||
|
"uptime": "3105845"
|
||||||
|
},
|
||||||
|
"ssh_session_table": [],
|
||||||
|
"scanning": false,
|
||||||
|
"spectrum_scanning": false,
|
||||||
|
"guest_token": "4D630D2A1AF84771FCBB8EEB4C47E030",
|
||||||
|
"meshv3_peer_mac": "",
|
||||||
|
"satisfaction": 95,
|
||||||
|
"isolated": false,
|
||||||
|
"radio_table_stats": [
|
||||||
|
{
|
||||||
|
"name": "wifi0",
|
||||||
|
"channel": 6,
|
||||||
|
"radio": "ng",
|
||||||
|
"ast_txto": null,
|
||||||
|
"ast_cst": null,
|
||||||
|
"ast_be_xmit": 398,
|
||||||
|
"cu_total": 20,
|
||||||
|
"cu_self_rx": 14,
|
||||||
|
"cu_self_tx": 4,
|
||||||
|
"gain": 3,
|
||||||
|
"state": "RUN",
|
||||||
|
"extchannel": 1,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_packets": 183,
|
||||||
|
"tx_retries": 108,
|
||||||
|
"num_sta": 2,
|
||||||
|
"guest-num_sta": 0,
|
||||||
|
"user-num_sta": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "wifi1",
|
||||||
|
"channel": 36,
|
||||||
|
"radio": "na",
|
||||||
|
"ast_txto": null,
|
||||||
|
"ast_cst": null,
|
||||||
|
"ast_be_xmit": 398,
|
||||||
|
"cu_total": 12,
|
||||||
|
"cu_self_rx": 10,
|
||||||
|
"cu_self_tx": 2,
|
||||||
|
"gain": 3,
|
||||||
|
"state": "RUN",
|
||||||
|
"extchannel": 1,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_packets": 22466,
|
||||||
|
"tx_retries": 858,
|
||||||
|
"num_sta": 4,
|
||||||
|
"guest-num_sta": 0,
|
||||||
|
"user-num_sta": 4
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uplink": {
|
||||||
|
"full_duplex": true,
|
||||||
|
"ip": "0.0.0.0",
|
||||||
|
"mac": "80:22:22:22:22:22",
|
||||||
|
"max_vlan": 96,
|
||||||
|
"name": "eth0",
|
||||||
|
"netmask": "0.0.0.0",
|
||||||
|
"num_port": 2,
|
||||||
|
"rx_bytes": 3752803309,
|
||||||
|
"rx_dropped": 102338,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_multicast": 0,
|
||||||
|
"rx_packets": 245302304,
|
||||||
|
"speed": 1000,
|
||||||
|
"tx_bytes": 1604707458,
|
||||||
|
"tx_dropped": 341,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 194278357,
|
||||||
|
"up": true,
|
||||||
|
"max_speed": 1000,
|
||||||
|
"type": "wire",
|
||||||
|
"tx_bytes-r": 9693222,
|
||||||
|
"rx_bytes-r": 92418,
|
||||||
|
"uplink_mac": "f0:22:22:22:22:22",
|
||||||
|
"uplink_remote_port": 15
|
||||||
|
},
|
||||||
|
"vap_table": [
|
||||||
|
{
|
||||||
|
"avg_client_signal": 0,
|
||||||
|
"bssid": "82:22:22:22:22:22",
|
||||||
|
"ccq": 0,
|
||||||
|
"channel": 36,
|
||||||
|
"essid": "Extra Free",
|
||||||
|
"extchannel": 1,
|
||||||
|
"id": "574e96834566ffb914a26875",
|
||||||
|
"mac_filter_rejections": 0,
|
||||||
|
"name": "ath3",
|
||||||
|
"num_satisfaction_sta": 0,
|
||||||
|
"num_sta": 0,
|
||||||
|
"radio": "na",
|
||||||
|
"radio_name": "wifi1",
|
||||||
|
"rx_bytes": 61253,
|
||||||
|
"rx_crypts": 0,
|
||||||
|
"rx_dropped": 0,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_frags": 0,
|
||||||
|
"rx_nwids": 47658,
|
||||||
|
"rx_packets": 576,
|
||||||
|
"rx_tcp_stats": {
|
||||||
|
"goodbytes": 0,
|
||||||
|
"lat_avg": 0,
|
||||||
|
"lat_max": 0,
|
||||||
|
"lat_min": 4294967295,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"satisfaction": -1,
|
||||||
|
"satisfaction_now": -1,
|
||||||
|
"state": "RUN",
|
||||||
|
"tx_bytes": 922841,
|
||||||
|
"tx_combined_retries": 0,
|
||||||
|
"tx_data_mpdu_bytes": 0,
|
||||||
|
"tx_dropped": 18128,
|
||||||
|
"tx_errors": 7,
|
||||||
|
"tx_packets": 736,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_retries": 0,
|
||||||
|
"tx_rts_retries": 0,
|
||||||
|
"tx_success": 0,
|
||||||
|
"tx_tcp_stats": {
|
||||||
|
"goodbytes": 0,
|
||||||
|
"lat_avg": 0,
|
||||||
|
"lat_max": 0,
|
||||||
|
"lat_min": 4294967295,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"tx_total": 0,
|
||||||
|
"up": true,
|
||||||
|
"usage": "guest",
|
||||||
|
"wifi_tx_attempts": 0,
|
||||||
|
"wifi_tx_dropped": 0,
|
||||||
|
"wifi_tx_latency_mov": {
|
||||||
|
"avg": 0,
|
||||||
|
"max": 0,
|
||||||
|
"min": 4294967295,
|
||||||
|
"total": 0,
|
||||||
|
"total_count": 0
|
||||||
|
},
|
||||||
|
"t": "vap",
|
||||||
|
"wlanconf_id": "574e96834566ffb914a26875",
|
||||||
|
"is_guest": true,
|
||||||
|
"is_wep": false,
|
||||||
|
"ap_mac": "80:22:a8:22:22:22",
|
||||||
|
"map_id": null,
|
||||||
|
"site_id": "574e86994566ffb914a2683c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avg_client_signal": -65,
|
||||||
|
"bssid": "80:22:a8:22:22:22",
|
||||||
|
"ccq": 333,
|
||||||
|
"channel": 36,
|
||||||
|
"essid": "Extra Fast",
|
||||||
|
"extchannel": 1,
|
||||||
|
"id": "574e96614566ffb914a26874",
|
||||||
|
"mac_filter_rejections": 0,
|
||||||
|
"name": "ath2",
|
||||||
|
"num_satisfaction_sta": 4,
|
||||||
|
"num_sta": 4,
|
||||||
|
"radio": "na",
|
||||||
|
"radio_name": "wifi1",
|
||||||
|
"rx_bytes": 3358763522,
|
||||||
|
"rx_crypts": 161639,
|
||||||
|
"rx_dropped": 161639,
|
||||||
|
"rx_errors": 161639,
|
||||||
|
"rx_frags": 0,
|
||||||
|
"rx_nwids": 37605,
|
||||||
|
"rx_packets": 99128603,
|
||||||
|
"rx_tcp_stats": {
|
||||||
|
"goodbytes": 16243150352,
|
||||||
|
"lat_avg": 7,
|
||||||
|
"lat_max": 100,
|
||||||
|
"lat_min": 10,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"satisfaction": 96,
|
||||||
|
"satisfaction_now": 97,
|
||||||
|
"state": "RUN",
|
||||||
|
"tx_bytes": 834859686,
|
||||||
|
"tx_combined_retries": 9067488,
|
||||||
|
"tx_data_mpdu_bytes": 48117828355,
|
||||||
|
"tx_dropped": 109,
|
||||||
|
"tx_errors": 4076905,
|
||||||
|
"tx_packets": 111980588,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_retries": 9067488,
|
||||||
|
"tx_rts_retries": 0,
|
||||||
|
"tx_success": 62855481,
|
||||||
|
"tx_tcp_stats": {
|
||||||
|
"goodbytes": 2154118473,
|
||||||
|
"lat_avg": 18,
|
||||||
|
"lat_max": 120,
|
||||||
|
"lat_min": 10,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"tx_total": 62855552,
|
||||||
|
"up": true,
|
||||||
|
"usage": "user",
|
||||||
|
"wifi_tx_attempts": 71923040,
|
||||||
|
"wifi_tx_dropped": 71,
|
||||||
|
"wifi_tx_latency_mov": {
|
||||||
|
"avg": 565,
|
||||||
|
"max": 31757,
|
||||||
|
"min": 98,
|
||||||
|
"total": 10183098,
|
||||||
|
"total_count": 18019
|
||||||
|
},
|
||||||
|
"t": "vap",
|
||||||
|
"wlanconf_id": "574e96614566ffb914a26874",
|
||||||
|
"is_guest": false,
|
||||||
|
"is_wep": false,
|
||||||
|
"ap_mac": "80:22:22:22:22:22",
|
||||||
|
"map_id": null,
|
||||||
|
"site_id": "574e86994566ffb914a2683c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avg_client_signal": 0,
|
||||||
|
"bssid": "82:22:a8:22:22:22",
|
||||||
|
"ccq": 0,
|
||||||
|
"channel": 6,
|
||||||
|
"essid": "Extra Free",
|
||||||
|
"extchannel": 1,
|
||||||
|
"id": "574e96834566ffb914a26875",
|
||||||
|
"mac_filter_rejections": 0,
|
||||||
|
"name": "ath1",
|
||||||
|
"num_satisfaction_sta": 0,
|
||||||
|
"num_sta": 0,
|
||||||
|
"radio": "ng",
|
||||||
|
"radio_name": "wifi0",
|
||||||
|
"reasons_bar_chart": {
|
||||||
|
"phy_rate": 0,
|
||||||
|
"signal": 0,
|
||||||
|
"sleepy_client": 0,
|
||||||
|
"sta_arp_timeout": 0,
|
||||||
|
"sta_dns_timeout": 0,
|
||||||
|
"sta_ip_timeout": 0,
|
||||||
|
"stream_eff": 0,
|
||||||
|
"tcp_latency": 0,
|
||||||
|
"tcp_packet_loss": 0,
|
||||||
|
"wifi_latency": 0,
|
||||||
|
"wifi_retries": 0
|
||||||
|
},
|
||||||
|
"reasons_bar_chart_now": {
|
||||||
|
"phy_rate": 0,
|
||||||
|
"signal": 0,
|
||||||
|
"sleepy_client": 0,
|
||||||
|
"sta_arp_timeout": 0,
|
||||||
|
"sta_dns_timeout": 0,
|
||||||
|
"sta_ip_timeout": 0,
|
||||||
|
"stream_eff": 0,
|
||||||
|
"tcp_latency": 0,
|
||||||
|
"tcp_packet_loss": 0,
|
||||||
|
"wifi_latency": 0,
|
||||||
|
"wifi_retries": 0
|
||||||
|
},
|
||||||
|
"rx_bytes": 0,
|
||||||
|
"rx_crypts": 0,
|
||||||
|
"rx_dropped": 0,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_frags": 0,
|
||||||
|
"rx_nwids": 120385,
|
||||||
|
"rx_packets": 0,
|
||||||
|
"rx_tcp_stats": {
|
||||||
|
"goodbytes": 0,
|
||||||
|
"lat_avg": 0,
|
||||||
|
"lat_max": 0,
|
||||||
|
"lat_min": 4294967295,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"satisfaction": -1,
|
||||||
|
"satisfaction_now": -1,
|
||||||
|
"state": "RUN",
|
||||||
|
"tx_bytes": 0,
|
||||||
|
"tx_combined_retries": 0,
|
||||||
|
"tx_data_mpdu_bytes": 0,
|
||||||
|
"tx_dropped": 20262,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 0,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_retries": 0,
|
||||||
|
"tx_rts_retries": 0,
|
||||||
|
"tx_success": 0,
|
||||||
|
"tx_tcp_stats": {
|
||||||
|
"goodbytes": 0,
|
||||||
|
"lat_avg": 0,
|
||||||
|
"lat_max": 0,
|
||||||
|
"lat_min": 4294967295,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"tx_total": 0,
|
||||||
|
"up": true,
|
||||||
|
"usage": "guest",
|
||||||
|
"wifi_tx_attempts": 0,
|
||||||
|
"wifi_tx_dropped": 0,
|
||||||
|
"wifi_tx_latency_mov": {
|
||||||
|
"avg": 0,
|
||||||
|
"max": 0,
|
||||||
|
"min": 4294967295,
|
||||||
|
"total": 0,
|
||||||
|
"total_count": 0
|
||||||
|
},
|
||||||
|
"t": "vap",
|
||||||
|
"wlanconf_id": "574e96834566ffb914a26875",
|
||||||
|
"is_guest": true,
|
||||||
|
"is_wep": false,
|
||||||
|
"ap_mac": "80:22:a8:22:22:22",
|
||||||
|
"map_id": null,
|
||||||
|
"site_id": "574e86994566ffb914a2683c"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avg_client_signal": -68,
|
||||||
|
"bssid": "80:22:22:22:22:22",
|
||||||
|
"ccq": 966,
|
||||||
|
"channel": 6,
|
||||||
|
"essid": "Extra Fast",
|
||||||
|
"extchannel": 1,
|
||||||
|
"id": "574e96614566ffb914a26874",
|
||||||
|
"mac_filter_rejections": 0,
|
||||||
|
"name": "ath0",
|
||||||
|
"num_satisfaction_sta": 2,
|
||||||
|
"num_sta": 2,
|
||||||
|
"radio": "ng",
|
||||||
|
"radio_name": "wifi0",
|
||||||
|
"reasons_bar_chart": {
|
||||||
|
"phy_rate": 0,
|
||||||
|
"signal": 0,
|
||||||
|
"sleepy_client": 0,
|
||||||
|
"sta_arp_timeout": 0,
|
||||||
|
"sta_dns_timeout": 0,
|
||||||
|
"sta_ip_timeout": 0,
|
||||||
|
"stream_eff": 0,
|
||||||
|
"tcp_latency": 0,
|
||||||
|
"tcp_packet_loss": 0,
|
||||||
|
"wifi_latency": 0,
|
||||||
|
"wifi_retries": 1
|
||||||
|
},
|
||||||
|
"reasons_bar_chart_now": {
|
||||||
|
"phy_rate": 0,
|
||||||
|
"signal": 0,
|
||||||
|
"sleepy_client": 0,
|
||||||
|
"sta_arp_timeout": 0,
|
||||||
|
"sta_dns_timeout": 0,
|
||||||
|
"sta_ip_timeout": 0,
|
||||||
|
"stream_eff": 0,
|
||||||
|
"tcp_latency": 0,
|
||||||
|
"tcp_packet_loss": 0,
|
||||||
|
"wifi_latency": 0,
|
||||||
|
"wifi_retries": 1
|
||||||
|
},
|
||||||
|
"rx_bytes": 1017366419,
|
||||||
|
"rx_crypts": 11013,
|
||||||
|
"rx_dropped": 12764,
|
||||||
|
"rx_errors": 12764,
|
||||||
|
"rx_frags": 0,
|
||||||
|
"rx_nwids": 177145,
|
||||||
|
"rx_packets": 22542668,
|
||||||
|
"rx_tcp_stats": {
|
||||||
|
"goodbytes": 114220296,
|
||||||
|
"lat_avg": 5,
|
||||||
|
"lat_max": 10,
|
||||||
|
"lat_min": 10,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"satisfaction": 93,
|
||||||
|
"satisfaction_now": 94,
|
||||||
|
"state": "RUN",
|
||||||
|
"tx_bytes": 965488630,
|
||||||
|
"tx_combined_retries": 8202639,
|
||||||
|
"tx_data_mpdu_bytes": 1145631754,
|
||||||
|
"tx_dropped": 43,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 22623798,
|
||||||
|
"tx_power": 22,
|
||||||
|
"tx_retries": 7194267,
|
||||||
|
"tx_rts_retries": 1008372,
|
||||||
|
"tx_success": 9545999,
|
||||||
|
"tx_tcp_stats": {
|
||||||
|
"goodbytes": 182912739,
|
||||||
|
"lat_avg": 5,
|
||||||
|
"lat_max": 10,
|
||||||
|
"lat_min": 10,
|
||||||
|
"stalls": 0
|
||||||
|
},
|
||||||
|
"tx_total": 9547096,
|
||||||
|
"up": true,
|
||||||
|
"usage": "user",
|
||||||
|
"wifi_tx_attempts": 16740276,
|
||||||
|
"wifi_tx_dropped": 1095,
|
||||||
|
"wifi_tx_latency_mov": {
|
||||||
|
"avg": 673,
|
||||||
|
"max": 13612,
|
||||||
|
"min": 0,
|
||||||
|
"total": 263176,
|
||||||
|
"total_count": 391
|
||||||
|
},
|
||||||
|
"t": "vap",
|
||||||
|
"wlanconf_id": "574e96614566ffb914a26874",
|
||||||
|
"is_guest": false,
|
||||||
|
"is_wep": false,
|
||||||
|
"ap_mac": "80:22:22:22:22:22",
|
||||||
|
"map_id": null,
|
||||||
|
"site_id": "574e86994566ffb914a2683c"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"downlink_table": [],
|
||||||
|
"vwire_vap_table": [],
|
||||||
|
"bytes-d": 204913232,
|
||||||
|
"tx_bytes-d": 1921569,
|
||||||
|
"rx_bytes-d": 202991663,
|
||||||
|
"bytes-r": 9757772,
|
||||||
|
"last_uplink": {
|
||||||
|
"uplink_mac": "f0:22:22:22:22:22",
|
||||||
|
"uplink_remote_port": 15
|
||||||
|
},
|
||||||
|
"stat": {
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"o": "ap",
|
||||||
|
"oid": "80:22:a8:22:22:22",
|
||||||
|
"ap": "80:22:a8:22:22:22",
|
||||||
|
"time": 1562207100000,
|
||||||
|
"datetime": "2019-07-04T02:25:00Z",
|
||||||
|
"guest-wifi0-rx_packets": 0,
|
||||||
|
"guest-wifi1-rx_packets": 0,
|
||||||
|
"user-wifi1-rx_packets": 31373230,
|
||||||
|
"user-wifi0-rx_packets": 169790,
|
||||||
|
"user-rx_packets": 31543020,
|
||||||
|
"guest-rx_packets": 0,
|
||||||
|
"wifi0-rx_packets": 169790,
|
||||||
|
"wifi1-rx_packets": 31373230,
|
||||||
|
"rx_packets": 31543020,
|
||||||
|
"guest-wifi0-rx_bytes": 0,
|
||||||
|
"guest-wifi1-rx_bytes": 0,
|
||||||
|
"user-wifi1-rx_bytes": 42049645434,
|
||||||
|
"user-wifi0-rx_bytes": 16755639,
|
||||||
|
"user-rx_bytes": 42066401073,
|
||||||
|
"guest-rx_bytes": 0,
|
||||||
|
"wifi0-rx_bytes": 16755639,
|
||||||
|
"wifi1-rx_bytes": 42049645434,
|
||||||
|
"rx_bytes": 42066401073,
|
||||||
|
"guest-wifi0-rx_errors": 0,
|
||||||
|
"guest-wifi1-rx_errors": 0,
|
||||||
|
"user-wifi1-rx_errors": 150651,
|
||||||
|
"user-wifi0-rx_errors": 0,
|
||||||
|
"user-rx_errors": 150651,
|
||||||
|
"guest-rx_errors": 0,
|
||||||
|
"wifi0-rx_errors": 0,
|
||||||
|
"wifi1-rx_errors": 150651,
|
||||||
|
"rx_errors": 150651,
|
||||||
|
"guest-wifi0-rx_dropped": 0,
|
||||||
|
"guest-wifi1-rx_dropped": 0,
|
||||||
|
"user-wifi1-rx_dropped": 150651,
|
||||||
|
"user-wifi0-rx_dropped": 0,
|
||||||
|
"user-rx_dropped": 150651,
|
||||||
|
"guest-rx_dropped": 0,
|
||||||
|
"wifi0-rx_dropped": 0,
|
||||||
|
"wifi1-rx_dropped": 150651,
|
||||||
|
"rx_dropped": 150651,
|
||||||
|
"guest-wifi0-rx_crypts": 0,
|
||||||
|
"guest-wifi1-rx_crypts": 0,
|
||||||
|
"user-wifi1-rx_crypts": 150651,
|
||||||
|
"user-wifi0-rx_crypts": 0,
|
||||||
|
"user-rx_crypts": 150651,
|
||||||
|
"guest-rx_crypts": 0,
|
||||||
|
"wifi0-rx_crypts": 0,
|
||||||
|
"wifi1-rx_crypts": 150651,
|
||||||
|
"rx_crypts": 150651,
|
||||||
|
"guest-wifi0-rx_frags": 0,
|
||||||
|
"guest-wifi1-rx_frags": 0,
|
||||||
|
"user-wifi1-rx_frags": 0,
|
||||||
|
"user-wifi0-rx_frags": 0,
|
||||||
|
"user-rx_frags": 0,
|
||||||
|
"guest-rx_frags": 0,
|
||||||
|
"wifi0-rx_frags": 0,
|
||||||
|
"wifi1-rx_frags": 0,
|
||||||
|
"rx_frags": 0,
|
||||||
|
"guest-wifi0-tx_packets": 0,
|
||||||
|
"guest-wifi1-tx_packets": 0,
|
||||||
|
"user-wifi1-tx_packets": 7125589,
|
||||||
|
"user-wifi0-tx_packets": 210389,
|
||||||
|
"user-tx_packets": 7335978,
|
||||||
|
"guest-tx_packets": 0,
|
||||||
|
"wifi0-tx_packets": 210389,
|
||||||
|
"wifi1-tx_packets": 7125589,
|
||||||
|
"tx_packets": 7335978,
|
||||||
|
"guest-wifi0-tx_bytes": 0,
|
||||||
|
"guest-wifi1-tx_bytes": 0,
|
||||||
|
"user-wifi1-tx_bytes": 3011293823,
|
||||||
|
"user-wifi0-tx_bytes": 25966558,
|
||||||
|
"user-tx_bytes": 3037260381,
|
||||||
|
"guest-tx_bytes": 0,
|
||||||
|
"wifi0-tx_bytes": 25966558,
|
||||||
|
"wifi1-tx_bytes": 3011293823,
|
||||||
|
"tx_bytes": 3037260381,
|
||||||
|
"guest-wifi0-tx_errors": 0,
|
||||||
|
"guest-wifi1-tx_errors": 0,
|
||||||
|
"user-wifi1-tx_errors": 102193,
|
||||||
|
"user-wifi0-tx_errors": 0,
|
||||||
|
"user-tx_errors": 102193,
|
||||||
|
"guest-tx_errors": 0,
|
||||||
|
"wifi0-tx_errors": 0,
|
||||||
|
"wifi1-tx_errors": 102193,
|
||||||
|
"tx_errors": 102193,
|
||||||
|
"guest-wifi0-tx_dropped": 296,
|
||||||
|
"guest-wifi1-tx_dropped": 296,
|
||||||
|
"user-wifi1-tx_dropped": 0,
|
||||||
|
"user-wifi0-tx_dropped": 0,
|
||||||
|
"user-tx_dropped": 0,
|
||||||
|
"guest-tx_dropped": 592,
|
||||||
|
"wifi0-tx_dropped": 296,
|
||||||
|
"wifi1-tx_dropped": 296,
|
||||||
|
"tx_dropped": 592,
|
||||||
|
"guest-wifi0-tx_retries": 0,
|
||||||
|
"guest-wifi1-tx_retries": 0,
|
||||||
|
"user-wifi1-tx_retries": 519734,
|
||||||
|
"user-wifi0-tx_retries": 90225,
|
||||||
|
"user-tx_retries": 609959,
|
||||||
|
"guest-tx_retries": 0,
|
||||||
|
"wifi0-tx_retries": 90225,
|
||||||
|
"wifi1-tx_retries": 519734,
|
||||||
|
"tx_retries": 609959,
|
||||||
|
"guest-wifi0-mac_filter_rejections": 0,
|
||||||
|
"guest-wifi1-mac_filter_rejections": 0,
|
||||||
|
"user-wifi1-mac_filter_rejections": 0,
|
||||||
|
"user-wifi0-mac_filter_rejections": 0,
|
||||||
|
"user-mac_filter_rejections": 0,
|
||||||
|
"guest-mac_filter_rejections": 0,
|
||||||
|
"wifi0-mac_filter_rejections": 0,
|
||||||
|
"wifi1-mac_filter_rejections": 0,
|
||||||
|
"mac_filter_rejections": 0,
|
||||||
|
"guest-wifi0-wifi_tx_attempts": 0,
|
||||||
|
"guest-wifi1-wifi_tx_attempts": 0,
|
||||||
|
"user-wifi1-wifi_tx_attempts": 4419026,
|
||||||
|
"user-wifi0-wifi_tx_attempts": 255999,
|
||||||
|
"user-wifi_tx_attempts": 4675025,
|
||||||
|
"guest-wifi_tx_attempts": 0,
|
||||||
|
"wifi0-wifi_tx_attempts": 255999,
|
||||||
|
"wifi1-wifi_tx_attempts": 4419026,
|
||||||
|
"wifi_tx_attempts": 4675025,
|
||||||
|
"guest-wifi0-wifi_tx_dropped": 0,
|
||||||
|
"guest-wifi1-wifi_tx_dropped": 0,
|
||||||
|
"user-wifi1-wifi_tx_dropped": 25,
|
||||||
|
"user-wifi0-wifi_tx_dropped": 2,
|
||||||
|
"user-wifi_tx_dropped": 27,
|
||||||
|
"guest-wifi_tx_dropped": 0,
|
||||||
|
"wifi0-wifi_tx_dropped": 2,
|
||||||
|
"wifi1-wifi_tx_dropped": 25,
|
||||||
|
"wifi_tx_dropped": 27,
|
||||||
|
"bytes": 45103661454,
|
||||||
|
"duration": 17988000,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-rx_packets": 31373230,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-rx_bytes": 42049645434,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-tx_packets": 7125589,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-tx_bytes": 3011293823,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-tx_errors": 102193,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-tx_retries": 519734,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-wifi_tx_attempts": 4419026,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-rx_packets": 169790,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-rx_bytes": 16755639,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-tx_packets": 210389,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-tx_bytes": 25966558,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-tx_retries": 90225,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-wifi_tx_attempts": 255999,
|
||||||
|
"guest-wifi1-ath3-574e96834566ffb914a26875-tx_dropped": 296,
|
||||||
|
"guest-wifi0-ath1-574e96834566ffb914a26875-tx_dropped": 296,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-rx_errors": 150651,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-rx_dropped": 150651,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-rx_crypts": 150651,
|
||||||
|
"user-wifi0-ath0-574e96614566ffb914a26874-wifi_tx_dropped": 2,
|
||||||
|
"user-wifi1-ath2-574e96614566ffb914a26874-wifi_tx_dropped": 25
|
||||||
|
},
|
||||||
|
"tx_bytes": 3037260381,
|
||||||
|
"rx_bytes": 42066401073,
|
||||||
|
"bytes": 45103661454,
|
||||||
|
"vwireEnabled": false,
|
||||||
|
"uplink_table": [],
|
||||||
|
"num_sta": 6,
|
||||||
|
"user-num_sta": 6,
|
||||||
|
"guest-num_sta": 0
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,371 @@
|
||||||
|
{
|
||||||
|
"_id": "59a35da745663e6cc82600f6",
|
||||||
|
"adopted": true,
|
||||||
|
"cfgversion": "bf9f0335063fe6ea",
|
||||||
|
"config_network": {
|
||||||
|
"type": "dhcp",
|
||||||
|
"ip": "192.168.2.0"
|
||||||
|
},
|
||||||
|
"ethernet_table": [
|
||||||
|
{
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"num_port": 1,
|
||||||
|
"name": "eth0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"num_port": 1,
|
||||||
|
"name": "eth1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"num_port": 1,
|
||||||
|
"name": "eth2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"fw_caps": 184323,
|
||||||
|
"inform_ip": "192.168.3.1",
|
||||||
|
"inform_url": "http://security:8080/inform",
|
||||||
|
"ip": "3.1.33.7",
|
||||||
|
"led_override": "default",
|
||||||
|
"license_state": "registered",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"model": "UGW3",
|
||||||
|
"name": "gateway",
|
||||||
|
"outdoor_mode_override": "default",
|
||||||
|
"serial": "xxxyyyzzz",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"type": "ugw",
|
||||||
|
"usg_caps": 786431,
|
||||||
|
"version": "4.4.41.5193700",
|
||||||
|
"required_version": "4.0.0",
|
||||||
|
"ethernet_overrides": [
|
||||||
|
{
|
||||||
|
"ifname": "eth1",
|
||||||
|
"networkgroup": "LAN"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ifname": "eth0",
|
||||||
|
"networkgroup": "WAN"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hw_caps": 0,
|
||||||
|
"board_rev": 16,
|
||||||
|
"unsupported": false,
|
||||||
|
"unsupported_reason": 0,
|
||||||
|
"device_id": "59a35da745663e6cc82600f6",
|
||||||
|
"state": 1,
|
||||||
|
"last_seen": 1562311857,
|
||||||
|
"upgradable": false,
|
||||||
|
"adoptable_when_upgraded": false,
|
||||||
|
"rollupgrade": false,
|
||||||
|
"known_cfgversion": "bf9f0335063fe6ea",
|
||||||
|
"uptime": 3191626,
|
||||||
|
"_uptime": 3191626,
|
||||||
|
"locating": false,
|
||||||
|
"connect_request_ip": "192.168.2.1",
|
||||||
|
"connect_request_port": "35615",
|
||||||
|
"sys_stats": {
|
||||||
|
"loadavg_1": "0.01",
|
||||||
|
"loadavg_15": "0.12",
|
||||||
|
"loadavg_5": "0.06",
|
||||||
|
"mem_buffer": 62406656,
|
||||||
|
"mem_total": 507412480,
|
||||||
|
"mem_used": 397500416
|
||||||
|
},
|
||||||
|
"system-stats": {
|
||||||
|
"cpu": "14",
|
||||||
|
"mem": "30",
|
||||||
|
"uptime": "3191066"
|
||||||
|
},
|
||||||
|
"guest_token": "83342830AE9C0641DC39DD2759C122A1",
|
||||||
|
"speedtest-status": {
|
||||||
|
"latency": 14,
|
||||||
|
"rundate": 1562310531,
|
||||||
|
"runtime": 172,
|
||||||
|
"status_download": 2,
|
||||||
|
"status_ping": 2,
|
||||||
|
"status_summary": 2,
|
||||||
|
"status_upload": 2,
|
||||||
|
"xput_download": 157.36776733398438,
|
||||||
|
"xput_upload": 37.90521240234375
|
||||||
|
},
|
||||||
|
"speedtest-status-saved": true,
|
||||||
|
"wan1": {
|
||||||
|
"tx_bytes-r": 2852355,
|
||||||
|
"rx_bytes-r": 1224743,
|
||||||
|
"bytes-r": 4077098,
|
||||||
|
"max_speed": 1000,
|
||||||
|
"type": "wire",
|
||||||
|
"name": "wan",
|
||||||
|
"ifname": "eth0",
|
||||||
|
"ip": "3.1.33.7",
|
||||||
|
"netmask": "255.255.254.0",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"up": true,
|
||||||
|
"speed": 1000,
|
||||||
|
"full_duplex": true,
|
||||||
|
"rx_bytes": 2648236513108,
|
||||||
|
"rx_dropped": 34030,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_packets": 3068347172,
|
||||||
|
"tx_bytes": 3009601283006,
|
||||||
|
"tx_dropped": 0,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 2859713220,
|
||||||
|
"rx_multicast": 939111,
|
||||||
|
"enable": true,
|
||||||
|
"dns": [
|
||||||
|
"1.1.1.1",
|
||||||
|
"8.8.8.8"
|
||||||
|
],
|
||||||
|
"gateway": "3.1.33.8"
|
||||||
|
},
|
||||||
|
"port_table": [
|
||||||
|
{
|
||||||
|
"name": "wan",
|
||||||
|
"ifname": "eth0",
|
||||||
|
"ip": "3.1.33.7",
|
||||||
|
"netmask": "255.255.254.0",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"up": true,
|
||||||
|
"speed": 1000,
|
||||||
|
"full_duplex": true,
|
||||||
|
"rx_bytes": 2648236513108,
|
||||||
|
"rx_dropped": 34030,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_packets": 3068347172,
|
||||||
|
"tx_bytes": 3009601283006,
|
||||||
|
"tx_dropped": 0,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 2859713220,
|
||||||
|
"rx_multicast": 939111,
|
||||||
|
"enable": true,
|
||||||
|
"dns": [
|
||||||
|
"216.146.35.35",
|
||||||
|
"216.146.36.36"
|
||||||
|
],
|
||||||
|
"gateway": "3.1.33.8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lan",
|
||||||
|
"ifname": "eth1",
|
||||||
|
"ip": "192.168.2.1",
|
||||||
|
"netmask": "255.255.252.0",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"up": true,
|
||||||
|
"speed": 1000,
|
||||||
|
"full_duplex": true,
|
||||||
|
"rx_bytes": 2911311797255,
|
||||||
|
"rx_dropped": 3438,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_packets": 2659342049,
|
||||||
|
"tx_bytes": 2140222188895,
|
||||||
|
"tx_dropped": 0,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 2734245088,
|
||||||
|
"rx_multicast": 11929365,
|
||||||
|
"enable": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lan2",
|
||||||
|
"ifname": "eth2",
|
||||||
|
"ip": "0.0.0.0",
|
||||||
|
"netmask": "0.0.0.0",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"up": false,
|
||||||
|
"speed": 0,
|
||||||
|
"full_duplex": false,
|
||||||
|
"rx_bytes": 0,
|
||||||
|
"rx_dropped": 0,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_packets": 0,
|
||||||
|
"tx_bytes": 0,
|
||||||
|
"tx_dropped": 0,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 0,
|
||||||
|
"rx_multicast": 0,
|
||||||
|
"enable": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"network_table": [
|
||||||
|
{
|
||||||
|
"_id": "574e8de34566ffb914a26862",
|
||||||
|
"is_nat": true,
|
||||||
|
"dhcpd_dns_enabled": false,
|
||||||
|
"purpose": "guest",
|
||||||
|
"dhcpd_leasetime": "86400",
|
||||||
|
"igmp_snooping": true,
|
||||||
|
"dhcpguard_enabled": false,
|
||||||
|
"dhcpd_start": "192.168.5.1",
|
||||||
|
"enabled": true,
|
||||||
|
"dhcpd_stop": "192.168.5.254",
|
||||||
|
"dhcpd_wins_enabled": false,
|
||||||
|
"domain_name": "guest.lan",
|
||||||
|
"dhcpd_enabled": true,
|
||||||
|
"ip_subnet": "192.168.5.0/23",
|
||||||
|
"vlan": "5",
|
||||||
|
"networkgroup": "LAN",
|
||||||
|
"name": "Public Wireless",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"dhcpd_ip_1": "",
|
||||||
|
"vlan_enabled": true,
|
||||||
|
"dhcpd_gateway_enabled": false,
|
||||||
|
"dhcpd_time_offset_enabled": false,
|
||||||
|
"ipv6_interface_type": "none",
|
||||||
|
"dhcp_relay_enabled": false,
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"is_guest": true,
|
||||||
|
"ip": "192.168.5.0",
|
||||||
|
"up": "true",
|
||||||
|
"num_sta": 1,
|
||||||
|
"rx_bytes": 578602537,
|
||||||
|
"rx_packets": 471151,
|
||||||
|
"tx_bytes": 182318948,
|
||||||
|
"tx_packets": 239651
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "59a362f645663e6cc8260133",
|
||||||
|
"is_nat": true,
|
||||||
|
"dhcpd_dns_enabled": false,
|
||||||
|
"purpose": "corporate",
|
||||||
|
"dhcpd_leasetime": 86400,
|
||||||
|
"dhcpd_start": "192.168.68.2",
|
||||||
|
"dhcpd_stop": "192.168.68.250",
|
||||||
|
"enabled": true,
|
||||||
|
"domain_name": "secure.lan",
|
||||||
|
"dhcpd_enabled": true,
|
||||||
|
"vlan": "69",
|
||||||
|
"ip_subnet": "192.168.69.1/23",
|
||||||
|
"networkgroup": "LAN",
|
||||||
|
"name": "Security Network",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"vlan_enabled": true,
|
||||||
|
"dhcpd_ntp_1": "192.168.69.1",
|
||||||
|
"dhcpd_gateway_enabled": false,
|
||||||
|
"dhcpd_time_offset_enabled": false,
|
||||||
|
"dhcp_relay_enabled": false,
|
||||||
|
"dhcpd_ntp_enabled": true,
|
||||||
|
"ipv6_interface_type": "none",
|
||||||
|
"dhcpd_unifi_controller": "192.168.3.1",
|
||||||
|
"igmp_snooping": true,
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"is_guest": false,
|
||||||
|
"ip": "192.168.69.1",
|
||||||
|
"up": "true",
|
||||||
|
"num_sta": 11,
|
||||||
|
"rx_bytes": 5221725,
|
||||||
|
"rx_packets": 70663,
|
||||||
|
"tx_bytes": 0,
|
||||||
|
"tx_packets": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "574e869d4566ffb914a26841",
|
||||||
|
"purpose": "corporate",
|
||||||
|
"dhcpd_leasetime": "86400",
|
||||||
|
"igmp_snooping": false,
|
||||||
|
"dhcpd_ntp_1": "192.168.2.1",
|
||||||
|
"dhcpguard_enabled": false,
|
||||||
|
"dhcpd_gateway_enabled": false,
|
||||||
|
"dhcpd_time_offset_enabled": false,
|
||||||
|
"dhcpd_start": "192.168.1.1",
|
||||||
|
"dhcpd_unifi_controller": "192.168.3.1",
|
||||||
|
"dhcpd_stop": "192.168.1.254",
|
||||||
|
"enabled": true,
|
||||||
|
"domain_name": "home.lan",
|
||||||
|
"dhcpd_enabled": true,
|
||||||
|
"ip_subnet": "192.168.2.1/22",
|
||||||
|
"networkgroup": "LAN",
|
||||||
|
"dhcpd_ip_1": "",
|
||||||
|
"vlan_enabled": false,
|
||||||
|
"is_nat": true,
|
||||||
|
"dhcpd_dns_enabled": false,
|
||||||
|
"dhcp_relay_enabled": false,
|
||||||
|
"dhcpd_wins_enabled": false,
|
||||||
|
"upnp_lan_enabled": true,
|
||||||
|
"dhcpd_ntp_enabled": true,
|
||||||
|
"name": "Home Network",
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"attr_no_delete": true,
|
||||||
|
"attr_hidden_id": "LAN",
|
||||||
|
"ipv6_interface_type": "none",
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"is_guest": false,
|
||||||
|
"ip": "192.168.2.1",
|
||||||
|
"up": "true",
|
||||||
|
"num_sta": 30,
|
||||||
|
"rx_bytes": 2099754971983,
|
||||||
|
"rx_packets": 2689749160,
|
||||||
|
"tx_bytes": 2877873632166,
|
||||||
|
"tx_packets": 2579198457
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"uplink": {
|
||||||
|
"drops": 40,
|
||||||
|
"enable": true,
|
||||||
|
"full_duplex": true,
|
||||||
|
"gateways": [
|
||||||
|
"3.1.33.8"
|
||||||
|
],
|
||||||
|
"ip": "3.1.33.7",
|
||||||
|
"latency": 103,
|
||||||
|
"mac": "22:22:00:22:22:00",
|
||||||
|
"name": "eth0",
|
||||||
|
"nameservers": [
|
||||||
|
"1.1.1.1",
|
||||||
|
"8.8.8.8"
|
||||||
|
],
|
||||||
|
"netmask": "255.255.254.0",
|
||||||
|
"num_port": 1,
|
||||||
|
"rx_bytes": 2648236513108,
|
||||||
|
"rx_dropped": 34030,
|
||||||
|
"rx_errors": 0,
|
||||||
|
"rx_multicast": 939111,
|
||||||
|
"rx_packets": 3068347172,
|
||||||
|
"speed": 1000,
|
||||||
|
"speedtest_lastrun": 1562310531,
|
||||||
|
"speedtest_ping": 14,
|
||||||
|
"speedtest_status": "Success",
|
||||||
|
"tx_bytes": 3009601283006,
|
||||||
|
"tx_dropped": 0,
|
||||||
|
"tx_errors": 0,
|
||||||
|
"tx_packets": 2859713220,
|
||||||
|
"up": true,
|
||||||
|
"uptime": 559088,
|
||||||
|
"xput_down": 157.368,
|
||||||
|
"xput_up": 37.905,
|
||||||
|
"tx_bytes-r": 2852355,
|
||||||
|
"rx_bytes-r": 1224743,
|
||||||
|
"bytes-r": 4077098,
|
||||||
|
"max_speed": 1000,
|
||||||
|
"type": "wire"
|
||||||
|
},
|
||||||
|
"stat": {
|
||||||
|
"site_id": "574e86994566ffb914a2683c",
|
||||||
|
"o": "gw",
|
||||||
|
"oid": "22:22:00:22:22:00",
|
||||||
|
"gw": "22:22:00:22:22:00",
|
||||||
|
"time": 1562207100000,
|
||||||
|
"datetime": "2019-07-04T02:25:00Z",
|
||||||
|
"duration": 104466000,
|
||||||
|
"wan-rx_packets": 151387924,
|
||||||
|
"wan-rx_bytes": 111251311739,
|
||||||
|
"wan-tx_packets": 182985900,
|
||||||
|
"wan-tx_bytes": 230372237709,
|
||||||
|
"lan-rx_packets": 173953163,
|
||||||
|
"lan-rx_bytes": 226862410885,
|
||||||
|
"lan-tx_packets": 137029474,
|
||||||
|
"lan-tx_bytes": 89478206254,
|
||||||
|
"wan-rx_dropped": 561,
|
||||||
|
"lan-rx_dropped": 29
|
||||||
|
},
|
||||||
|
"tx_bytes": 2648236513108,
|
||||||
|
"rx_bytes": 3009601283006,
|
||||||
|
"bytes": 5657837796114,
|
||||||
|
"num_sta": 41,
|
||||||
|
"user-num_sta": 41,
|
||||||
|
"guest-num_sta": 0,
|
||||||
|
"num_desktop": 7,
|
||||||
|
"num_mobile": 2,
|
||||||
|
"num_handheld": 8
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
@ -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=
|
||||||
|
|
@ -0,0 +1,150 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IDSList contains a list that contains all of the IDS Events on a controller.
|
||||||
|
type IDSList []*IDS
|
||||||
|
|
||||||
|
// IDS holds an Intrusion Prevention System Event.
|
||||||
|
type IDS struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Archived FlexBool `json:"archived"`
|
||||||
|
Timestamp int64 `json:"timestamp"`
|
||||||
|
FlowID int64 `json:"flow_id"`
|
||||||
|
InIface string `json:"in_iface"`
|
||||||
|
EventType string `json:"event_type"`
|
||||||
|
SrcIP string `json:"src_ip"`
|
||||||
|
SrcMac string `json:"src_mac"`
|
||||||
|
SrcPort int `json:"src_port,omitempty"`
|
||||||
|
DestIP string `json:"dest_ip"`
|
||||||
|
DstMac string `json:"dst_mac"`
|
||||||
|
DestPort int `json:"dest_port,omitempty"`
|
||||||
|
Proto string `json:"proto"`
|
||||||
|
AppProto string `json:"app_proto,omitempty"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Usgip string `json:"usgip"`
|
||||||
|
UniqueAlertid string `json:"unique_alertid"`
|
||||||
|
SrcipCountry string `json:"srcipCountry"`
|
||||||
|
DstipCountry FlexBool `json:"dstipCountry"`
|
||||||
|
UsgipCountry string `json:"usgipCountry"`
|
||||||
|
SrcipGeo struct {
|
||||||
|
ContinentCode string `json:"continent_code"`
|
||||||
|
CountryCode string `json:"country_code"`
|
||||||
|
CountryCode3 string `json:"country_code3"`
|
||||||
|
CountryName string `json:"country_name"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
City string `json:"city"`
|
||||||
|
PostalCode string `json:"postal_code"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
DmaCode int64 `json:"dma_code"`
|
||||||
|
AreaCode int64 `json:"area_code"`
|
||||||
|
} `json:"srcipGeo"`
|
||||||
|
DstipGeo bool `json:"dstipGeo"`
|
||||||
|
UsgipGeo struct {
|
||||||
|
ContinentCode string `json:"continent_code"`
|
||||||
|
CountryCode string `json:"country_code"`
|
||||||
|
CountryCode3 string `json:"country_code3"`
|
||||||
|
CountryName string `json:"country_name"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
City string `json:"city"`
|
||||||
|
PostalCode string `json:"postal_code"`
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
DmaCode int64 `json:"dma_code"`
|
||||||
|
AreaCode int64 `json:"area_code"`
|
||||||
|
} `json:"usgipGeo"`
|
||||||
|
SrcipASN string `json:"srcipASN"`
|
||||||
|
DstipASN string `json:"dstipASN"`
|
||||||
|
UsgipASN string `json:"usgipASN"`
|
||||||
|
Catname string `json:"catname"`
|
||||||
|
InnerAlertAction string `json:"inner_alert_action"`
|
||||||
|
InnerAlertGID int64 `json:"inner_alert_gid"`
|
||||||
|
InnerAlertSignatureID int64 `json:"inner_alert_signature_id"`
|
||||||
|
InnerAlertRev int64 `json:"inner_alert_rev"`
|
||||||
|
InnerAlertSignature string `json:"inner_alert_signature"`
|
||||||
|
InnerAlertCategory string `json:"inner_alert_category"`
|
||||||
|
InnerAlertSeverity int64 `json:"inner_alert_severity"`
|
||||||
|
Key string `json:"key"`
|
||||||
|
Subsystem string `json:"subsystem"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
Time int64 `json:"time"`
|
||||||
|
Datetime time.Time `json:"datetime"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
IcmpType int64 `json:"icmp_type,omitempty"`
|
||||||
|
IcmpCode int64 `json:"icmp_code,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIDS returns Intrusion Detection Systems events.
|
||||||
|
// Returns all events that happened in site between from and to.
|
||||||
|
func (u *Unifi) GetIDS(sites Sites, from, to time.Time) ([]*IDS, error) {
|
||||||
|
data := []*IDS{}
|
||||||
|
|
||||||
|
for _, site := range sites {
|
||||||
|
u.DebugLog("Polling Controller for IDS/IPS Data, site %s (%s) ", site.Name, site.Desc)
|
||||||
|
|
||||||
|
ids, err := u.GetSiteIDS(site, from, to)
|
||||||
|
if err != nil {
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range ids {
|
||||||
|
ids[i].SourceName = u.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
data = append(data, ids...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSiteIDS is a helper to offload the for-loop work.
|
||||||
|
// This method retreives the Intrusion Detection System Data for 1 Site.
|
||||||
|
func (u *Unifi) GetSiteIDS(site *Site, from, to time.Time) ([]*IDS, error) {
|
||||||
|
var response struct {
|
||||||
|
Data []*IDS `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
URIpath := fmt.Sprintf(APIIPSEvents, site.Name)
|
||||||
|
|
||||||
|
params := fmt.Sprintf(`{"start":"%v000","end":"%v000","_limit":50000}`, from.Unix(), to.Unix())
|
||||||
|
|
||||||
|
req, err := u.UniReq(URIpath, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := u.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return nil, fmt.Errorf("invalid status code from server %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(body, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range response.Data {
|
||||||
|
response.Data[i].SiteName = site.SiteName
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.Data, nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetSites returns a list of configured sites on the UniFi controller.
|
||||||
|
func (u *Unifi) GetSites() (Sites, error) {
|
||||||
|
var response struct {
|
||||||
|
Data []*Site `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := u.GetData(APISiteList, &response); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sites := []string{} // used for debug log only
|
||||||
|
|
||||||
|
for i, d := range response.Data {
|
||||||
|
// Add special SourceName value.
|
||||||
|
response.Data[i].SourceName = u.URL
|
||||||
|
// If the human name is missing (description), set it to the cryptic name.
|
||||||
|
response.Data[i].Desc = pick(d.Desc, d.Name)
|
||||||
|
// Add the custom site name to each site. used as a Grafana filter somewhere.
|
||||||
|
response.Data[i].SiteName = d.Desc + " (" + d.Name + ")"
|
||||||
|
sites = append(sites, d.Name) // used for debug log only
|
||||||
|
}
|
||||||
|
|
||||||
|
u.DebugLog("Found %d site(s): %s", len(sites), strings.Join(sites, ","))
|
||||||
|
|
||||||
|
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.
|
||||||
|
type Sites []*Site
|
||||||
|
|
||||||
|
// Site represents a site's data.
|
||||||
|
type Site struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Desc string `json:"desc"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
AttrHiddenID string `json:"attr_hidden_id"`
|
||||||
|
AttrNoDelete FlexBool `json:"attr_no_delete"`
|
||||||
|
Health []struct {
|
||||||
|
Subsystem string `json:"subsystem"`
|
||||||
|
NumUser FlexInt `json:"num_user,omitempty"`
|
||||||
|
NumGuest FlexInt `json:"num_guest,omitempty"`
|
||||||
|
NumIot FlexInt `json:"num_iot,omitempty"`
|
||||||
|
TxBytesR FlexInt `json:"tx_bytes-r,omitempty"`
|
||||||
|
RxBytesR FlexInt `json:"rx_bytes-r,omitempty"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
NumAp FlexInt `json:"num_ap,omitempty"`
|
||||||
|
NumAdopted FlexInt `json:"num_adopted,omitempty"`
|
||||||
|
NumDisabled FlexInt `json:"num_disabled,omitempty"`
|
||||||
|
NumDisconnected FlexInt `json:"num_disconnected,omitempty"`
|
||||||
|
NumPending FlexInt `json:"num_pending,omitempty"`
|
||||||
|
NumGw FlexInt `json:"num_gw,omitempty"`
|
||||||
|
WanIP string `json:"wan_ip,omitempty"`
|
||||||
|
Gateways []string `json:"gateways,omitempty"`
|
||||||
|
Netmask string `json:"netmask,omitempty"`
|
||||||
|
Nameservers []string `json:"nameservers,omitempty"`
|
||||||
|
NumSta FlexInt `json:"num_sta,omitempty"`
|
||||||
|
GwMac string `json:"gw_mac,omitempty"`
|
||||||
|
GwName string `json:"gw_name,omitempty"`
|
||||||
|
GwSystemStats struct {
|
||||||
|
CPU FlexInt `json:"cpu"`
|
||||||
|
Mem FlexInt `json:"mem"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
} `json:"gw_system-stats,omitempty"`
|
||||||
|
GwVersion string `json:"gw_version,omitempty"`
|
||||||
|
Latency FlexInt `json:"latency,omitempty"`
|
||||||
|
Uptime FlexInt `json:"uptime,omitempty"`
|
||||||
|
Drops FlexInt `json:"drops,omitempty"`
|
||||||
|
XputUp FlexInt `json:"xput_up,omitempty"`
|
||||||
|
XputDown FlexInt `json:"xput_down,omitempty"`
|
||||||
|
SpeedtestStatus string `json:"speedtest_status,omitempty"`
|
||||||
|
SpeedtestLastrun FlexInt `json:"speedtest_lastrun,omitempty"`
|
||||||
|
SpeedtestPing FlexInt `json:"speedtest_ping,omitempty"`
|
||||||
|
LanIP string `json:"lan_ip,omitempty"`
|
||||||
|
NumSw FlexInt `json:"num_sw,omitempty"`
|
||||||
|
RemoteUserEnabled FlexBool `json:"remote_user_enabled,omitempty"`
|
||||||
|
RemoteUserNumActive FlexInt `json:"remote_user_num_active,omitempty"`
|
||||||
|
RemoteUserNumInactive FlexInt `json:"remote_user_num_inactive,omitempty"`
|
||||||
|
RemoteUserRxBytes FlexInt `json:"remote_user_rx_bytes,omitempty"`
|
||||||
|
RemoteUserTxBytes FlexInt `json:"remote_user_tx_bytes,omitempty"`
|
||||||
|
RemoteUserRxPackets FlexInt `json:"remote_user_rx_packets,omitempty"`
|
||||||
|
RemoteUserTxPackets FlexInt `json:"remote_user_tx_packets,omitempty"`
|
||||||
|
SiteToSiteEnabled FlexBool `json:"site_to_site_enabled,omitempty"`
|
||||||
|
} `json:"health"`
|
||||||
|
NumNewAlarms FlexInt `json:"num_new_alarms"`
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a list of unifi API paths.
|
||||||
|
// The %s in each string must be replaced with a Site.Name.
|
||||||
|
const (
|
||||||
|
// APIStatusPath shows Controller version.
|
||||||
|
APIStatusPath string = "/status"
|
||||||
|
// APISiteList is the path to the api site list.
|
||||||
|
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 string = "/api/s/%s/stat/sta"
|
||||||
|
// APIDevicePath is where we get data about Unifi devices.
|
||||||
|
APIDevicePath string = "/api/s/%s/stat/device"
|
||||||
|
// APINetworkPath contains network-configuration data. Not really graphable.
|
||||||
|
APINetworkPath string = "/api/s/%s/rest/networkconf"
|
||||||
|
// APIUserGroupPath contains usergroup configurations.
|
||||||
|
APIUserGroupPath string = "/api/s/%s/rest/usergroup"
|
||||||
|
// APILoginPath is Unifi Controller Login API Path
|
||||||
|
APILoginPath string = "/api/login"
|
||||||
|
// APIIPSEvents returns Intrusion Detection Systems Events
|
||||||
|
APIIPSEvents string = "/api/s/%s/stat/ips/event"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Logger is a base type to deal with changing log outputs. Create a logger
|
||||||
|
// that matches this interface to capture debug and error logs.
|
||||||
|
type Logger func(msg string, fmt ...interface{})
|
||||||
|
|
||||||
|
// discardLogs is the default debug logger.
|
||||||
|
func discardLogs(msg string, v ...interface{}) {
|
||||||
|
// do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Devices contains a list of all the unifi devices from a controller.
|
||||||
|
// Contains Access points, security gateways and switches.
|
||||||
|
type Devices struct {
|
||||||
|
UAPs []*UAP
|
||||||
|
USGs []*USG
|
||||||
|
USWs []*USW
|
||||||
|
UDMs []*UDM
|
||||||
|
}
|
||||||
|
|
||||||
|
// Config is the data passed into our library. This configures things and allows
|
||||||
|
// us to connect to a controller and write log messages.
|
||||||
|
type Config struct {
|
||||||
|
User string
|
||||||
|
Pass string
|
||||||
|
URL string
|
||||||
|
VerifySSL bool
|
||||||
|
ErrorLog Logger
|
||||||
|
DebugLog Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unifi is what you get in return for providing a password! Unifi represents
|
||||||
|
// a controller that you can make authenticated requests to. Use this to make
|
||||||
|
// additional requests for devices, clients or other custom data. Do not set
|
||||||
|
// the loggers to nil. Set them to DiscardLogs if you want no logs.
|
||||||
|
type Unifi struct {
|
||||||
|
*http.Client
|
||||||
|
*Config
|
||||||
|
*server
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlexInt provides a container and unmarshalling for fields that may be
|
||||||
|
// numbers or strings in the Unifi API.
|
||||||
|
type FlexInt struct {
|
||||||
|
Val float64
|
||||||
|
Txt string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON converts a string or number to an integer.
|
||||||
|
// Generally, do call this directly, it's used in the json interface.
|
||||||
|
func (f *FlexInt) UnmarshalJSON(b []byte) error {
|
||||||
|
var unk interface{}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(b, &unk); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch i := unk.(type) {
|
||||||
|
case float64:
|
||||||
|
f.Val = i
|
||||||
|
f.Txt = strconv.FormatFloat(i, 'f', -1, 64)
|
||||||
|
case string:
|
||||||
|
f.Txt = i
|
||||||
|
f.Val, _ = strconv.ParseFloat(i, 64)
|
||||||
|
case nil:
|
||||||
|
f.Txt = "0"
|
||||||
|
f.Val = 0
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("cannot unmarshal to FlexInt: %s", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FlexBool provides a container and unmarshalling for fields that may be
|
||||||
|
// boolean or strings in the Unifi API.
|
||||||
|
type FlexBool struct {
|
||||||
|
Val bool
|
||||||
|
Txt string
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON method converts armed/disarmed, yes/no, active/inactive or 0/1 to true/false.
|
||||||
|
// Really it converts ready, ok, up, t, armed, yes, active, enabled, 1, true to true. Anything else is false.
|
||||||
|
func (f *FlexBool) UnmarshalJSON(b []byte) error {
|
||||||
|
f.Txt = strings.Trim(string(b), `"`)
|
||||||
|
f.Val = f.Txt == "1" || strings.EqualFold(f.Txt, "true") || strings.EqualFold(f.Txt, "yes") ||
|
||||||
|
strings.EqualFold(f.Txt, "t") || strings.EqualFold(f.Txt, "armed") || strings.EqualFold(f.Txt, "active") ||
|
||||||
|
strings.EqualFold(f.Txt, "enabled") || strings.EqualFold(f.Txt, "ready") || strings.EqualFold(f.Txt, "up") ||
|
||||||
|
strings.EqualFold(f.Txt, "ok")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFlexInt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a := assert.New(t)
|
||||||
|
five, seven := 5, 7
|
||||||
|
|
||||||
|
var r struct {
|
||||||
|
Five FlexInt `json:"five"`
|
||||||
|
Seven FlexInt `json:"seven"`
|
||||||
|
Auto FlexInt `json:"auto"`
|
||||||
|
Channel FlexInt `json:"channel"`
|
||||||
|
Nil FlexInt `json:"nil"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// test unmarshalling the custom type three times with different values.
|
||||||
|
a.Nil(json.Unmarshal([]byte(`{"five": "5", "seven": 7, "auto": "auto", "nil": null}`), &r))
|
||||||
|
// test number in string.
|
||||||
|
a.EqualValues(five, r.Five.Val)
|
||||||
|
a.EqualValues("5", r.Five.Txt)
|
||||||
|
// test number.
|
||||||
|
a.EqualValues(seven, r.Seven.Val)
|
||||||
|
a.EqualValues("7", r.Seven.Txt)
|
||||||
|
// test string.
|
||||||
|
a.EqualValues(0, r.Auto.Val)
|
||||||
|
a.EqualValues("auto", r.Auto.Txt)
|
||||||
|
// test (error) struct.
|
||||||
|
a.NotNil(json.Unmarshal([]byte(`{"channel": {}}`), &r),
|
||||||
|
"a non-string and non-number must produce an error.")
|
||||||
|
a.EqualValues(0, r.Channel.Val)
|
||||||
|
// test null.
|
||||||
|
a.EqualValues(0, r.Nil.Val)
|
||||||
|
a.EqualValues("0", r.Nil.Txt)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,566 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UAP represents all the data from the Ubiquiti Controller for a Unifi Access Point.
|
||||||
|
// This was auto generated then edited by hand to get all the data types right.
|
||||||
|
type UAP struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Adopted FlexBool `json:"adopted"`
|
||||||
|
AntennaTable []struct {
|
||||||
|
Default FlexBool `json:"default"`
|
||||||
|
ID FlexInt `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Wifi0Gain FlexInt `json:"wifi0_gain"`
|
||||||
|
Wifi1Gain FlexInt `json:"wifi1_gain"`
|
||||||
|
} `json:"antenna_table"`
|
||||||
|
BandsteeringMode string `json:"bandsteering_mode,omitempty"`
|
||||||
|
BoardRev int `json:"board_rev"`
|
||||||
|
Cfgversion string `json:"cfgversion"`
|
||||||
|
ConfigNetwork struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
} `json:"config_network"`
|
||||||
|
CountrycodeTable []int `json:"countrycode_table"`
|
||||||
|
EthernetTable []struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
NumPort FlexInt `json:"num_port"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"ethernet_table"`
|
||||||
|
FwCaps int `json:"fw_caps"`
|
||||||
|
HasEth1 FlexBool `json:"has_eth1"`
|
||||||
|
HasSpeaker FlexBool `json:"has_speaker"`
|
||||||
|
InformIP string `json:"inform_ip"`
|
||||||
|
InformURL string `json:"inform_url"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
LedOverride string `json:"led_override"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
MeshStaVapEnabled FlexBool `json:"mesh_sta_vap_enabled"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OutdoorModeOverride string `json:"outdoor_mode_override"`
|
||||||
|
PortTable []Port `json:"port_table"`
|
||||||
|
RadioTable RadioTable `json:"radio_table"`
|
||||||
|
ScanRadioTable []interface{} `json:"scan_radio_table"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
VwireTable []interface{} `json:"vwire_table"`
|
||||||
|
WifiCaps int `json:"wifi_caps"`
|
||||||
|
WlangroupIDNa string `json:"wlangroup_id_na"`
|
||||||
|
WlangroupIDNg string `json:"wlangroup_id_ng"`
|
||||||
|
RequiredVersion string `json:"required_version"`
|
||||||
|
HwCaps int `json:"hw_caps"`
|
||||||
|
Unsupported FlexBool `json:"unsupported"`
|
||||||
|
UnsupportedReason FlexInt `json:"unsupported_reason"`
|
||||||
|
SysErrorCaps int `json:"sys_error_caps"`
|
||||||
|
HasFan FlexBool `json:"has_fan"`
|
||||||
|
HasTemperature FlexBool `json:"has_temperature"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
State int `json:"state"`
|
||||||
|
LastSeen FlexInt `json:"last_seen"`
|
||||||
|
Upgradable FlexBool `json:"upgradable"`
|
||||||
|
AdoptableWhenUpgraded FlexBool `json:"adoptable_when_upgraded"`
|
||||||
|
Rollupgrade FlexBool `json:"rollupgrade"`
|
||||||
|
KnownCfgversion string `json:"known_cfgversion"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
UUptime FlexInt `json:"_uptime"`
|
||||||
|
Locating FlexBool `json:"locating"`
|
||||||
|
ConnectRequestIP string `json:"connect_request_ip"`
|
||||||
|
ConnectRequestPort string `json:"connect_request_port"`
|
||||||
|
SysStats SysStats `json:"sys_stats"`
|
||||||
|
SystemStats SystemStats `json:"system-stats"`
|
||||||
|
SSHSessionTable []interface{} `json:"ssh_session_table"`
|
||||||
|
Scanning FlexBool `json:"scanning"`
|
||||||
|
SpectrumScanning FlexBool `json:"spectrum_scanning"`
|
||||||
|
GuestToken string `json:"guest_token"`
|
||||||
|
Meshv3PeerMac string `json:"meshv3_peer_mac"`
|
||||||
|
Satisfaction FlexInt `json:"satisfaction"`
|
||||||
|
Isolated FlexBool `json:"isolated"`
|
||||||
|
RadioTableStats RadioTableStats `json:"radio_table_stats"`
|
||||||
|
Uplink struct {
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
MaxVlan int `json:"max_vlan"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Netmask string `json:"netmask"`
|
||||||
|
NumPort int `json:"num_port"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxMulticast FlexInt `json:"rx_multicast"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
MaxSpeed FlexInt `json:"max_speed"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
TxBytesR FlexInt `json:"tx_bytes-r"`
|
||||||
|
RxBytesR FlexInt `json:"rx_bytes-r"`
|
||||||
|
UplinkMac string `json:"uplink_mac"`
|
||||||
|
UplinkRemotePort int `json:"uplink_remote_port"`
|
||||||
|
} `json:"uplink"`
|
||||||
|
VapTable VapTable `json:"vap_table"`
|
||||||
|
DownlinkTable []struct {
|
||||||
|
PortIdx int `json:"port_idx"`
|
||||||
|
Speed int `json:"speed"`
|
||||||
|
FullDuplex bool `json:"full_duplex"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
} `json:"downlink_table,omitempty"`
|
||||||
|
VwireVapTable []interface{} `json:"vwire_vap_table"`
|
||||||
|
BytesD FlexInt `json:"bytes-d"`
|
||||||
|
TxBytesD FlexInt `json:"tx_bytes-d"`
|
||||||
|
RxBytesD FlexInt `json:"rx_bytes-d"`
|
||||||
|
BytesR FlexInt `json:"bytes-r"`
|
||||||
|
LastUplink struct {
|
||||||
|
UplinkMac string `json:"uplink_mac"`
|
||||||
|
UplinkRemotePort int `json:"uplink_remote_port"`
|
||||||
|
} `json:"last_uplink"`
|
||||||
|
Stat UAPStat `json:"stat"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
Bytes FlexInt `json:"bytes"`
|
||||||
|
VwireEnabled FlexBool `json:"vwireEnabled"`
|
||||||
|
UplinkTable []interface{} `json:"uplink_table"`
|
||||||
|
NumSta FlexInt `json:"num_sta"`
|
||||||
|
UserNumSta FlexInt `json:"user-num_sta"`
|
||||||
|
GuestNumSta FlexInt `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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ap is a subtype of UAPStat to make unmarshalling of different controller versions possible.
|
||||||
|
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"`
|
||||||
|
Bytes FlexInt `json:"bytes"`
|
||||||
|
Duration FlexInt `json:"duration"`
|
||||||
|
WifiTxDropped FlexInt `json:"wifi_tx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxFrags FlexInt `json:"rx_frags"`
|
||||||
|
RxCrypts FlexInt `json:"rx_crypts"`
|
||||||
|
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"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
UserRxDropped FlexInt `json:"user-rx_dropped"`
|
||||||
|
GuestRxDropped FlexInt `json:"guest-rx_dropped"`
|
||||||
|
UserRxErrors FlexInt `json:"user-rx_errors"`
|
||||||
|
GuestRxErrors FlexInt `json:"guest-rx_errors"`
|
||||||
|
UserRxPackets FlexInt `json:"user-rx_packets"`
|
||||||
|
GuestRxPackets FlexInt `json:"guest-rx_packets"`
|
||||||
|
UserRxBytes FlexInt `json:"user-rx_bytes"`
|
||||||
|
GuestRxBytes FlexInt `json:"guest-rx_bytes"`
|
||||||
|
UserRxCrypts FlexInt `json:"user-rx_crypts"`
|
||||||
|
GuestRxCrypts FlexInt `json:"guest-rx_crypts"`
|
||||||
|
UserRxFrags FlexInt `json:"user-rx_frags"`
|
||||||
|
GuestRxFrags FlexInt `json:"guest-rx_frags"`
|
||||||
|
UserTxPackets FlexInt `json:"user-tx_packets"`
|
||||||
|
GuestTxPackets FlexInt `json:"guest-tx_packets"`
|
||||||
|
UserTxBytes FlexInt `json:"user-tx_bytes"`
|
||||||
|
GuestTxBytes FlexInt `json:"guest-tx_bytes"`
|
||||||
|
UserTxErrors FlexInt `json:"user-tx_errors"`
|
||||||
|
GuestTxErrors FlexInt `json:"guest-tx_errors"`
|
||||||
|
UserTxDropped FlexInt `json:"user-tx_dropped"`
|
||||||
|
GuestTxDropped FlexInt `json:"guest-tx_dropped"`
|
||||||
|
UserTxRetries FlexInt `json:"user-tx_retries"`
|
||||||
|
GuestTxRetries FlexInt `json:"guest-tx_retries"`
|
||||||
|
MacFilterRejections FlexInt `json:"mac_filter_rejections"`
|
||||||
|
UserMacFilterRejections FlexInt `json:"user-mac_filter_rejections"`
|
||||||
|
GuestMacFilterRejections FlexInt `json:"guest-mac_filter_rejections"`
|
||||||
|
WifiTxAttempts FlexInt `json:"wifi_tx_attempts"`
|
||||||
|
UserWifiTxDropped FlexInt `json:"user-wifi_tx_dropped"`
|
||||||
|
GuestWifiTxDropped FlexInt `json:"guest-wifi_tx_dropped"`
|
||||||
|
UserWifiTxAttempts FlexInt `json:"user-wifi_tx_attempts"`
|
||||||
|
GuestWifiTxAttempts FlexInt `json:"guest-wifi_tx_attempts"`
|
||||||
|
|
||||||
|
// UAP-AC-PRO names, others may differ.
|
||||||
|
/* These are all in VAP TABLE */
|
||||||
|
/*
|
||||||
|
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"`
|
||||||
|
Wifi0RxPackets FlexInt `json:"wifi0-rx_packets"`
|
||||||
|
Wifi1RxPackets FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0RxBytes FlexInt `json:"wifi0-rx_bytes"`
|
||||||
|
Wifi1RxBytes FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0RxErrors FlexInt `json:"wifi0-rx_errors"`
|
||||||
|
Wifi1RxErrors FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0RxDropped FlexInt `json:"wifi0-rx_dropped"`
|
||||||
|
Wifi1RxDropped FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0RxCrypts FlexInt `json:"wifi0-rx_crypts"`
|
||||||
|
Wifi1RxCrypts FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0RxFrags FlexInt `json:"wifi0-rx_frags"`
|
||||||
|
Wifi1RxFrags FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0TxPackets FlexInt `json:"wifi0-tx_packets"`
|
||||||
|
Wifi1TxPackets FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0TxBytes FlexInt `json:"wifi0-tx_bytes"`
|
||||||
|
Wifi1TxBytes FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0TxErrors FlexInt `json:"wifi0-tx_errors"`
|
||||||
|
Wifi1TxErrors FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0TxDropped FlexInt `json:"wifi0-tx_dropped"`
|
||||||
|
Wifi1TxDropped FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0TxRetries FlexInt `json:"wifi0-tx_retries"`
|
||||||
|
Wifi1TxRetries FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0MacFilterRejections FlexInt `json:"wifi0-mac_filter_rejections"`
|
||||||
|
Wifi1MacFilterRejections FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0WifiTxAttempts FlexInt `json:"wifi0-wifi_tx_attempts"`
|
||||||
|
Wifi1WifiTxAttempts FlexInt `json:"wifi1-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"`
|
||||||
|
Wifi0WifiTxDropped FlexInt `json:"wifi0-wifi_tx_dropped"`
|
||||||
|
Wifi1WifiTxDropped FlexInt `json:"wifi1-wifi_tx_dropped"`
|
||||||
|
// UDM Names
|
||||||
|
GuestRa0RxPackets FlexInt `json:"guest-ra0-rx_packets"`
|
||||||
|
UserRa0RxPackets FlexInt `json:"user-ra0-rx_packets"`
|
||||||
|
Ra0RxPackets FlexInt `json:"ra0-rx_packets"`
|
||||||
|
GuestRa0RxBytes FlexInt `json:"guest-ra0-rx_bytes"`
|
||||||
|
UserRa0RxBytes FlexInt `json:"user-ra0-rx_bytes"`
|
||||||
|
Ra0RxBytes FlexInt `json:"ra0-rx_bytes"`
|
||||||
|
GuestRa0RxErrors FlexInt `json:"guest-ra0-rx_errors"`
|
||||||
|
UserRa0RxErrors FlexInt `json:"user-ra0-rx_errors"`
|
||||||
|
Ra0RxErrors FlexInt `json:"ra0-rx_errors"`
|
||||||
|
GuestRa0RxDropped FlexInt `json:"guest-ra0-rx_dropped"`
|
||||||
|
UserRa0RxDropped FlexInt `json:"user-ra0-rx_dropped"`
|
||||||
|
Ra0RxDropped FlexInt `json:"ra0-rx_dropped"`
|
||||||
|
GuestRa0RxCrypts FlexInt `json:"guest-ra0-rx_crypts"`
|
||||||
|
UserRa0RxCrypts FlexInt `json:"user-ra0-rx_crypts"`
|
||||||
|
Ra0RxCrypts FlexInt `json:"ra0-rx_crypts"`
|
||||||
|
GuestRa0RxFrags FlexInt `json:"guest-ra0-rx_frags"`
|
||||||
|
UserRa0RxFrags FlexInt `json:"user-ra0-rx_frags"`
|
||||||
|
Ra0RxFrags FlexInt `json:"ra0-rx_frags"`
|
||||||
|
GuestRa0TxPackets FlexInt `json:"guest-ra0-tx_packets"`
|
||||||
|
UserRa0TxPackets FlexInt `json:"user-ra0-tx_packets"`
|
||||||
|
Ra0TxPackets FlexInt `json:"ra0-tx_packets"`
|
||||||
|
GuestRa0TxBytes FlexInt `json:"guest-ra0-tx_bytes"`
|
||||||
|
UserRa0TxBytes FlexInt `json:"user-ra0-tx_bytes"`
|
||||||
|
Ra0TxBytes FlexInt `json:"ra0-tx_bytes"`
|
||||||
|
GuestRa0TxErrors FlexInt `json:"guest-ra0-tx_errors"`
|
||||||
|
UserRa0TxErrors FlexInt `json:"user-ra0-tx_errors"`
|
||||||
|
Ra0TxErrors FlexInt `json:"ra0-tx_errors"`
|
||||||
|
GuestRa0TxDropped FlexInt `json:"guest-ra0-tx_dropped"`
|
||||||
|
UserRa0TxDropped FlexInt `json:"user-ra0-tx_dropped"`
|
||||||
|
Ra0TxDropped FlexInt `json:"ra0-tx_dropped"`
|
||||||
|
GuestRa0TxRetries FlexInt `json:"guest-ra0-tx_retries"`
|
||||||
|
UserRa0TxRetries FlexInt `json:"user-ra0-tx_retries"`
|
||||||
|
Ra0TxRetries FlexInt `json:"ra0-tx_retries"`
|
||||||
|
GuestRa0MacFilterRejections FlexInt `json:"guest-ra0-mac_filter_rejections"`
|
||||||
|
UserRa0MacFilterRejections FlexInt `json:"user-ra0-mac_filter_rejections"`
|
||||||
|
Ra0MacFilterRejections FlexInt `json:"ra0-mac_filter_rejections"`
|
||||||
|
GuestRa0WifiTxAttempts FlexInt `json:"guest-ra0-wifi_tx_attempts"`
|
||||||
|
UserRa0WifiTxAttempts FlexInt `json:"user-ra0-wifi_tx_attempts"`
|
||||||
|
Ra0WifiTxAttempts FlexInt `json:"ra0-wifi_tx_attempts"`
|
||||||
|
GuestRa0WifiTxDropped FlexInt `json:"guest-ra0-wifi_tx_dropped"`
|
||||||
|
UserRa0WifiTxDropped FlexInt `json:"user-ra0-wifi_tx_dropped"`
|
||||||
|
Ra0WifiTxDropped FlexInt `json:"ra0-wifi_tx_dropped"`
|
||||||
|
GuestRai0RxPackets FlexInt `json:"guest-rai0-rx_packets"`
|
||||||
|
UserRai0RxPackets FlexInt `json:"user-rai0-rx_packets"`
|
||||||
|
Rai0RxPackets FlexInt `json:"rai0-rx_packets"`
|
||||||
|
GuestRai0RxBytes FlexInt `json:"guest-rai0-rx_bytes"`
|
||||||
|
UserRai0RxBytes FlexInt `json:"user-rai0-rx_bytes"`
|
||||||
|
Rai0RxBytes FlexInt `json:"rai0-rx_bytes"`
|
||||||
|
GuestRai0RxErrors FlexInt `json:"guest-rai0-rx_errors"`
|
||||||
|
UserRai0RxErrors FlexInt `json:"user-rai0-rx_errors"`
|
||||||
|
Rai0RxErrors FlexInt `json:"rai0-rx_errors"`
|
||||||
|
GuestRai0RxDropped FlexInt `json:"guest-rai0-rx_dropped"`
|
||||||
|
UserRai0RxDropped FlexInt `json:"user-rai0-rx_dropped"`
|
||||||
|
Rai0RxDropped FlexInt `json:"rai0-rx_dropped"`
|
||||||
|
GuestRai0RxCrypts FlexInt `json:"guest-rai0-rx_crypts"`
|
||||||
|
UserRai0RxCrypts FlexInt `json:"user-rai0-rx_crypts"`
|
||||||
|
Rai0RxCrypts FlexInt `json:"rai0-rx_crypts"`
|
||||||
|
GuestRai0RxFrags FlexInt `json:"guest-rai0-rx_frags"`
|
||||||
|
UserRai0RxFrags FlexInt `json:"user-rai0-rx_frags"`
|
||||||
|
Rai0RxFrags FlexInt `json:"rai0-rx_frags"`
|
||||||
|
GuestRai0TxPackets FlexInt `json:"guest-rai0-tx_packets"`
|
||||||
|
UserRai0TxPackets FlexInt `json:"user-rai0-tx_packets"`
|
||||||
|
Rai0TxPackets FlexInt `json:"rai0-tx_packets"`
|
||||||
|
GuestRai0TxBytes FlexInt `json:"guest-rai0-tx_bytes"`
|
||||||
|
UserRai0TxBytes FlexInt `json:"user-rai0-tx_bytes"`
|
||||||
|
Rai0TxBytes FlexInt `json:"rai0-tx_bytes"`
|
||||||
|
GuestRai0TxErrors FlexInt `json:"guest-rai0-tx_errors"`
|
||||||
|
UserRai0TxErrors FlexInt `json:"user-rai0-tx_errors"`
|
||||||
|
Rai0TxErrors FlexInt `json:"rai0-tx_errors"`
|
||||||
|
GuestRai0TxDropped FlexInt `json:"guest-rai0-tx_dropped"`
|
||||||
|
UserRai0TxDropped FlexInt `json:"user-rai0-tx_dropped"`
|
||||||
|
Rai0TxDropped FlexInt `json:"rai0-tx_dropped"`
|
||||||
|
GuestRai0TxRetries FlexInt `json:"guest-rai0-tx_retries"`
|
||||||
|
UserRai0TxRetries FlexInt `json:"user-rai0-tx_retries"`
|
||||||
|
Rai0TxRetries FlexInt `json:"rai0-tx_retries"`
|
||||||
|
GuestRai0MacFilterRejections FlexInt `json:"guest-rai0-mac_filter_rejections"`
|
||||||
|
UserRai0MacFilterRejections FlexInt `json:"user-rai0-mac_filter_rejections"`
|
||||||
|
Rai0MacFilterRejections FlexInt `json:"rai0-mac_filter_rejections"`
|
||||||
|
GuestRai0WifiTxAttempts FlexInt `json:"guest-rai0-wifi_tx_attempts"`
|
||||||
|
UserRai0WifiTxAttempts FlexInt `json:"user-rai0-wifi_tx_attempts"`
|
||||||
|
Rai0WifiTxAttempts FlexInt `json:"rai0-wifi_tx_attempts"`
|
||||||
|
GuestRai0WifiTxDropped FlexInt `json:"guest-rai0-wifi_tx_dropped"`
|
||||||
|
UserRai0WifiTxDropped FlexInt `json:"user-rai0-wifi_tx_dropped"`
|
||||||
|
Rai0WifiTxDropped FlexInt `json:"rai0-wifi_tx_dropped"`
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// RadioTable is part of the data for UAPs and UDMs.
|
||||||
|
type RadioTable []struct {
|
||||||
|
AntennaGain FlexInt `json:"antenna_gain"`
|
||||||
|
BuiltinAntGain FlexInt `json:"builtin_ant_gain"`
|
||||||
|
BuiltinAntenna FlexBool `json:"builtin_antenna"`
|
||||||
|
Channel FlexInt `json:"channel"`
|
||||||
|
CurrentAntennaGain FlexInt `json:"current_antenna_gain"`
|
||||||
|
HasDfs FlexBool `json:"has_dfs"`
|
||||||
|
HasFccdfs FlexBool `json:"has_fccdfs"`
|
||||||
|
HasHt160 FlexBool `json:"has_ht160"`
|
||||||
|
Ht FlexInt `json:"ht"`
|
||||||
|
Is11Ac FlexBool `json:"is_11ac"`
|
||||||
|
MaxTxpower FlexInt `json:"max_txpower"`
|
||||||
|
MinRssi FlexInt `json:"min_rssi,omitempty"`
|
||||||
|
MinRssiEnabled FlexBool `json:"min_rssi_enabled"`
|
||||||
|
MinTxpower FlexInt `json:"min_txpower"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Nss FlexInt `json:"nss"`
|
||||||
|
Radio string `json:"radio"`
|
||||||
|
RadioCaps FlexInt `json:"radio_caps"`
|
||||||
|
SensLevelEnabled FlexBool `json:"sens_level_enabled"`
|
||||||
|
TxPower FlexInt `json:"tx_power"`
|
||||||
|
TxPowerMode string `json:"tx_power_mode"`
|
||||||
|
VwireEnabled FlexBool `json:"vwire_enabled"`
|
||||||
|
WlangroupID string `json:"wlangroup_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RadioTableStats is part of the data shared between UAP and UDM
|
||||||
|
type RadioTableStats []struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Channel FlexInt `json:"channel"`
|
||||||
|
Radio string `json:"radio"`
|
||||||
|
AstTxto interface{} `json:"ast_txto"`
|
||||||
|
AstCst interface{} `json:"ast_cst"`
|
||||||
|
AstBeXmit FlexInt `json:"ast_be_xmit"`
|
||||||
|
CuTotal FlexInt `json:"cu_total"`
|
||||||
|
CuSelfRx FlexInt `json:"cu_self_rx"`
|
||||||
|
CuSelfTx FlexInt `json:"cu_self_tx"`
|
||||||
|
Gain FlexInt `json:"gain"`
|
||||||
|
Satisfaction FlexInt `json:"satisfaction"`
|
||||||
|
State string `json:"state"`
|
||||||
|
Extchannel FlexInt `json:"extchannel"`
|
||||||
|
TxPower FlexInt `json:"tx_power"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
TxRetries FlexInt `json:"tx_retries"`
|
||||||
|
NumSta FlexInt `json:"num_sta"`
|
||||||
|
GuestNumSta FlexInt `json:"guest-num_sta"`
|
||||||
|
UserNumSta FlexInt `json:"user-num_sta"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// VapTable holds much of the UAP wireless data. Shared by UDM.
|
||||||
|
type VapTable []struct {
|
||||||
|
AnomaliesBarChart struct {
|
||||||
|
HighDNSLatency FlexInt `json:"high_dns_latency"`
|
||||||
|
HighTCPLatency FlexInt `json:"high_tcp_latency"`
|
||||||
|
HighTCPPacketLoss FlexInt `json:"high_tcp_packet_loss"`
|
||||||
|
HighWifiLatency FlexInt `json:"high_wifi_latency"`
|
||||||
|
HighWifiRetries FlexInt `json:"high_wifi_retries"`
|
||||||
|
LowPhyRate FlexInt `json:"low_phy_rate"`
|
||||||
|
PoorStreamEff FlexInt `json:"poor_stream_eff"`
|
||||||
|
SleepyClient FlexInt `json:"sleepy_client"`
|
||||||
|
StaArpTimeout FlexInt `json:"sta_arp_timeout"`
|
||||||
|
StaDNSTimeout FlexInt `json:"sta_dns_timeout"`
|
||||||
|
StaIPTimeout FlexInt `json:"sta_ip_timeout"`
|
||||||
|
WeakSignal FlexInt `json:"weak_signal"`
|
||||||
|
} `json:"anomalies_bar_chart"`
|
||||||
|
AnomaliesBarChartNow struct {
|
||||||
|
HighDNSLatency FlexInt `json:"high_dns_latency"`
|
||||||
|
HighTCPLatency FlexInt `json:"high_tcp_latency"`
|
||||||
|
HighTCPPacketLoss FlexInt `json:"high_tcp_packet_loss"`
|
||||||
|
HighWifiLatency FlexInt `json:"high_wifi_latency"`
|
||||||
|
HighWifiRetries FlexInt `json:"high_wifi_retries"`
|
||||||
|
LowPhyRate FlexInt `json:"low_phy_rate"`
|
||||||
|
PoorStreamEff FlexInt `json:"poor_stream_eff"`
|
||||||
|
SleepyClient FlexInt `json:"sleepy_client"`
|
||||||
|
StaArpTimeout FlexInt `json:"sta_arp_timeout"`
|
||||||
|
StaDNSTimeout FlexInt `json:"sta_dns_timeout"`
|
||||||
|
StaIPTimeout FlexInt `json:"sta_ip_timeout"`
|
||||||
|
WeakSignal FlexInt `json:"weak_signal"`
|
||||||
|
} `json:"anomalies_bar_chart_now"`
|
||||||
|
ReasonsBarChart struct {
|
||||||
|
PhyRate FlexInt `json:"phy_rate"`
|
||||||
|
Signal FlexInt `json:"signal"`
|
||||||
|
SleepyClient FlexInt `json:"sleepy_client"`
|
||||||
|
StaArpTimeout FlexInt `json:"sta_arp_timeout"`
|
||||||
|
StaDNSLatency FlexInt `json:"sta_dns_latency"`
|
||||||
|
StaDNSTimeout FlexInt `json:"sta_dns_timeout"`
|
||||||
|
StaIPTimeout FlexInt `json:"sta_ip_timeout"`
|
||||||
|
StreamEff FlexInt `json:"stream_eff"`
|
||||||
|
TCPLatency FlexInt `json:"tcp_latency"`
|
||||||
|
TCPPacketLoss FlexInt `json:"tcp_packet_loss"`
|
||||||
|
WifiLatency FlexInt `json:"wifi_latency"`
|
||||||
|
WifiRetries FlexInt `json:"wifi_retries"`
|
||||||
|
} `json:"reasons_bar_chart"`
|
||||||
|
ReasonsBarChartNow struct {
|
||||||
|
PhyRate FlexInt `json:"phy_rate"`
|
||||||
|
Signal FlexInt `json:"signal"`
|
||||||
|
SleepyClient FlexInt `json:"sleepy_client"`
|
||||||
|
StaArpTimeout FlexInt `json:"sta_arp_timeout"`
|
||||||
|
StaDNSLatency FlexInt `json:"sta_dns_latency"`
|
||||||
|
StaDNSTimeout FlexInt `json:"sta_dns_timeout"`
|
||||||
|
StaIPTimeout FlexInt `json:"sta_ip_timeout"`
|
||||||
|
StreamEff FlexInt `json:"stream_eff"`
|
||||||
|
TCPLatency FlexInt `json:"tcp_latency"`
|
||||||
|
TCPPacketLoss FlexInt `json:"tcp_packet_loss"`
|
||||||
|
WifiLatency FlexInt `json:"wifi_latency"`
|
||||||
|
WifiRetries FlexInt `json:"wifi_retries"`
|
||||||
|
} `json:"reasons_bar_chart_now"`
|
||||||
|
RxTCPStats struct {
|
||||||
|
Goodbytes FlexInt `json:"goodbytes"`
|
||||||
|
LatAvg FlexInt `json:"lat_avg"`
|
||||||
|
LatMax FlexInt `json:"lat_max"`
|
||||||
|
LatMin FlexInt `json:"lat_min"`
|
||||||
|
Stalls FlexInt `json:"stalls"`
|
||||||
|
} `json:"rx_tcp_stats"`
|
||||||
|
TxTCPStats struct {
|
||||||
|
Goodbytes FlexInt `json:"goodbytes"`
|
||||||
|
LatAvg FlexInt `json:"lat_avg"`
|
||||||
|
LatMax FlexInt `json:"lat_max"`
|
||||||
|
LatMin FlexInt `json:"lat_min"`
|
||||||
|
Stalls FlexInt `json:"stalls"`
|
||||||
|
} `json:"tx_tcp_stats"`
|
||||||
|
WifiTxLatencyMov struct {
|
||||||
|
Avg FlexInt `json:"avg"`
|
||||||
|
Max FlexInt `json:"max"`
|
||||||
|
Min FlexInt `json:"min"`
|
||||||
|
Total FlexInt `json:"total"`
|
||||||
|
TotalCount FlexInt `json:"total_count"`
|
||||||
|
} `json:"wifi_tx_latency_mov"`
|
||||||
|
ApMac string `json:"ap_mac"`
|
||||||
|
AvgClientSignal FlexInt `json:"avg_client_signal"`
|
||||||
|
Bssid string `json:"bssid"`
|
||||||
|
Ccq int `json:"ccq"`
|
||||||
|
Channel FlexInt `json:"channel"`
|
||||||
|
DNSAvgLatency FlexInt `json:"dns_avg_latency"`
|
||||||
|
Essid string `json:"essid"`
|
||||||
|
Extchannel int `json:"extchannel"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
IsGuest FlexBool `json:"is_guest"`
|
||||||
|
IsWep FlexBool `json:"is_wep"`
|
||||||
|
MacFilterRejections int `json:"mac_filter_rejections"`
|
||||||
|
MapID interface{} `json:"map_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
NumSatisfactionSta FlexInt `json:"num_satisfaction_sta"`
|
||||||
|
NumSta int `json:"num_sta"`
|
||||||
|
Radio string `json:"radio"`
|
||||||
|
RadioName string `json:"radio_name"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxCrypts FlexInt `json:"rx_crypts"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxFrags FlexInt `json:"rx_frags"`
|
||||||
|
RxNwids FlexInt `json:"rx_nwids"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
Satisfaction FlexInt `json:"satisfaction"`
|
||||||
|
SatisfactionNow FlexInt `json:"satisfaction_now"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
State string `json:"state"`
|
||||||
|
T string `json:"t"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxCombinedRetries FlexInt `json:"tx_combined_retries"`
|
||||||
|
TxDataMpduBytes FlexInt `json:"tx_data_mpdu_bytes"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
TxPower FlexInt `json:"tx_power"`
|
||||||
|
TxRetries FlexInt `json:"tx_retries"`
|
||||||
|
TxRtsRetries FlexInt `json:"tx_rts_retries"`
|
||||||
|
TxSuccess FlexInt `json:"tx_success"`
|
||||||
|
TxTotal FlexInt `json:"tx_total"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
Usage string `json:"usage"`
|
||||||
|
WifiTxAttempts FlexInt `json:"wifi_tx_attempts"`
|
||||||
|
WifiTxDropped FlexInt `json:"wifi_tx_dropped"`
|
||||||
|
WlanconfID string `json:"wlanconf_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
rxPakcets := 49299197
|
||||||
|
u := &UAPStat{}
|
||||||
|
err := u.UnmarshalJSON([]byte(testcontroller510))
|
||||||
|
a.Nil(err, "must be no error unmarshaling test strings")
|
||||||
|
a.Equal(float64(rxPakcets), 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(rxPakcets), u.RxPackets.Val, "data was not properly unmarshaled")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
// UDM represents all the data from the Ubiquiti Controller for a Unifi Dream Machine.
|
||||||
|
// The UDM shares several structs/type-data with USW and USG.
|
||||||
|
type UDM struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Adopted FlexBool `json:"adopted"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Default FlexBool `json:"default"`
|
||||||
|
Locating FlexBool `json:"locating"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Unsupported FlexBool `json:"unsupported"`
|
||||||
|
UnsupportedReason FlexInt `json:"unsupported_reason"`
|
||||||
|
DiscoveredVia string `json:"discovered_via"`
|
||||||
|
AdoptIP string `json:"adopt_ip"`
|
||||||
|
AdoptURL string `json:"adopt_url"`
|
||||||
|
State FlexInt `json:"state"`
|
||||||
|
AdoptStatus FlexInt `json:"adopt_status"`
|
||||||
|
UpgradeState FlexInt `json:"upgrade_state"`
|
||||||
|
LastSeen FlexInt `json:"last_seen"`
|
||||||
|
AdoptableWhenUpgraded FlexBool `json:"adoptable_when_upgraded"`
|
||||||
|
Cfgversion string `json:"cfgversion"`
|
||||||
|
ConfigNetwork struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
} `json:"config_network"`
|
||||||
|
VwireTable []interface{} `json:"vwire_table"`
|
||||||
|
Dot1XPortctrlEnabled FlexBool `json:"dot1x_portctrl_enabled"`
|
||||||
|
JumboframeEnabled FlexBool `json:"jumboframe_enabled"`
|
||||||
|
FlowctrlEnabled FlexBool `json:"flowctrl_enabled"`
|
||||||
|
StpVersion string `json:"stp_version"`
|
||||||
|
StpPriority FlexInt `json:"stp_priority"`
|
||||||
|
PowerSourceCtrlEnabled FlexBool `json:"power_source_ctrl_enabled"`
|
||||||
|
LicenseState string `json:"license_state"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
AdoptState FlexInt `json:"adopt_state"`
|
||||||
|
AdoptTries FlexInt `json:"adopt_tries"`
|
||||||
|
AdoptManual FlexBool `json:"adopt_manual"`
|
||||||
|
InformURL string `json:"inform_url"`
|
||||||
|
InformIP string `json:"inform_ip"`
|
||||||
|
RequiredVersion string `json:"required_version"`
|
||||||
|
BoardRev FlexInt `json:"board_rev"`
|
||||||
|
EthernetTable []struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
NumPort FlexInt `json:"num_port"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"ethernet_table"`
|
||||||
|
PortTable []Port `json:"port_table"`
|
||||||
|
EthernetOverrides []struct {
|
||||||
|
Ifname string `json:"ifname"`
|
||||||
|
Networkgroup string `json:"networkgroup"`
|
||||||
|
} `json:"ethernet_overrides"`
|
||||||
|
UsgCaps FlexInt `json:"usg_caps"`
|
||||||
|
HasSpeaker FlexBool `json:"has_speaker"`
|
||||||
|
HasEth1 FlexBool `json:"has_eth1"`
|
||||||
|
FwCaps FlexInt `json:"fw_caps"`
|
||||||
|
HwCaps FlexInt `json:"hw_caps"`
|
||||||
|
WifiCaps FlexInt `json:"wifi_caps"`
|
||||||
|
SwitchCaps struct {
|
||||||
|
MaxMirrorSessions FlexInt `json:"max_mirror_sessions"`
|
||||||
|
MaxAggregateSessions FlexInt `json:"max_aggregate_sessions"`
|
||||||
|
} `json:"switch_caps"`
|
||||||
|
HasFan FlexBool `json:"has_fan"`
|
||||||
|
HasTemperature FlexBool `json:"has_temperature"`
|
||||||
|
RulesetInterfaces interface{} `json:"ruleset_interfaces"`
|
||||||
|
/* struct {
|
||||||
|
Br0 string `json:"br0"`
|
||||||
|
Eth0 string `json:"eth0"`
|
||||||
|
Eth1 string `json:"eth1"`
|
||||||
|
Eth2 string `json:"eth2"`
|
||||||
|
Eth3 string `json:"eth3"`
|
||||||
|
Eth4 string `json:"eth4"`
|
||||||
|
Eth5 string `json:"eth5"`
|
||||||
|
Eth6 string `json:"eth6"`
|
||||||
|
Eth7 string `json:"eth7"`
|
||||||
|
Eth8 string `json:"eth8"`
|
||||||
|
} */
|
||||||
|
KnownCfgversion string `json:"known_cfgversion"`
|
||||||
|
SysStats SysStats `json:"sys_stats"`
|
||||||
|
SystemStats SystemStats `json:"system-stats"`
|
||||||
|
GuestToken string `json:"guest_token"`
|
||||||
|
Overheating FlexBool `json:"overheating"`
|
||||||
|
SpeedtestStatus SpeedtestStatus `json:"speedtest-status"`
|
||||||
|
SpeedtestStatusSaved FlexBool `json:"speedtest-status-saved"`
|
||||||
|
Wan1 Wan `json:"wan1"`
|
||||||
|
Wan2 Wan `json:"wan2"`
|
||||||
|
Uplink Uplink `json:"uplink"`
|
||||||
|
ConnectRequestIP string `json:"connect_request_ip"`
|
||||||
|
ConnectRequestPort string `json:"connect_request_port"`
|
||||||
|
DownlinkTable []interface{} `json:"downlink_table"`
|
||||||
|
WlangroupIDNa string `json:"wlangroup_id_na"`
|
||||||
|
WlangroupIDNg string `json:"wlangroup_id_ng"`
|
||||||
|
BandsteeringMode string `json:"bandsteering_mode"`
|
||||||
|
RadioTable *RadioTable `json:"radio_table,omitempty"`
|
||||||
|
RadioTableStats *RadioTableStats `json:"radio_table_stats,omitempty"`
|
||||||
|
VapTable *VapTable `json:"vap_table"`
|
||||||
|
XInformAuthkey string `json:"x_inform_authkey"`
|
||||||
|
NetworkTable NetworkTable `json:"network_table"`
|
||||||
|
PortOverrides []struct {
|
||||||
|
PortIdx FlexInt `json:"port_idx"`
|
||||||
|
PortconfID string `json:"portconf_id"`
|
||||||
|
} `json:"port_overrides"`
|
||||||
|
Stat UDMStat `json:"stat"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
Bytes FlexInt `json:"bytes"`
|
||||||
|
BytesD FlexInt `json:"bytes-d"`
|
||||||
|
TxBytesD FlexInt `json:"tx_bytes-d"`
|
||||||
|
RxBytesD FlexInt `json:"rx_bytes-d"`
|
||||||
|
BytesR FlexInt `json:"bytes-r"`
|
||||||
|
NumSta FlexInt `json:"num_sta"` // USG
|
||||||
|
WlanNumSta FlexInt `json:"wlan-num_sta"` // UAP
|
||||||
|
LanNumSta FlexInt `json:"lan-num_sta"` // USW
|
||||||
|
UserWlanNumSta FlexInt `json:"user-wlan-num_sta"` // UAP
|
||||||
|
UserLanNumSta FlexInt `json:"user-lan-num_sta"` // USW
|
||||||
|
UserNumSta FlexInt `json:"user-num_sta"` // USG
|
||||||
|
GuestWlanNumSta FlexInt `json:"guest-wlan-num_sta"` // UAP
|
||||||
|
GuestLanNumSta FlexInt `json:"guest-lan-num_sta"` // USW
|
||||||
|
GuestNumSta FlexInt `json:"guest-num_sta"` // USG
|
||||||
|
NumDesktop FlexInt `json:"num_desktop"` // USG
|
||||||
|
NumMobile FlexInt `json:"num_mobile"` // USG
|
||||||
|
NumHandheld FlexInt `json:"num_handheld"` // USG
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkTable is the list of networks on a gateway.
|
||||||
|
type NetworkTable []struct {
|
||||||
|
ID string `json:"_id"`
|
||||||
|
AttrNoDelete FlexBool `json:"attr_no_delete"`
|
||||||
|
AttrHiddenID string `json:"attr_hidden_id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
VlanEnabled FlexBool `json:"vlan_enabled"`
|
||||||
|
Purpose string `json:"purpose"`
|
||||||
|
IPSubnet string `json:"ip_subnet"`
|
||||||
|
Ipv6InterfaceType string `json:"ipv6_interface_type"`
|
||||||
|
DomainName string `json:"domain_name"`
|
||||||
|
IsNat FlexBool `json:"is_nat"`
|
||||||
|
DhcpdEnabled FlexBool `json:"dhcpd_enabled"`
|
||||||
|
DhcpdStart string `json:"dhcpd_start"`
|
||||||
|
DhcpdStop string `json:"dhcpd_stop"`
|
||||||
|
Dhcpdv6Enabled FlexBool `json:"dhcpdv6_enabled"`
|
||||||
|
Ipv6RaEnabled FlexBool `json:"ipv6_ra_enabled"`
|
||||||
|
LteLanEnabled FlexBool `json:"lte_lan_enabled"`
|
||||||
|
Networkgroup string `json:"networkgroup"`
|
||||||
|
DhcpdLeasetime FlexInt `json:"dhcpd_leasetime"`
|
||||||
|
DhcpdDNSEnabled FlexBool `json:"dhcpd_dns_enabled"`
|
||||||
|
DhcpdGatewayEnabled FlexBool `json:"dhcpd_gateway_enabled"`
|
||||||
|
DhcpdTimeOffsetEnabled FlexBool `json:"dhcpd_time_offset_enabled"`
|
||||||
|
Ipv6PdStart string `json:"ipv6_pd_start"`
|
||||||
|
Ipv6PdStop string `json:"ipv6_pd_stop"`
|
||||||
|
DhcpdDNS1 string `json:"dhcpd_dns_1"`
|
||||||
|
DhcpdDNS2 string `json:"dhcpd_dns_2"`
|
||||||
|
DhcpdDNS3 string `json:"dhcpd_dns_3"`
|
||||||
|
DhcpdDNS4 string `json:"dhcpd_dns_4"`
|
||||||
|
Enabled FlexBool `json:"enabled"`
|
||||||
|
DhcpRelayEnabled FlexBool `json:"dhcp_relay_enabled"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
IsGuest FlexBool `json:"is_guest"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
NumSta FlexInt `json:"num_sta"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDMStat holds the "stat" data for a dream machine.
|
||||||
|
// A dream machine is a USG + USW + Controller
|
||||||
|
type UDMStat struct {
|
||||||
|
*Gw `json:"gw"`
|
||||||
|
*Sw `json:"sw"`
|
||||||
|
*Ap `json:"ap,omitempty"`
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
// Package unifi provides a set of types to unload (unmarshal) Ubiquiti UniFi
|
||||||
|
// controller data. Also provided are methods to easily get data for devices -
|
||||||
|
// things like access points and switches, and for clients - the things
|
||||||
|
// connected to those access points and switches. As a bonus, each device and
|
||||||
|
// client type provided has an attached method to create InfluxDB datapoints.
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewUnifi creates a http.Client with authenticated cookies.
|
||||||
|
// Used to make additional, authenticated requests to the APIs.
|
||||||
|
// Start here.
|
||||||
|
func NewUnifi(config *Config) (*Unifi, error) {
|
||||||
|
jar, err := cookiejar.New(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
config.URL = strings.TrimRight(config.URL, "/")
|
||||||
|
|
||||||
|
if config.ErrorLog == nil {
|
||||||
|
config.ErrorLog = discardLogs
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.DebugLog == nil {
|
||||||
|
config.DebugLog = discardLogs
|
||||||
|
}
|
||||||
|
|
||||||
|
u := &Unifi{Config: config,
|
||||||
|
Client: &http.Client{
|
||||||
|
Jar: jar,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: !config.VerifySSL},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := u.Login(); err != nil {
|
||||||
|
return u, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := u.GetServerData(); err != nil {
|
||||||
|
return u, fmt.Errorf("unable to get server version: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Login is a helper method. It can be called to grab a new authentication cookie.
|
||||||
|
func (u *Unifi) Login() error {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
// magic login.
|
||||||
|
req, err := u.UniReq(APILoginPath, fmt.Sprintf(`{"username":"%s","password":"%s"}`, u.User, u.Pass))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := u.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close() // we need no data here.
|
||||||
|
_, _ = io.Copy(ioutil.Discard, resp.Body) // avoid leaking.
|
||||||
|
u.DebugLog("Requested %s: elapsed %v, returned %d bytes",
|
||||||
|
APILoginPath, time.Since(start).Round(time.Millisecond), resp.ContentLength)
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
return fmt.Errorf("authentication failed (user: %s): %s (status: %s)",
|
||||||
|
u.User, u.URL+APILoginPath, resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetServerData sets the controller's version and UUID. Only call this if you
|
||||||
|
// previously called Login and suspect the controller version has changed.
|
||||||
|
func (u *Unifi) GetServerData() error {
|
||||||
|
var response struct {
|
||||||
|
Data server `json:"meta"`
|
||||||
|
}
|
||||||
|
|
||||||
|
u.server = &response.Data
|
||||||
|
|
||||||
|
return u.GetData(APIStatusPath, &response)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetData makes a unifi request and unmarshals the response into a provided pointer.
|
||||||
|
func (u *Unifi) GetData(apiPath string, v interface{}, params ...string) error {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
body, err := u.GetJSON(apiPath, params...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
u.DebugLog("Requested %s: elapsed %v, returned %d bytes",
|
||||||
|
apiPath, time.Since(start).Round(time.Millisecond), len(body))
|
||||||
|
|
||||||
|
return json.Unmarshal(body, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UniReq is a small helper function that adds an Accept header.
|
||||||
|
// Use this if you're unmarshalling UniFi data into custom types.
|
||||||
|
// And if you're doing that... sumbut a pull request with your new struct. :)
|
||||||
|
// This is a helper method that is exposed for convenience.
|
||||||
|
func (u *Unifi) UniReq(apiPath string, params string) (req *http.Request, err error) {
|
||||||
|
switch params {
|
||||||
|
case "":
|
||||||
|
req, err = http.NewRequest("GET", u.URL+apiPath, nil)
|
||||||
|
default:
|
||||||
|
req, err = http.NewRequest("POST", u.URL+apiPath, bytes.NewBufferString(params))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Add("Accept", "application/json")
|
||||||
|
u.DebugLog("Requesting %s, with params: %v", apiPath, params != "")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetJSON returns the raw JSON from a path. This is useful for debugging.
|
||||||
|
func (u *Unifi) GetJSON(apiPath string, params ...string) ([]byte, error) {
|
||||||
|
req, err := u.UniReq(apiPath, strings.Join(params, " "))
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := u.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return []byte{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return body, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
err = fmt.Errorf("invalid status code from server %s", resp.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return body, err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewUnifi(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a := assert.New(t)
|
||||||
|
u := "http://127.0.0.1:64431"
|
||||||
|
c := &Config{
|
||||||
|
User: "user1",
|
||||||
|
Pass: "pass2",
|
||||||
|
URL: u,
|
||||||
|
VerifySSL: false,
|
||||||
|
DebugLog: discardLogs,
|
||||||
|
}
|
||||||
|
authReq, err := NewUnifi(c)
|
||||||
|
a.NotNil(err)
|
||||||
|
a.EqualValues(u, authReq.URL)
|
||||||
|
a.Contains(err.Error(), "connection refused", "an invalid destination should produce a connection error.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUniReq(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a := assert.New(t)
|
||||||
|
p := "/test/path"
|
||||||
|
u := "http://some.url:8443"
|
||||||
|
// Test empty parameters.
|
||||||
|
authReq := &Unifi{Client: &http.Client{}, Config: &Config{URL: u, DebugLog: discardLogs}}
|
||||||
|
r, err := authReq.UniReq(p, "")
|
||||||
|
a.Nil(err, "newrequest must not produce an error")
|
||||||
|
a.EqualValues(p, r.URL.Path,
|
||||||
|
"the provided apiPath was not added to http request")
|
||||||
|
a.EqualValues(u, r.URL.Scheme+"://"+r.URL.Host, "URL improperly encoded")
|
||||||
|
a.EqualValues("GET", r.Method, "without parameters the method must be GET")
|
||||||
|
a.EqualValues("application/json", r.Header.Get("Accept"), "Accept header must be set to application/json")
|
||||||
|
|
||||||
|
// Test with parameters
|
||||||
|
k := "key1=value9&key2=value7"
|
||||||
|
authReq = &Unifi{Client: &http.Client{}, Config: &Config{URL: "http://some.url:8443", DebugLog: discardLogs}}
|
||||||
|
r, err = authReq.UniReq(p, k)
|
||||||
|
a.Nil(err, "newrequest must not produce an error")
|
||||||
|
a.EqualValues(p, r.URL.Path,
|
||||||
|
"the provided apiPath was not added to http request")
|
||||||
|
a.EqualValues(u, r.URL.Scheme+"://"+r.URL.Host, "URL improperly encoded")
|
||||||
|
a.EqualValues("POST", r.Method, "with parameters the method must be POST")
|
||||||
|
a.EqualValues("application/json", r.Header.Get("Accept"), "Accept header must be set to application/json")
|
||||||
|
// Check the parameters.
|
||||||
|
d, err := ioutil.ReadAll(r.Body)
|
||||||
|
a.Nil(err, "problem reading request body, POST parameters may be malformed")
|
||||||
|
a.EqualValues(k, string(d), "POST parameters improperly encoded")
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOT DONE: OPEN web server, check parameters posted, more. This test is incomplete.
|
||||||
|
a.EqualValues(`{"username": "user1","password": "pass2"}`, string(post_params),
|
||||||
|
"user/pass json parameters improperly encoded")
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// USG represents all the data from the Ubiquiti Controller for a Unifi Security Gateway.
|
||||||
|
type USG struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Adopted FlexBool `json:"adopted"`
|
||||||
|
Cfgversion string `json:"cfgversion"`
|
||||||
|
ConfigNetwork struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
} `json:"config_network"`
|
||||||
|
EthernetTable []struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
NumPort FlexInt `json:"num_port"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"ethernet_table"`
|
||||||
|
FwCaps FlexInt `json:"fw_caps"`
|
||||||
|
InformIP string `json:"inform_ip"`
|
||||||
|
InformURL string `json:"inform_url"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
LedOverride string `json:"led_override"`
|
||||||
|
LicenseState string `json:"license_state"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OutdoorModeOverride string `json:"outdoor_mode_override"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
UsgCaps FlexInt `json:"usg_caps"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
RequiredVersion string `json:"required_version"`
|
||||||
|
EthernetOverrides []struct {
|
||||||
|
Ifname string `json:"ifname"`
|
||||||
|
Networkgroup string `json:"networkgroup"`
|
||||||
|
} `json:"ethernet_overrides"`
|
||||||
|
HwCaps FlexInt `json:"hw_caps"`
|
||||||
|
BoardRev FlexInt `json:"board_rev"`
|
||||||
|
Unsupported FlexBool `json:"unsupported"`
|
||||||
|
UnsupportedReason FlexInt `json:"unsupported_reason"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
State FlexInt `json:"state"`
|
||||||
|
LastSeen FlexInt `json:"last_seen"`
|
||||||
|
Upgradable FlexBool `json:"upgradable"`
|
||||||
|
AdoptableWhenUpgraded FlexBool `json:"adoptable_when_upgraded"`
|
||||||
|
Rollupgrade FlexBool `json:"rollupgrade"`
|
||||||
|
KnownCfgversion string `json:"known_cfgversion"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
Locating FlexBool `json:"locating"`
|
||||||
|
ConnectRequestIP string `json:"connect_request_ip"`
|
||||||
|
ConnectRequestPort string `json:"connect_request_port"`
|
||||||
|
SysStats SysStats `json:"sys_stats"`
|
||||||
|
SystemStats SystemStats `json:"system-stats"`
|
||||||
|
GuestToken string `json:"guest_token"`
|
||||||
|
SpeedtestStatus SpeedtestStatus `json:"speedtest-status"`
|
||||||
|
SpeedtestStatusSaved FlexBool `json:"speedtest-status-saved"`
|
||||||
|
Wan1 Wan `json:"wan1"`
|
||||||
|
Wan2 Wan `json:"wan2"`
|
||||||
|
PortTable []struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Ifname string `json:"ifname"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Netmask string `json:"netmask"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
RxMulticast FlexInt `json:"rx_multicast"`
|
||||||
|
Enable FlexBool `json:"enable"`
|
||||||
|
DNS []string `json:"dns,omitempty"`
|
||||||
|
Gateway string `json:"gateway,omitempty"`
|
||||||
|
} `json:"port_table"`
|
||||||
|
NetworkTable NetworkTable `json:"network_table"`
|
||||||
|
Uplink Uplink `json:"uplink"`
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uplink is the Internet connection (or uplink) on a UniFi device.
|
||||||
|
type Uplink struct {
|
||||||
|
BytesR FlexInt `json:"bytes-r"`
|
||||||
|
Drops FlexInt `json:"drops"`
|
||||||
|
Enable FlexBool `json:"enable,omitempty"`
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
Gateways []string `json:"gateways,omitempty"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Latency FlexInt `json:"latency"`
|
||||||
|
Mac string `json:"mac,omitempty"`
|
||||||
|
MaxSpeed FlexInt `json:"max_speed"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Nameservers []string `json:"nameservers"`
|
||||||
|
Netmask string `json:"netmask"`
|
||||||
|
NumPort FlexInt `json:"num_port"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxBytesR FlexInt `json:"rx_bytes-r"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxMulticast FlexInt `json:"rx_multicast"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
SpeedtestLastrun FlexInt `json:"speedtest_lastrun,omitempty"`
|
||||||
|
SpeedtestPing FlexInt `json:"speedtest_ping,omitempty"`
|
||||||
|
SpeedtestStatus string `json:"speedtest_status,omitempty"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxBytesR FlexInt `json:"tx_bytes-r"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
XputDown FlexInt `json:"xput_down,omitempty"`
|
||||||
|
XputUp FlexInt `json:"xput_up,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wan is a Wan interface on a USG or UDM.
|
||||||
|
type Wan struct {
|
||||||
|
Autoneg FlexBool `json:"autoneg"`
|
||||||
|
BytesR FlexInt `json:"bytes-r"`
|
||||||
|
DNS []string `json:"dns"`
|
||||||
|
Enable FlexBool `json:"enable"`
|
||||||
|
FlowctrlRx FlexBool `json:"flowctrl_rx"`
|
||||||
|
FlowctrlTx FlexBool `json:"flowctrl_tx"`
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
Gateway string `json:"gateway"` // may be deprecated
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Ifname string `json:"ifname"`
|
||||||
|
IsUplink FlexBool `json:"is_uplink"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
MaxSpeed FlexInt `json:"max_speed"`
|
||||||
|
Media string `json:"media"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Netmask string `json:"netmask"` // may be deprecated
|
||||||
|
NumPort int `json:"num_port"`
|
||||||
|
PortIdx int `json:"port_idx"`
|
||||||
|
PortPoe FlexBool `json:"port_poe"`
|
||||||
|
RxBroadcast FlexInt `json:"rx_broadcast"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxBytesR FlexInt `json:"rx_bytes-r"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxMulticast FlexInt `json:"rx_multicast"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
TxBroadcast FlexInt `json:"tx_broadcast"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxBytesR FlexInt `json:"tx_bytes-r"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxMulticast FlexInt `json:"tx_multicast"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SpeedtestStatus is the speed test info on a USG or UDM.
|
||||||
|
type SpeedtestStatus struct {
|
||||||
|
Latency FlexInt `json:"latency"`
|
||||||
|
Rundate FlexInt `json:"rundate"`
|
||||||
|
Runtime FlexInt `json:"runtime"`
|
||||||
|
ServerDesc string `json:"server_desc,omitempty"`
|
||||||
|
StatusDownload FlexInt `json:"status_download"`
|
||||||
|
StatusPing FlexInt `json:"status_ping"`
|
||||||
|
StatusSummary FlexInt `json:"status_summary"`
|
||||||
|
StatusUpload FlexInt `json:"status_upload"`
|
||||||
|
XputDownload FlexInt `json:"xput_download"`
|
||||||
|
XputUpload FlexInt `json:"xput_upload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SystemStats is system info for a UDM, USG, USW.
|
||||||
|
type SystemStats struct {
|
||||||
|
CPU FlexInt `json:"cpu"`
|
||||||
|
Mem FlexInt `json:"mem"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SysStats is load info for a UDM, USG, USW.
|
||||||
|
type SysStats struct {
|
||||||
|
Loadavg1 FlexInt `json:"loadavg_1"`
|
||||||
|
Loadavg15 FlexInt `json:"loadavg_15"`
|
||||||
|
Loadavg5 FlexInt `json:"loadavg_5"`
|
||||||
|
MemBuffer FlexInt `json:"mem_buffer"`
|
||||||
|
MemTotal FlexInt `json:"mem_total"`
|
||||||
|
MemUsed FlexInt `json:"mem_used"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gw is a subtype of USGStat to make unmarshalling of different controller versions possible.
|
||||||
|
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"`
|
||||||
|
WanRxDropped FlexInt `json:"wan-rx_dropped"`
|
||||||
|
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"`
|
||||||
|
LanRxDropped FlexInt `json:"lan-rx_dropped"`
|
||||||
|
WanRxErrors FlexInt `json:"wan-rx_errors,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
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{}
|
||||||
|
lanRx := 37599596992669
|
||||||
|
err := u.UnmarshalJSON([]byte(testcontroller510))
|
||||||
|
a.Nil(err, "must be no error unmarshaling test strings")
|
||||||
|
a.Equal(float64(lanRx), 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(lanRx), u.LanRxBytes.Val, "data was not properly unmarshaled")
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,377 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// USW represents all the data from the Ubiquiti Controller for a Unifi Switch.
|
||||||
|
type USW struct {
|
||||||
|
SourceName string `json:"-"`
|
||||||
|
SiteName string `json:"-"`
|
||||||
|
ID string `json:"_id"`
|
||||||
|
Adopted FlexBool `json:"adopted"`
|
||||||
|
BoardRev FlexInt `json:"board_rev"`
|
||||||
|
Cfgversion string `json:"cfgversion"`
|
||||||
|
ConfigNetwork struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
} `json:"config_network"`
|
||||||
|
Dot1XPortctrlEnabled FlexBool `json:"dot1x_portctrl_enabled"`
|
||||||
|
EthernetTable []struct {
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
NumPort FlexInt `json:"num_port,omitempty"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
} `json:"ethernet_table"`
|
||||||
|
FlowctrlEnabled FlexBool `json:"flowctrl_enabled"`
|
||||||
|
FwCaps FlexInt `json:"fw_caps"`
|
||||||
|
HasFan FlexBool `json:"has_fan"`
|
||||||
|
HasTemperature FlexBool `json:"has_temperature"`
|
||||||
|
InformIP string `json:"inform_ip"`
|
||||||
|
InformURL string `json:"inform_url"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
JumboframeEnabled FlexBool `json:"jumboframe_enabled"`
|
||||||
|
LedOverride string `json:"led_override"`
|
||||||
|
LicenseState string `json:"license_state"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
OutdoorModeOverride string `json:"outdoor_mode_override"`
|
||||||
|
PortOverrides []struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
PoeMode string `json:"poe_mode,omitempty"`
|
||||||
|
PortIdx FlexInt `json:"port_idx"`
|
||||||
|
PortconfID string `json:"portconf_id"`
|
||||||
|
} `json:"port_overrides"`
|
||||||
|
PortTable []Port `json:"port_table"`
|
||||||
|
Serial string `json:"serial"`
|
||||||
|
SiteID string `json:"site_id"`
|
||||||
|
StpPriority FlexInt `json:"stp_priority"`
|
||||||
|
StpVersion string `json:"stp_version"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
RequiredVersion string `json:"required_version"`
|
||||||
|
SwitchCaps struct {
|
||||||
|
FeatureCaps FlexInt `json:"feature_caps"`
|
||||||
|
MaxMirrorSessions FlexInt `json:"max_mirror_sessions"`
|
||||||
|
MaxAggregateSessions FlexInt `json:"max_aggregate_sessions"`
|
||||||
|
} `json:"switch_caps"`
|
||||||
|
HwCaps FlexInt `json:"hw_caps"`
|
||||||
|
Unsupported FlexBool `json:"unsupported"`
|
||||||
|
UnsupportedReason FlexInt `json:"unsupported_reason"`
|
||||||
|
SysErrorCaps FlexInt `json:"sys_error_caps"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
State FlexInt `json:"state"`
|
||||||
|
LastSeen FlexInt `json:"last_seen"`
|
||||||
|
Upgradable FlexBool `json:"upgradable,omitempty"`
|
||||||
|
AdoptableWhenUpgraded FlexBool `json:"adoptable_when_upgraded,omitempty"`
|
||||||
|
Rollupgrade FlexBool `json:"rollupgrade,omitempty"`
|
||||||
|
KnownCfgversion string `json:"known_cfgversion"`
|
||||||
|
Uptime FlexInt `json:"uptime"`
|
||||||
|
Locating FlexBool `json:"locating"`
|
||||||
|
ConnectRequestIP string `json:"connect_request_ip"`
|
||||||
|
ConnectRequestPort string `json:"connect_request_port"`
|
||||||
|
SysStats SysStats `json:"sys_stats"`
|
||||||
|
SystemStats SystemStats `json:"system-stats"`
|
||||||
|
FanLevel FlexInt `json:"fan_level"`
|
||||||
|
GeneralTemperature FlexInt `json:"general_temperature"`
|
||||||
|
Overheating FlexBool `json:"overheating"`
|
||||||
|
TotalMaxPower FlexInt `json:"total_max_power"`
|
||||||
|
DownlinkTable []struct {
|
||||||
|
PortIdx FlexInt `json:"port_idx"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
Mac string `json:"mac"`
|
||||||
|
} `json:"downlink_table"`
|
||||||
|
Uplink Uplink `json:"uplink"`
|
||||||
|
LastUplink struct {
|
||||||
|
UplinkMac string `json:"uplink_mac"`
|
||||||
|
} `json:"last_uplink"`
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Port is a physical connection on a USW or UDM.
|
||||||
|
type Port struct {
|
||||||
|
AggregatedBy FlexBool `json:"aggregated_by"`
|
||||||
|
Autoneg FlexBool `json:"autoneg,omitempty"`
|
||||||
|
BytesR FlexInt `json:"bytes-r"`
|
||||||
|
DNS []string `json:"dns,omitempty"`
|
||||||
|
Dot1XMode string `json:"dot1x_mode"`
|
||||||
|
Dot1XStatus string `json:"dot1x_status"`
|
||||||
|
Enable FlexBool `json:"enable"`
|
||||||
|
FlowctrlRx FlexBool `json:"flowctrl_rx"`
|
||||||
|
FlowctrlTx FlexBool `json:"flowctrl_tx"`
|
||||||
|
FullDuplex FlexBool `json:"full_duplex"`
|
||||||
|
IP string `json:"ip,omitempty"`
|
||||||
|
Ifname string `json:"ifname,omitempty"`
|
||||||
|
IsUplink FlexBool `json:"is_uplink"`
|
||||||
|
Mac string `json:"mac,omitempty"`
|
||||||
|
Jumbo FlexBool `json:"jumbo,omitempty"`
|
||||||
|
Masked FlexBool `json:"masked"`
|
||||||
|
Media string `json:"media"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
NetworkName string `json:"network_name,omitempty"`
|
||||||
|
NumPort int `json:"num_port,omitempty"`
|
||||||
|
OpMode string `json:"op_mode"`
|
||||||
|
PoeCaps FlexInt `json:"poe_caps"`
|
||||||
|
PoeClass string `json:"poe_class,omitempty"`
|
||||||
|
PoeCurrent FlexInt `json:"poe_current,omitempty"`
|
||||||
|
PoeEnable FlexBool `json:"poe_enable,omitempty"`
|
||||||
|
PoeGood FlexBool `json:"poe_good,omitempty"`
|
||||||
|
PoeMode string `json:"poe_mode,omitempty"`
|
||||||
|
PoePower FlexInt `json:"poe_power,omitempty"`
|
||||||
|
PoeVoltage FlexInt `json:"poe_voltage,omitempty"`
|
||||||
|
PortDelta struct {
|
||||||
|
TimeDelta int64 `json:"time_delta"`
|
||||||
|
} `json:"port_delta,omitempty"`
|
||||||
|
PortIdx FlexInt `json:"port_idx"`
|
||||||
|
PortPoe FlexBool `json:"port_poe"`
|
||||||
|
PortconfID string `json:"portconf_id"`
|
||||||
|
RxBroadcast FlexInt `json:"rx_broadcast"`
|
||||||
|
RxBytes FlexInt `json:"rx_bytes"`
|
||||||
|
RxBytesR FlexInt `json:"rx_bytes-r"`
|
||||||
|
RxDropped FlexInt `json:"rx_dropped"`
|
||||||
|
RxErrors FlexInt `json:"rx_errors"`
|
||||||
|
RxMulticast FlexInt `json:"rx_multicast"`
|
||||||
|
RxPackets FlexInt `json:"rx_packets"`
|
||||||
|
Satisfaction FlexInt `json:"satisfaction,omitempty"`
|
||||||
|
SfpFound FlexBool `json:"sfp_found,omitempty"`
|
||||||
|
Speed FlexInt `json:"speed"`
|
||||||
|
SpeedCaps FlexInt `json:"speed_caps"`
|
||||||
|
StpPathcost FlexInt `json:"stp_pathcost"`
|
||||||
|
StpState string `json:"stp_state"`
|
||||||
|
TxBroadcast FlexInt `json:"tx_broadcast"`
|
||||||
|
TxBytes FlexInt `json:"tx_bytes"`
|
||||||
|
TxBytesR FlexInt `json:"tx_bytes-r"`
|
||||||
|
TxDropped FlexInt `json:"tx_dropped"`
|
||||||
|
TxErrors FlexInt `json:"tx_errors"`
|
||||||
|
TxMulticast FlexInt `json:"tx_multicast"`
|
||||||
|
TxPackets FlexInt `json:"tx_packets"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Up FlexBool `json:"up"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sw is a subtype of USWStat to make unmarshalling of different controller versions possible.
|
||||||
|
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"`
|
||||||
|
/* These are all in port table */
|
||||||
|
/*
|
||||||
|
Port1RxPackets FlexInt `json:"port_1-rx_packets,omitempty"`
|
||||||
|
Port1RxBytes FlexInt `json:"port_1-rx_bytes,omitempty"`
|
||||||
|
Port1TxPackets FlexInt `json:"port_1-tx_packets,omitempty"`
|
||||||
|
Port1TxBytes FlexInt `json:"port_1-tx_bytes,omitempty"`
|
||||||
|
Port1TxMulticast FlexInt `json:"port_1-tx_multicast"`
|
||||||
|
Port1TxBroadcast FlexInt `json:"port_1-tx_broadcast"`
|
||||||
|
Port3RxPackets FlexInt `json:"port_3-rx_packets,omitempty"`
|
||||||
|
Port3RxBytes FlexInt `json:"port_3-rx_bytes,omitempty"`
|
||||||
|
Port3TxPackets FlexInt `json:"port_3-tx_packets,omitempty"`
|
||||||
|
Port3TxBytes FlexInt `json:"port_3-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port6RxBytes FlexInt `json:"port_6-rx_bytes,omitempty"`
|
||||||
|
Port6TxPackets FlexInt `json:"port_6-tx_packets,omitempty"`
|
||||||
|
Port6TxBytes FlexInt `json:"port_6-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port7RxBytes FlexInt `json:"port_7-rx_bytes,omitempty"`
|
||||||
|
Port7TxPackets FlexInt `json:"port_7-tx_packets,omitempty"`
|
||||||
|
Port7TxBytes FlexInt `json:"port_7-tx_bytes,omitempty"`
|
||||||
|
Port7TxMulticast FlexInt `json:"port_7-tx_multicast"`
|
||||||
|
Port7TxBroadcast FlexInt `json:"port_7-tx_broadcast"`
|
||||||
|
Port9RxPackets FlexInt `json:"port_9-rx_packets,omitempty"`
|
||||||
|
Port9RxBytes FlexInt `json:"port_9-rx_bytes,omitempty"`
|
||||||
|
Port9TxPackets FlexInt `json:"port_9-tx_packets,omitempty"`
|
||||||
|
Port9TxBytes FlexInt `json:"port_9-tx_bytes,omitempty"`
|
||||||
|
Port9TxMulticast FlexInt `json:"port_9-tx_multicast"`
|
||||||
|
Port9TxBroadcast FlexInt `json:"port_9-tx_broadcast"`
|
||||||
|
Port10RxPackets FlexInt `json:"port_10-rx_packets,omitempty"`
|
||||||
|
Port10RxBytes FlexInt `json:"port_10-rx_bytes,omitempty"`
|
||||||
|
Port10TxPackets FlexInt `json:"port_10-tx_packets,omitempty"`
|
||||||
|
Port10TxBytes FlexInt `json:"port_10-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port11RxBytes FlexInt `json:"port_11-rx_bytes,omitempty"`
|
||||||
|
Port11TxPackets FlexInt `json:"port_11-tx_packets,omitempty"`
|
||||||
|
Port11TxBytes FlexInt `json:"port_11-tx_bytes,omitempty"`
|
||||||
|
Port11TxMulticast FlexInt `json:"port_11-tx_multicast"`
|
||||||
|
Port11TxBroadcast FlexInt `json:"port_11-tx_broadcast"`
|
||||||
|
Port12RxPackets FlexInt `json:"port_12-rx_packets,omitempty"`
|
||||||
|
Port12RxBytes FlexInt `json:"port_12-rx_bytes,omitempty"`
|
||||||
|
Port12TxPackets FlexInt `json:"port_12-tx_packets,omitempty"`
|
||||||
|
Port12TxBytes FlexInt `json:"port_12-tx_bytes,omitempty"`
|
||||||
|
Port12TxMulticast FlexInt `json:"port_12-tx_multicast"`
|
||||||
|
Port12TxBroadcast FlexInt `json:"port_12-tx_broadcast"`
|
||||||
|
Port13RxPackets FlexInt `json:"port_13-rx_packets,omitempty"`
|
||||||
|
Port13RxBytes FlexInt `json:"port_13-rx_bytes,omitempty"`
|
||||||
|
Port13TxPackets FlexInt `json:"port_13-tx_packets,omitempty"`
|
||||||
|
Port13TxBytes FlexInt `json:"port_13-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port15RxBytes FlexInt `json:"port_15-rx_bytes,omitempty"`
|
||||||
|
Port15TxPackets FlexInt `json:"port_15-tx_packets,omitempty"`
|
||||||
|
Port15TxBytes FlexInt `json:"port_15-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port16RxBytes FlexInt `json:"port_16-rx_bytes,omitempty"`
|
||||||
|
Port16TxPackets FlexInt `json:"port_16-tx_packets,omitempty"`
|
||||||
|
Port16TxBytes FlexInt `json:"port_16-tx_bytes,omitempty"`
|
||||||
|
Port16TxMulticast FlexInt `json:"port_16-tx_multicast"`
|
||||||
|
Port16TxBroadcast FlexInt `json:"port_16-tx_broadcast"`
|
||||||
|
Port17RxPackets FlexInt `json:"port_17-rx_packets,omitempty"`
|
||||||
|
Port17RxBytes FlexInt `json:"port_17-rx_bytes,omitempty"`
|
||||||
|
Port17TxPackets FlexInt `json:"port_17-tx_packets,omitempty"`
|
||||||
|
Port17TxBytes FlexInt `json:"port_17-tx_bytes,omitempty"`
|
||||||
|
Port17TxMulticast FlexInt `json:"port_17-tx_multicast"`
|
||||||
|
Port17TxBroadcast FlexInt `json:"port_17-tx_broadcast"`
|
||||||
|
Port18RxPackets FlexInt `json:"port_18-rx_packets,omitempty"`
|
||||||
|
Port18RxBytes FlexInt `json:"port_18-rx_bytes,omitempty"`
|
||||||
|
Port18TxPackets FlexInt `json:"port_18-tx_packets,omitempty"`
|
||||||
|
Port18TxBytes FlexInt `json:"port_18-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port19RxBytes FlexInt `json:"port_19-rx_bytes,omitempty"`
|
||||||
|
Port19TxPackets FlexInt `json:"port_19-tx_packets,omitempty"`
|
||||||
|
Port19TxBytes FlexInt `json:"port_19-tx_bytes,omitempty"`
|
||||||
|
Port19TxMulticast FlexInt `json:"port_19-tx_multicast"`
|
||||||
|
Port19TxBroadcast FlexInt `json:"port_19-tx_broadcast"`
|
||||||
|
Port21RxPackets FlexInt `json:"port_21-rx_packets,omitempty"`
|
||||||
|
Port21RxBytes FlexInt `json:"port_21-rx_bytes,omitempty"`
|
||||||
|
Port21TxPackets FlexInt `json:"port_21-tx_packets,omitempty"`
|
||||||
|
Port21TxBytes FlexInt `json:"port_21-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port22RxBytes FlexInt `json:"port_22-rx_bytes,omitempty"`
|
||||||
|
Port22TxPackets FlexInt `json:"port_22-tx_packets,omitempty"`
|
||||||
|
Port22TxBytes FlexInt `json:"port_22-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port23RxBytes FlexInt `json:"port_23-rx_bytes,omitempty"`
|
||||||
|
Port23RxDropped FlexInt `json:"port_23-rx_dropped"`
|
||||||
|
Port23TxPackets FlexInt `json:"port_23-tx_packets,omitempty"`
|
||||||
|
Port23TxBytes FlexInt `json:"port_23-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port24RxBytes FlexInt `json:"port_24-rx_bytes,omitempty"`
|
||||||
|
Port24TxPackets FlexInt `json:"port_24-tx_packets,omitempty"`
|
||||||
|
Port24TxBytes FlexInt `json:"port_24-tx_bytes,omitempty"`
|
||||||
|
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,omitempty"`
|
||||||
|
Port4RxBytes FlexInt `json:"port_4-rx_bytes,omitempty"`
|
||||||
|
Port4RxDropped FlexInt `json:"port_4-rx_dropped"`
|
||||||
|
Port4TxPackets FlexInt `json:"port_4-tx_packets,omitempty"`
|
||||||
|
Port4TxBytes FlexInt `json:"port_4-tx_bytes,omitempty"`
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package unifi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testGetControllerJSON() (string, string) {
|
||||||
|
return `{
|
||||||
|
"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}}`,
|
||||||
|
`{
|
||||||
|
"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}`
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUSWUnmarshalJSON(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
a := assert.New(t)
|
||||||
|
testcontroller511, testcontroller510 := testGetControllerJSON()
|
||||||
|
rxMulticast := 123
|
||||||
|
u := &USWStat{}
|
||||||
|
err := u.UnmarshalJSON([]byte(testcontroller510))
|
||||||
|
a.Nil(err, "must be no error unmarshaling test strings")
|
||||||
|
a.Equal(float64(rxMulticast), 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(rxMulticast), u.RxMulticast.Val, "data was not properly unmarshaled")
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue