Remove the library. Source it externally.

This commit is contained in:
David Newhall II 2019-01-24 00:11:04 -08:00
parent 0643bec6e5
commit f50af43c62
18 changed files with 35 additions and 2207 deletions

29
core/poller/Gopkg.lock generated
View File

@ -2,10 +2,10 @@
[[projects]]
name = "github.com/davecgh/go-spew"
packages = ["spew"]
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
branch = "master"
name = "github.com/golift/unifi"
packages = ["."]
revision = "24c7eb106b3c9ff4260c88b54c02f0f86301fa75"
[[projects]]
name = "github.com/influxdata/influxdb"
@ -14,17 +14,16 @@
"models",
"pkg/escape"
]
revision = "76f907b0fada2f16931e37471da695349fcdf8c6"
version = "v1.7.2"
revision = "698dbc789aff13c2678357a6b93ff73dd7136571"
version = "v1.7.3"
[[projects]]
branch = "master"
name = "github.com/influxdata/platform"
packages = [
"models",
"pkg/escape"
]
revision = "98469bf07613ffae6f025893761c1e7a5e96e4aa"
revision = "0f79e4ea3248354c789cba274542e0a8e55971db"
[[projects]]
name = "github.com/naoina/go-stringutil"
@ -53,21 +52,9 @@
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert"]
revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053"
version = "v1.3.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "3b1d8ae8346fc10f0725163478eab3fa466a2064f4d44077102c5f7651625dc4"
inputs-digest = "5fa0fad44ae6516c3c699a60210634ddcc7d36e6b8a10bae25d0efcc001bb768"
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -25,9 +25,13 @@
# unused-packages = true
[[constraint]]
branch = "master"
name = "github.com/golift/unifi"
[[constraint]]
name = "github.com/influxdata/influxdb"
version = "1.7.2"
version = "1.7.3"
[[constraint]]
name = "github.com/naoina/toml"
@ -37,14 +41,6 @@
name = "github.com/ogier/pflag"
version = "0.0.1"
[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.1"
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.3.0"
[prune]
go-tests = true
unused-packages = true

View File

@ -12,7 +12,7 @@ build:
linux:
for p in $(PACKAGES); do GOOS=linux go build -ldflags "-w -s" $${p}; done
install: man
install: man test build
@echo "If you get errors, you may need sudo."
GOBIN=/usr/local/bin go install -ldflags "-w -s" ./...
mkdir -p /usr/local/etc/unifi-poller /usr/local/share/man/man1

View File

@ -90,13 +90,6 @@ select multiple to put specific stats side-by-side.
![image](images/unifi-uap-dashboard.png?raw=true)
# Woah, there's a library in here.
Sure is. If you want to write your own code around unifi data, you can import
the `unidev` library and easily poll your controller. If you have interest in
how to use the library, or need more features, open an Issue. I'm not committed
to documenting it unless it seems useful.
## Copyright & License
- Copyright © 2016 Garrett Bjerkhoel.

View File

@ -7,19 +7,19 @@ import (
"os"
"time"
"github.com/davidnewhall/unifi-poller/unidev"
influx "github.com/influxdata/influxdb/client/v2"
"github.com/golift/unifi"
"github.com/influxdata/influxdb/client/v2"
"github.com/naoina/toml"
flg "github.com/ogier/pflag"
flag "github.com/ogier/pflag"
)
func main() {
configFile := parseFlags()
log.Println("Unifi-Poller Starting Up! PID:", os.Getpid())
config, err := GetConfig(configFile)
if err != nil {
flg.Usage()
flag.Usage()
log.Fatalf("Config Error '%v': %v", configFile, err)
} else if log.SetFlags(0); config.Debug {
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
@ -27,13 +27,13 @@ func main() {
}
log.Println("Loaded Configuration:", configFile)
// Create an authenticated session to the Unifi Controller.
unifi, err := unidev.AuthController(config.UnifiUser, config.UnifiPass, config.UnifiBase, config.VerifySSL)
device, err := unifi.AuthController(config.UnifiUser, config.UnifiPass, config.UnifiBase, config.VerifySSL)
if err != nil {
log.Fatalln("Unifi Controller Error:", err)
} else if !config.Quiet {
log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser)
}
infdb, err := influx.NewHTTPClient(influx.HTTPConfig{
infdb, err := client.NewHTTPClient(client.HTTPConfig{
Addr: config.InfluxURL,
Username: config.InfluxUser,
Password: config.InfluxPass,
@ -42,23 +42,23 @@ func main() {
log.Fatalln("InfluxDB Error:", err)
} else if config.Quiet {
// Doing it this way allows debug error logs (line numbers, etc)
unidev.Debug = false
unifi.Debug = false
} else {
log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser)
log.Println("Polling Unifi Controller, interval:", config.Interval.value)
}
log.Println("Everyting checks out! Beginning Poller Routine.")
config.PollUnifiController(infdb, unifi, config.Quiet)
config.PollUnifiController(infdb, device, config.Quiet)
}
func parseFlags() string {
flg.Usage = func() {
flag.Usage = func() {
fmt.Println("Usage: unifi-poller [--config=filepath] [--version]")
flg.PrintDefaults()
flag.PrintDefaults()
}
configFile := flg.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)")
version := flg.BoolP("version", "v", false, "Print the version and exit")
if flg.Parse(); *version {
configFile := flag.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)")
version := flag.BoolP("version", "v", false, "Print the version and exit")
if flag.Parse(); *version {
fmt.Println("unifi-poller version:", Version)
os.Exit(0) // don't run anything else.
}
@ -91,17 +91,17 @@ func GetConfig(configFile string) (Config, error) {
}
// PollUnifiController runs forever, polling and pushing.
func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedReq, quiet bool) {
func (c *Config) PollUnifiController(infdb client.Client, device *unifi.AuthedReq, quiet bool) {
ticker := time.NewTicker(c.Interval.value)
for range ticker.C {
var clients, devices []unidev.Asset
var bp influx.BatchPoints
var clients, devices []unifi.Asset
var bp client.BatchPoints
var err error
if clients, err = unifi.GetUnifiClientAssets(); err != nil {
if clients, err = device.GetUnifiClientAssets(); err != nil {
log.Println("ERROR unifi.GetUnifiClientsAssets():", err)
} else if devices, err = unifi.GetUnifiDeviceAssets(); err != nil {
} else if devices, err = device.GetUnifiDeviceAssets(); err != nil {
log.Println("ERROR unifi.GetUnifiDeviceAssets():", err)
} else if bp, err = influx.NewBatchPoints(influx.BatchPointsConfig{Database: c.InfluxDB}); err != nil {
} else if bp, err = client.NewBatchPoints(client.BatchPointsConfig{Database: c.InfluxDB}); err != nil {
log.Println("ERROR influx.NewBatchPoints:", err)
}
if err != nil {

View File

@ -8,5 +8,6 @@ for f in cmd/*/README.md;do
PKGNOCMD="${f#cmd/}"
PKG="${PKGNOCMD%/README.md}"
echo "Creating Man Page: ${f} -> ${OUTPUT}${PKG}.1.gz"
echo "If this produces an error. Install ronn; something like: sudo gem install ronn"
ronn < "$f" | gzip -9 > "${OUTPUT}${PKG}.1.gz"
done

View File

@ -1,10 +0,0 @@
# Go Library: `unidev`
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 included asset interface currently only works for InfluxDB but could
probably be modified to support other output mechanisms; not sure really.
This lib is rudimentary and gets a job done for the tool at hand. It could be
used to base your own library. Good luck!

View File

@ -1,104 +0,0 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Points generates a client's datapoints for InfluxDB.
func (u UCL) Points() ([]*influx.Point, error) {
var points []*influx.Point
if u.Name == "" && u.Hostname != "" {
u.Name = u.Hostname
} else if u.Hostname == "" && u.Name != "" {
u.Hostname = u.Name
} else if u.Hostname == "" && u.Name == "" {
u.Hostname = "-no-name-"
u.Name = "-no-name-"
}
tags := map[string]string{
"id": u.ID,
"mac": u.Mac,
"user_id": u.UserID,
"site_id": u.SiteID,
"network_id": u.NetworkID,
"usergroup_id": u.UserGroupID,
"ap_mac": u.ApMac,
"gw_mac": u.GwMac,
"sw_mac": u.SwMac,
"oui": u.Oui,
"radio_name": u.RadioName,
"radio": u.Radio,
"radio_proto": u.RadioProto,
"name": u.Name,
"fixed_ip": u.FixedIP,
"sw_port": strconv.Itoa(u.SwPort),
"os_class": strconv.Itoa(u.OsClass),
"os_name": strconv.Itoa(u.OsName),
"dev_cat": strconv.Itoa(u.DevCat),
"dev_id": strconv.Itoa(u.DevID),
"dev_family": strconv.Itoa(u.DevFamily),
"authorized": strconv.FormatBool(u.Authorized),
"is_11r": strconv.FormatBool(u.Is11R),
"is_wired": strconv.FormatBool(u.IsWired),
"is_guest": strconv.FormatBool(u.IsGuest),
"is_guest_by_uap": strconv.FormatBool(u.IsGuestByUAP),
"is_guest_by_ugw": strconv.FormatBool(u.IsGuestByUGW),
"is_guest_by_usw": strconv.FormatBool(u.IsGuestByUSW),
"noted": strconv.FormatBool(u.Noted),
"powersave_enabled": strconv.FormatBool(u.PowersaveEnabled),
"qos_policy_applied": strconv.FormatBool(u.QosPolicyApplied),
"use_fixedip": strconv.FormatBool(u.UseFixedIP),
"channel": strconv.Itoa(u.Channel),
"vlan": strconv.Itoa(u.Vlan),
}
fields := map[string]interface{}{
"ip": u.IP,
"essid": u.Essid,
"bssid": u.Bssid,
"hostname": u.Hostname,
"dpi_stats_last_updated": u.DpiStatsLastUpdated,
"last_seen_by_uap": u.LastSeenByUAP,
"last_seen_by_ugw": u.LastSeenByUGW,
"last_seen_by_usw": u.LastSeenByUSW,
"uptime_by_uap": u.UptimeByUAP,
"uptime_by_ugw": u.UptimeByUGW,
"uptime_by_usw": u.UptimeByUSW,
"assoc_time": u.AssocTime,
"bytes_r": u.BytesR,
"ccq": u.Ccq,
"first_seen": u.FirstSeen,
"idle_time": u.IdleTime,
"last_seen": u.LastSeen,
"latest_assoc_time": u.LatestAssocTime,
"network": u.Network,
"noise": u.Noise,
"note": u.Note,
"roam_count": u.RoamCount,
"rssi": u.Rssi,
"rx_bytes": u.RxBytes,
"rx_bytes_r": u.RxBytesR,
"rx_packets": u.RxPackets,
"rx_rate": u.RxRate,
"signal": u.Signal,
"tx_bytes": u.TxBytes,
"tx_bytes_r": u.TxBytesR,
"tx_packets": u.TxPackets,
"tx_power": u.TxPower,
"tx_rate": u.TxRate,
"uptime": u.Uptime,
"wired-rx_bytes": u.WiredRxBytes,
"wired-rx_bytes-r": u.WiredRxBytesR,
"wired-rx_packets": u.WiredRxPackets,
"wired-tx_bytes": u.WiredTxBytes,
"wired-tx_bytes-r": u.WiredTxBytesR,
"wired-tx_packets": u.WiredTxPackets,
}
pt, err := influx.NewPoint("clients", tags, fields, time.Now())
if err == nil {
points = append(points, pt)
}
return points, err
}

View File

@ -1,88 +0,0 @@
package unidev
// UCL defines all the data a connected-network client contains.
type UCL struct {
ID string `json:"_id"`
IsGuestByUAP bool `json:"_is_guest_by_uap"`
IsGuestByUGW bool `json:"_is_guest_by_ugw"`
IsGuestByUSW bool `json:"_is_guest_by_usw"`
LastSeenByUAP int64 `json:"_last_seen_by_uap"`
LastSeenByUGW int64 `json:"_last_seen_by_ugw"`
LastSeenByUSW int64 `json:"_last_seen_by_usw"`
UptimeByUAP int64 `json:"_uptime_by_uap"`
UptimeByUGW int64 `json:"_uptime_by_ugw"`
UptimeByUSW int64 `json:"_uptime_by_usw"`
ApMac string `json:"ap_mac"`
AssocTime int64 `json:"assoc_time"`
Authorized bool `json:"authorized"`
Bssid string `json:"bssid"`
BytesR int64 `json:"bytes-r"`
Ccq int64 `json:"ccq"`
Channel int `json:"channel"`
DevCat int `json:"dev_cat"`
DevFamily int `json:"dev_family"`
DevID int `json:"dev_id"`
DpiStats struct {
App int64
Cat int64
RxBytes int64
RxPackets int64
TxBytes int64
TxPackets int64
} `json:"dpi_stats"`
DpiStatsLastUpdated int64 `json:"dpi_stats_last_updated"`
Essid string `json:"essid"`
FirstSeen int64 `json:"first_seen"`
FixedIP string `json:"fixed_ip"`
Hostname string `json:"hostname"`
GwMac string `json:"gw_mac"`
IdleTime int64 `json:"idle_time"`
IP string `json:"ip"`
Is11R bool `json:"is_11r"`
IsGuest bool `json:"is_guest"`
IsWired bool `json:"is_wired"`
LastSeen int64 `json:"last_seen"`
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 bool `json:"noted"`
OsClass int `json:"os_class"`
OsName int `json:"os_name"`
Oui string `json:"oui"`
PowersaveEnabled bool `json:"powersave_enabled"`
QosPolicyApplied bool `json:"qos_policy_applied"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
RadioProto string `json:"radio_proto"`
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"`
SwDepth int `json:"sw_depth"`
SwMac string `json:"sw_mac"`
SwPort int `json:"sw_port"`
TxBytes int64 `json:"tx_bytes"`
TxBytesR int64 `json:"tx_bytes-r"`
TxPackets int64 `json:"tx_packets"`
TxPower int64 `json:"tx_power"`
TxRate int64 `json:"tx_rate"`
Uptime int64 `json:"uptime"`
UserID string `json:"user_id"`
UserGroupID string `json:"usergroup_id"`
UseFixedIP bool `json:"use_fixedip"`
Vlan int `json:"vlan"`
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"`
}

View File

@ -1,266 +0,0 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Points generates a device's datapoints for InfluxDB.
func (u UAP) Points() ([]*influx.Point, error) {
/* I generally suck at InfluxDB, so if I got the tags/fields wrong,
please send me a PR or open an Issue to address my faults. Thanks!
*/
var points []*influx.Point
tags := map[string]string{
"id": u.ID,
"mac": u.Mac,
"device_type": u.Stat.O,
"device_oid": u.Stat.Oid,
"device_ap": u.Stat.Ap,
"site_id": u.SiteID,
"name": u.Name,
"addopted": strconv.FormatBool(u.Adopted),
"bandsteering_mode": u.BandsteeringMode,
"board_rev": strconv.Itoa(u.BoardRev),
"cfgversion": u.Cfgversion,
"config_network_ip": u.ConfigNetwork.IP,
"config_network_type": u.ConfigNetwork.Type,
"connect_request_ip": u.ConnectRequestIP,
"connect_request_port": u.ConnectRequestPort,
"default": strconv.FormatBool(u.Default),
"device_id": u.DeviceID,
"discovered_via": u.DiscoveredVia,
"fw_caps": strconv.Itoa(u.FwCaps),
"guest-num_sta": strconv.Itoa(u.GuestNumSta),
"guest_token": u.GuestToken,
"has_eth1": strconv.FormatBool(u.HasEth1),
"has_speaker": strconv.FormatBool(u.HasSpeaker),
"inform_ip": u.InformIP,
"isolated": strconv.FormatBool(u.Isolated),
"last_uplink_mac": u.LastUplink.UplinkMac,
"last_uplink_remote_port": strconv.Itoa(u.LastUplink.UplinkRemotePort),
"known_cfgversion": u.KnownCfgversion,
"led_override": u.LedOverride,
"locating": strconv.FormatBool(u.Locating),
"model": u.Model,
"outdoor_mode_override": u.OutdoorModeOverride,
"serial": u.Serial,
"type": u.Type,
"version_incompatible": strconv.FormatBool(u.VersionIncompatible),
"vwireEnabled": strconv.FormatBool(u.VwireEnabled),
"wifi_caps": strconv.Itoa(u.WifiCaps),
}
fields := map[string]interface{}{
"ip": u.IP,
"bytes": u.Bytes,
"bytes_d": u.BytesD,
"bytes_r": u.BytesR,
"last_seen": u.LastSeen,
"rx_bytes": u.RxBytes,
"rx_bytes-d": u.RxBytesD,
"tx_bytes": u.TxBytes,
"tx_bytes-d": u.TxBytesD,
"uptime": u.Uptime.Number,
"considered_lost_at": u.ConsideredLostAt,
"next_heartbeat_at": u.NextHeartbeatAt,
"scanning": u.Scanning,
"spectrum_scanning": u.SpectrumScanning,
"roll_upgrade": u.Rollupgrade,
"state": u.State,
"upgradable": u.Upgradable,
"user-num_sta": u.UserNumSta,
"version": u.Version,
"loadavg_1": u.SysStats.Loadavg1,
"loadavg_5": u.SysStats.Loadavg5,
"loadavg_15": u.SysStats.Loadavg15,
"mem_buffer": u.SysStats.MemBuffer,
"mem_total": u.SysStats.MemTotal,
"mem_used": u.SysStats.MemUsed,
"cpu": u.SystemStats.CPU,
"mem": u.SystemStats.Mem,
"system_uptime": u.SystemStats.Uptime,
"stat_bytes": u.Stat.Bytes,
"stat_duration": u.Stat.Duration,
"stat_guest-rx_bytes": u.Stat.RxBytes,
"stat_guest-rx_crypts": u.Stat.RxCrypts,
"stat_guest-rx_dropped": u.Stat.RxDropped,
"stat_guest-rx_errors": u.Stat.RxErrors,
"stat_guest-rx_frags": u.Stat.RxFrags,
"stat_guest-rx_packets": u.Stat.RxPackets,
"stat_guest-tx_bytes": u.Stat.TxBytes,
"stat_guest-tx_dropped": u.Stat.TxDropped,
"stat_guest-tx_errors": u.Stat.TxErrors,
"stat_guest-tx_packets": u.Stat.TxPackets,
"stat_guest-tx_retries": u.Stat.TxRetries,
"stat_port_1-rx_broadcast": u.Stat.Port1RxBroadcast,
"stat_port_1-rx_bytes": u.Stat.Port1RxBytes,
"stat_port_1-rx_multicast": u.Stat.Port1RxMulticast,
"stat_port_1-rx_packets": u.Stat.Port1RxPackets,
"stat_port_1-tx_broadcast": u.Stat.Port1TxBroadcast,
"stat_port_1-tx_bytes": u.Stat.Port1TxBytes,
"stat_port_1-tx_multicast": u.Stat.Port1TxMulticast,
"stat_port_1-tx_packets": u.Stat.Port1TxPackets,
"stat_rx_bytes": u.Stat.RxBytes,
"stat_rx_crypts": u.Stat.RxCrypts,
"stat_rx_dropped": u.Stat.RxDropped,
"stat_rx_errors": u.Stat.RxErrors,
"stat_rx_frags": u.Stat.RxFrags,
"stat_rx_packets": u.Stat.TxPackets,
"stat_tx_bytes": u.Stat.TxBytes,
"stat_tx_dropped": u.Stat.TxDropped,
"stat_tx_errors": u.Stat.TxErrors,
"stat_tx_packets": u.Stat.TxPackets,
"stat_tx_retries": u.Stat.TxRetries,
"stat_user-rx_bytes": u.Stat.UserRxBytes,
"stat_user-rx_crypts": u.Stat.UserRxCrypts,
"stat_user-rx_dropped": u.Stat.UserRxDropped,
"stat_user-rx_errors": u.Stat.UserRxErrors,
"stat_user-rx_frags": u.Stat.UserRxFrags,
"stat_user-rx_packets": u.Stat.UserRxPackets,
"stat_user-tx_bytes": u.Stat.UserTxBytes,
"stat_user-tx_dropped": u.Stat.UserTxDropped,
"stat_user-tx_errors": u.Stat.UserTxErrors,
"stat_user-tx_packets": u.Stat.UserTxPackets,
"stat_user-tx_retries": u.Stat.UserTxRetries,
"stat_user-wifi0-rx_bytes": u.Stat.UserWifi0RxBytes,
"stat_user-wifi0-rx_crypts": u.Stat.UserWifi0RxCrypts,
"stat_user-wifi0-rx_dropped": u.Stat.UserWifi0RxDropped,
"stat_user-wifi0-rx_errors": u.Stat.UserWifi0RxErrors,
"stat_user-wifi0-rx_frags": u.Stat.UserWifi0RxFrags,
"stat_user-wifi0-rx_packets": u.Stat.UserWifi0RxPackets,
"stat_user-wifi0-tx_bytes": u.Stat.UserWifi0TxBytes,
"stat_user-wifi0-tx_dropped": u.Stat.UserWifi0TxDropped,
"stat_user-wifi0-tx_errors": u.Stat.UserWifi0TxErrors,
"stat_user-wifi0-tx_packets": u.Stat.UserWifi0TxPackets,
"stat_user-wifi0-tx_retries": u.Stat.UserWifi0TxRetries,
"stat_user-wifi1-rx_bytes": u.Stat.UserWifi1RxBytes,
"stat_user-wifi1-rx_crypts": u.Stat.UserWifi1RxCrypts,
"stat_user-wifi1-rx_dropped": u.Stat.UserWifi1RxDropped,
"stat_user-wifi1-rx_errors": u.Stat.UserWifi1RxErrors,
"stat_user-wifi1-rx_frags": u.Stat.UserWifi1RxFrags,
"stat_user-wifi1-rx_packets": u.Stat.UserWifi1RxPackets,
"stat_user-wifi1-tx_bytes": u.Stat.UserWifi1TxBytes,
"stat_user-wifi1-tx_dropped": u.Stat.UserWifi1TxDropped,
"stat_user-wifi1-tx_errors": u.Stat.UserWifi1TxErrors,
"stat_user-wifi1-tx_packets": u.Stat.UserWifi1TxPackets,
"stat_user-wifi1-tx_retries": u.Stat.UserWifi1TxRetries,
"stat_wifi0-rx_bytes": u.Stat.Wifi0RxBytes,
"stat_wifi0-rx_crypts": u.Stat.Wifi0RxCrypts,
"stat_wifi0-rx_dropped": u.Stat.Wifi0RxDropped,
"stat_wifi0-rx_errors": u.Stat.Wifi0RxErrors,
"stat_wifi0-rx_frags": u.Stat.Wifi0RxFrags,
"stat_wifi0-rx_packets": u.Stat.Wifi0RxPackets,
"stat_wifi0-tx_bytes": u.Stat.Wifi0TxBytes,
"stat_wifi0-tx_dropped": u.Stat.Wifi0TxDropped,
"stat_wifi0-tx_errors": u.Stat.Wifi0TxErrors,
"stat_wifi0-tx_packets": u.Stat.Wifi0TxPackets,
"stat_wifi0-tx_retries": u.Stat.Wifi0TxRetries,
"stat_wifi1-rx_bytes": u.Stat.Wifi1RxBytes,
"stat_wifi1-rx_crypts": u.Stat.Wifi1RxCrypts,
"stat_wifi1-rx_dropped": u.Stat.Wifi1RxDropped,
"stat_wifi1-rx_errors": u.Stat.Wifi1RxErrors,
"stat_wifi1-rx_frags": u.Stat.Wifi1RxFrags,
"stat_wifi1-rx_packets": u.Stat.Wifi1RxPackets,
"stat_wifi1-tx_bytes": u.Stat.Wifi1TxBytes,
"stat_wifi1-tx_dropped": u.Stat.Wifi1TxDropped,
"stat_wifi1-tx_errors": u.Stat.Wifi1TxErrors,
"stat_wifi1-tx_packets": u.Stat.Wifi1TxPackets,
"stat_wifi1-tx_retries": u.Stat.Wifi1TxRetries,
}
pt, err := influx.NewPoint("uap", tags, fields, time.Now())
if err != nil {
return nil, err
}
points = append(points, pt)
for _, p := range u.RadioTable {
tags := map[string]string{
"device_name": u.Name,
"device_id": u.ID,
"device_mac": u.Mac,
"name": p.Name,
"wlangroup_id": p.WlangroupID,
"channel": p.Channel.String,
"radio": p.Radio,
}
fields := map[string]interface{}{
"builtin_ant_gain": p.BuiltinAntGain,
"current_antenna_gain": p.CurrentAntennaGain,
"has_dfs": p.HasDfs,
"has_fccdfs": p.HasFccdfs,
"ht": p.Ht,
"is_11ac": p.Is11Ac,
"max_txpower": p.MaxTxpower,
"min_rssi_enabled": p.MinRssiEnabled,
"min_txpower": p.MinTxpower,
"nss": p.Nss,
"radio_caps": p.RadioCaps,
"tx_power": p.TxPower.Number,
"tx_power_mode": p.TxPowerMode,
}
for _, s := range u.RadioTableStats {
// This may be a tad slower but it allows putting
// all the radio stats into one table.
if p.Name == s.Name {
fields["ast_be_xmit"] = s.AstBeXmit
fields["ast_cst"] = s.AstCst
fields["channel"] = s.Channel
fields["ast_txto"] = s.AstTxto
fields["cu_self_rx"] = s.CuSelfRx
fields["cu_self_tx"] = s.CuSelfTx
fields["cu_total"] = s.CuTotal
fields["extchannel"] = s.Extchannel
fields["gain"] = s.Gain
fields["guest-num_sta"] = s.GuestNumSta
fields["num_sta"] = s.NumSta
fields["radio"] = s.Radio
fields["state"] = s.State
fields["radio_tx_packets"] = s.TxPackets
fields["radio_tx_power"] = s.TxPower
fields["radio_tx_retries"] = s.TxRetries
fields["user-num_sta"] = s.UserNumSta
}
}
for _, s := range u.VapTable {
if p.Name == s.RadioName {
tags["ap_mac"] = s.ApMac
tags["bssid"] = s.Bssid
fields["ccq"] = s.Ccq
fields["essid"] = s.Essid
fields["extchannel"] = s.Extchannel
tags["vap_id"] = s.ID
fields["is_guest"] = s.IsGuest
fields["is_wep"] = s.IsWep
fields["mac_filter_rejections"] = s.MacFilterRejections
fields["map_id"] = s.MapID
tags["vap_name"] = s.Name
fields["rx_bytes"] = s.RxBytes
fields["rx_crypts"] = s.RxCrypts
fields["rx_dropped"] = s.RxDropped
fields["rx_errors"] = s.RxErrors
fields["rx_frags"] = s.RxFrags
fields["rx_nwids"] = s.RxNwids
fields["rx_packets"] = s.RxPackets
fields["tx_bytes"] = s.TxBytes
fields["tx_dropped"] = s.TxDropped
fields["tx_errors"] = s.TxErrors
fields["tx_latency_avg"] = s.TxLatencyAvg
fields["tx_latency_max"] = s.TxLatencyMax
fields["tx_latency_min"] = s.TxLatencyMin
fields["tx_packets"] = s.TxPackets
fields["tx_power"] = s.TxPower
fields["tx_retries"] = s.TxRetries
fields["usage"] = s.Usage
tags["wlanconf_id"] = s.WlanconfID
}
}
pt, err := influx.NewPoint("uap_radios", tags, fields, time.Now())
if err != nil {
return points, err
}
points = append(points, pt)
}
return points, nil
}

View File

@ -1,361 +0,0 @@
package unidev
// UAP is a Unifi Access Point.
type UAP struct {
/* This was auto generated and then slowly edited by hand
to get all the data types right and graphable.
No ones feelings will be hurt if you want to break this
up into multiple structs, and/or make it better in general.
*/
ID string `json:"_id"`
UUptime float64 `json:"_uptime"`
AdoptIP string `json:"adopt_ip,omitempty"`
AdoptURL string `json:"adopt_url,omitempty"`
Adopted bool `json:"adopted"`
AntennaTable []struct {
ID float64 `json:"id"`
Name string `json:"name"`
Wifi0Gain float64 `json:"wifi0_gain"`
Wifi1Gain float64 `json:"wifi1_gain"`
} `json:"antenna_table"`
BandsteeringMode string `json:"bandsteering_mode,omitempty"`
BoardRev int `json:"board_rev"`
Bytes float64 `json:"bytes"`
BytesD float64 `json:"bytes-d"`
BytesR float64 `json:"bytes-r"`
Cfgversion string `json:"cfgversion"`
ConfigNetwork struct {
IP string `json:"ip"`
Type string `json:"type"`
} `json:"config_network"`
ConnectRequestIP string `json:"connect_request_ip"`
ConnectRequestPort string `json:"connect_request_port"`
ConsideredLostAt float64 `json:"considered_lost_at"`
CountrycodeTable []float64 `json:"countrycode_table"`
Default bool `json:"default,omitempty"`
DeviceID string `json:"device_id"`
DiscoveredVia string `json:"discovered_via,omitempty"`
DownlinkTable []interface{} `json:"downlink_table"`
EthernetTable []struct {
Mac string `json:"mac"`
Name string `json:"name"`
NumPort float64 `json:"num_port"`
} `json:"ethernet_table"`
FwCaps int `json:"fw_caps"`
GuestNumSta int `json:"guest-num_sta"`
GuestToken string `json:"guest_token"`
HasEth1 bool `json:"has_eth1"`
HasSpeaker bool `json:"has_speaker"`
InformIP string `json:"inform_ip"`
InformURL string `json:"inform_url"`
IP string `json:"ip"`
Isolated bool `json:"isolated"`
KnownCfgversion string `json:"known_cfgversion"`
LastSeen float64 `json:"last_seen"`
LastUplink struct {
UplinkMac string `json:"uplink_mac"`
UplinkRemotePort int `json:"uplink_remote_port"`
} `json:"last_uplink"`
LedOverride string `json:"led_override"`
Locating bool `json:"locating"`
Mac string `json:"mac"`
Model string `json:"model"`
Name string `json:"name"`
NextHeartbeatAt float64 `json:"next_heartbeat_at"`
NumSta float64 `json:"num_sta"`
OutdoorModeOverride string `json:"outdoor_mode_override"`
PortTable []struct {
AggregatedBy bool `json:"aggregated_by"`
AttrNoEdit bool `json:"attr_no_edit,omitempty"`
Autoneg bool `json:"autoneg"`
BytesR float64 `json:"bytes-r"`
Enable bool `json:"enable"`
FlowctrlRx bool `json:"flowctrl_rx"`
FlowctrlTx bool `json:"flowctrl_tx"`
FullDuplex bool `json:"full_duplex"`
IsUplink bool `json:"is_uplink"`
Jumbo bool `json:"jumbo"`
MacTable []struct {
Age float64 `json:"age"`
Mac string `json:"mac"`
Static bool `json:"static"`
Uptime float64 `json:"uptime"`
Vlan float64 `json:"vlan"`
} `json:"mac_table"`
Masked bool `json:"masked"`
Media string `json:"media"`
Name string `json:"name"`
OpMode string `json:"op_mode"`
PoeCaps float64 `json:"poe_caps"`
PortDelta struct {
RxBytes float64 `json:"rx_bytes"`
RxPackets float64 `json:"rx_packets"`
TimeDelta float64 `json:"time_delta"`
TxBytes float64 `json:"tx_bytes"`
TxPackets float64 `json:"tx_packets"`
} `json:"port_delta"`
PortIdx float64 `json:"port_idx"`
PortPoe bool `json:"port_poe"`
PortconfID string `json:"portconf_id"`
RxBroadcast float64 `json:"rx_broadcast"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
StpPathcost float64 `json:"stp_pathcost"`
StpState string `json:"stp_state"`
TxBroadcast float64 `json:"tx_broadcast"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxMulticast float64 `json:"tx_multicast"`
TxPackets float64 `json:"tx_packets"`
Up bool `json:"up"`
} `json:"port_table"`
RadioTable []struct {
BuiltinAntGain float64 `json:"builtin_ant_gain"`
BuiltinAntenna bool `json:"builtin_antenna"`
Channel FlexInt `json:"channel"`
CurrentAntennaGain float64 `json:"current_antenna_gain"`
Ht string `json:"ht"`
MaxTxpower float64 `json:"max_txpower"`
MinRssiEnabled bool `json:"min_rssi_enabled"`
MinTxpower float64 `json:"min_txpower"`
Name string `json:"name"`
Nss float64 `json:"nss"`
Radio string `json:"radio"`
RadioCaps float64 `json:"radio_caps"`
TxPower FlexInt `json:"tx_power"`
TxPowerMode string `json:"tx_power_mode"`
WlangroupID string `json:"wlangroup_id"`
HasDfs bool `json:"has_dfs,omitempty"`
HasFccdfs bool `json:"has_fccdfs,omitempty"`
Is11Ac bool `json:"is_11ac,omitempty"`
} `json:"radio_table"`
RadioTableStats []struct {
AstBeXmit float64 `json:"ast_be_xmit"`
AstCst float64 `json:"ast_cst"`
AstTxto float64 `json:"ast_txto"`
Channel float64 `json:"channel"`
CuSelfRx float64 `json:"cu_self_rx"`
CuSelfTx float64 `json:"cu_self_tx"`
CuTotal float64 `json:"cu_total"`
Extchannel float64 `json:"extchannel"`
Gain float64 `json:"gain"`
GuestNumSta float64 `json:"guest-num_sta"`
Name string `json:"name"`
NumSta float64 `json:"num_sta"`
Radio string `json:"radio"`
State string `json:"state"`
TxPackets float64 `json:"tx_packets"`
TxPower float64 `json:"tx_power"`
TxRetries float64 `json:"tx_retries"`
UserNumSta float64 `json:"user-num_sta"`
} `json:"radio_table_stats"`
Rollupgrade bool `json:"rollupgrade"`
RxBytes float64 `json:"rx_bytes"`
RxBytesD float64 `json:"rx_bytes-d"`
ScanRadioTable []interface{} `json:"scan_radio_table"`
Scanning bool `json:"scanning"`
Serial string `json:"serial"`
SiteID string `json:"site_id"`
SpectrumScanning bool `json:"spectrum_scanning"`
SSHSessionTable []interface{} `json:"ssh_session_table"`
Stat struct {
Ap string `json:"ap"`
Bytes float64 `json:"bytes"`
Datetime string `json:"datetime"`
Duration float64 `json:"duration"`
GuestRxBytes float64 `json:"guest-rx_bytes"`
GuestRxCrypts float64 `json:"guest-rx_crypts"`
GuestRxDropped float64 `json:"guest-rx_dropped"`
GuestRxErrors float64 `json:"guest-rx_errors"`
GuestRxFrags float64 `json:"guest-rx_frags"`
GuestRxPackets float64 `json:"guest-rx_packets"`
GuestTxBytes float64 `json:"guest-tx_bytes"`
GuestTxDropped float64 `json:"guest-tx_dropped"`
GuestTxErrors float64 `json:"guest-tx_errors"`
GuestTxPackets float64 `json:"guest-tx_packets"`
GuestTxRetries float64 `json:"guest-tx_retries"`
O string `json:"o"`
Oid string `json:"oid"`
Port1RxBroadcast float64 `json:"port_1-rx_broadcast"`
Port1RxBytes float64 `json:"port_1-rx_bytes"`
Port1RxMulticast float64 `json:"port_1-rx_multicast"`
Port1RxPackets float64 `json:"port_1-rx_packets"`
Port1TxBroadcast float64 `json:"port_1-tx_broadcast"`
Port1TxBytes float64 `json:"port_1-tx_bytes"`
Port1TxMulticast float64 `json:"port_1-tx_multicast"`
Port1TxPackets float64 `json:"port_1-tx_packets"`
RxBytes float64 `json:"rx_bytes"`
RxCrypts float64 `json:"rx_crypts"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxFrags float64 `json:"rx_frags"`
RxPackets float64 `json:"rx_packets"`
SiteID string `json:"site_id"`
Time float64 `json:"time"`
TxBytes float64 `json:"tx_bytes"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
TxRetries float64 `json:"tx_retries"`
UserRxBytes float64 `json:"user-rx_bytes"`
UserRxCrypts float64 `json:"user-rx_crypts"`
UserRxDropped float64 `json:"user-rx_dropped"`
UserRxErrors float64 `json:"user-rx_errors"`
UserRxFrags float64 `json:"user-rx_frags"`
UserRxPackets float64 `json:"user-rx_packets"`
UserTxBytes float64 `json:"user-tx_bytes"`
UserTxDropped float64 `json:"user-tx_dropped"`
UserTxErrors float64 `json:"user-tx_errors"`
UserTxPackets float64 `json:"user-tx_packets"`
UserTxRetries float64 `json:"user-tx_retries"`
UserWifi0RxBytes float64 `json:"user-wifi0-rx_bytes"`
UserWifi0RxCrypts float64 `json:"user-wifi0-rx_crypts"`
UserWifi0RxDropped float64 `json:"user-wifi0-rx_dropped"`
UserWifi0RxErrors float64 `json:"user-wifi0-rx_errors"`
UserWifi0RxFrags float64 `json:"user-wifi0-rx_frags"`
UserWifi0RxPackets float64 `json:"user-wifi0-rx_packets"`
UserWifi0TxBytes float64 `json:"user-wifi0-tx_bytes"`
UserWifi0TxDropped float64 `json:"user-wifi0-tx_dropped"`
UserWifi0TxErrors float64 `json:"user-wifi0-tx_errors"`
UserWifi0TxPackets float64 `json:"user-wifi0-tx_packets"`
UserWifi0TxRetries float64 `json:"user-wifi0-tx_retries"`
UserWifi1RxBytes float64 `json:"user-wifi1-rx_bytes"`
UserWifi1RxCrypts float64 `json:"user-wifi1-rx_crypts"`
UserWifi1RxDropped float64 `json:"user-wifi1-rx_dropped"`
UserWifi1RxErrors float64 `json:"user-wifi1-rx_errors"`
UserWifi1RxFrags float64 `json:"user-wifi1-rx_frags"`
UserWifi1RxPackets float64 `json:"user-wifi1-rx_packets"`
UserWifi1TxBytes float64 `json:"user-wifi1-tx_bytes"`
UserWifi1TxDropped float64 `json:"user-wifi1-tx_dropped"`
UserWifi1TxErrors float64 `json:"user-wifi1-tx_errors"`
UserWifi1TxPackets float64 `json:"user-wifi1-tx_packets"`
UserWifi1TxRetries float64 `json:"user-wifi1-tx_retries"`
Wifi0RxBytes float64 `json:"wifi0-rx_bytes"`
Wifi0RxCrypts float64 `json:"wifi0-rx_crypts"`
Wifi0RxDropped float64 `json:"wifi0-rx_dropped"`
Wifi0RxErrors float64 `json:"wifi0-rx_errors"`
Wifi0RxFrags float64 `json:"wifi0-rx_frags"`
Wifi0RxPackets float64 `json:"wifi0-rx_packets"`
Wifi0TxBytes float64 `json:"wifi0-tx_bytes"`
Wifi0TxDropped float64 `json:"wifi0-tx_dropped"`
Wifi0TxErrors float64 `json:"wifi0-tx_errors"`
Wifi0TxPackets float64 `json:"wifi0-tx_packets"`
Wifi0TxRetries float64 `json:"wifi0-tx_retries"`
Wifi1RxBytes float64 `json:"wifi1-rx_bytes"`
Wifi1RxCrypts float64 `json:"wifi1-rx_crypts"`
Wifi1RxDropped float64 `json:"wifi1-rx_dropped"`
Wifi1RxErrors float64 `json:"wifi1-rx_errors"`
Wifi1RxFrags float64 `json:"wifi1-rx_frags"`
Wifi1RxPackets float64 `json:"wifi1-rx_packets"`
Wifi1TxBytes float64 `json:"wifi1-tx_bytes"`
Wifi1TxDropped float64 `json:"wifi1-tx_dropped"`
Wifi1TxErrors float64 `json:"wifi1-tx_errors"`
Wifi1TxPackets float64 `json:"wifi1-tx_packets"`
Wifi1TxRetries float64 `json:"wifi1-tx_retries"`
} `json:"stat"`
State int `json:"state"`
SysStats struct {
Loadavg1 float64 `json:"loadavg_1,string"`
Loadavg15 float64 `json:"loadavg_15,string"`
Loadavg5 float64 `json:"loadavg_5,string"`
MemBuffer float64 `json:"mem_buffer"`
MemTotal float64 `json:"mem_total"`
MemUsed float64 `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU float64 `json:"cpu,string"`
Mem float64 `json:"mem,string"`
Uptime float64 `json:"uptime,string"`
} `json:"system-stats"`
TxBytes float64 `json:"tx_bytes"`
TxBytesD float64 `json:"tx_bytes-d"`
Type string `json:"type"`
Upgradable bool `json:"upgradable"`
Uplink struct {
FullDuplex bool `json:"full_duplex"`
IP string `json:"ip"`
Mac string `json:"mac"`
MaxSpeed int `json:"max_speed"`
MaxVlan int `json:"max_vlan"`
Media string `json:"media"`
Name string `json:"name"`
Netmask string `json:"netmask"`
NumPort int `json:"num_port"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
UplinkMac string `json:"uplink_mac"`
UplinkRemotePort int `json:"uplink_remote_port"`
} `json:"uplink"`
UplinkTable []interface{} `json:"uplink_table"`
Uptime FlexInt `json:"uptime"`
UserNumSta int `json:"user-num_sta"`
VapTable []struct {
ApMac string `json:"ap_mac"`
Bssid string `json:"bssid"`
Ccq int `json:"ccq"`
Channel int `json:"channel"`
Essid string `json:"essid"`
Extchannel int `json:"extchannel"`
ID string `json:"id"`
IsGuest bool `json:"is_guest"`
IsWep bool `json:"is_wep"`
MacFilterRejections int `json:"mac_filter_rejections"`
MapID string `json:"map_id"`
Name string `json:"name"`
NumSta int `json:"num_sta"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
RxBytes float64 `json:"rx_bytes"`
RxCrypts float64 `json:"rx_crypts"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxFrags float64 `json:"rx_frags"`
RxNwids float64 `json:"rx_nwids"`
RxPackets float64 `json:"rx_packets"`
SiteID string `json:"site_id"`
State string `json:"state"`
T string `json:"t"`
TxBytes float64 `json:"tx_bytes"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxLatencyAvg float64 `json:"tx_latency_avg"`
TxLatencyMax float64 `json:"tx_latency_max"`
TxLatencyMin float64 `json:"tx_latency_min"`
TxPackets float64 `json:"tx_packets"`
TxPower int `json:"tx_power"`
TxRetries int `json:"tx_retries"`
Up bool `json:"up"`
Usage string `json:"usage"`
WlanconfID string `json:"wlanconf_id"`
} `json:"vap_table"`
Version string `json:"version"`
VersionIncompatible bool `json:"version_incompatible"`
VwireEnabled bool `json:"vwireEnabled"`
VwireTable []interface{} `json:"vwire_table"`
VwireVapTable []struct {
Bssid string `json:"bssid"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
State string `json:"state"`
} `json:"vwire_vap_table"`
WifiCaps int `json:"wifi_caps"`
}

View File

@ -1,105 +0,0 @@
package unidev
import (
"bytes"
"crypto/tls"
"encoding/json"
"log"
"net/http"
"net/http/cookiejar"
"strconv"
influx "github.com/influxdata/influxdb/client/v2"
"github.com/pkg/errors"
)
// LoginPath is Unifi Controller Login API Path
const LoginPath = "/api/login"
// Asset provides a common interface to retreive metrics from a device or client.
// It currently only supports InfluxDB, but could be amended to support other
// libraries that have a similar interface.
// This app only uses the .AddPoint/s() methods with the Asset type.
type Asset interface {
// Point() means this is useful to influxdb..
Points() ([]*influx.Point, error)
// Add more methods to achieve more usefulness from this library.
}
// AuthedReq is what you get in return for providing a password!
type AuthedReq struct {
*http.Client
baseURL string
}
// FlexInt provides a container and unmarshalling for fields that may be
// numbers or strings in the Unifi API
type FlexInt struct {
Number float64
String string
}
// UnmarshalJSON converts a string or number to an integer.
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.Number = i
f.String = strconv.FormatFloat(i, 'f', -1, 64)
return nil
case string:
f.String = i
f.Number, _ = strconv.ParseFloat(i, 64)
return nil
default:
return errors.New("Cannot unmarshal to FlexInt")
}
}
// AuthController creates a http.Client with authenticated cookies.
// Used to make additional, authenticated requests to the APIs.
func AuthController(user, pass, url string, verifySSL bool) (*AuthedReq, error) {
json := `{"username": "` + user + `","password": "` + pass + `"}`
jar, err := cookiejar.New(nil)
if err != nil {
return nil, errors.Wrap(err, "cookiejar.New(nil)")
}
a := &AuthedReq{&http.Client{
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !verifySSL}},
Jar: jar,
}, url}
req, err := a.UniReq(LoginPath, json)
if err != nil {
return a, errors.Wrap(err, "UniReq(LoginPath, json)")
}
resp, err := a.Do(req)
if err != nil {
return a, errors.Wrap(err, "authReq.Do(req)")
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal. Just log it.
}
}()
if resp.StatusCode != http.StatusOK {
return a, errors.Errorf("authentication failed (%v): %v (status: %v/%v)",
user, url+LoginPath, resp.StatusCode, resp.Status)
}
return a, nil
}
// UniReq is a small helper function that adds an Accept header.
func (a AuthedReq) UniReq(apiPath string, params string) (req *http.Request, err error) {
if params != "" {
req, err = http.NewRequest("POST", a.baseURL+apiPath, bytes.NewBufferString(params))
} else {
req, err = http.NewRequest("GET", a.baseURL+apiPath, nil)
}
if err == nil {
req.Header.Add("Accept", "application/json")
}
return
}

View File

@ -1,82 +0,0 @@
package unidev
import (
"encoding/json"
"io/ioutil"
"net/http"
"testing"
"github.com/stretchr/testify/assert"
)
func TestFlexInt(t *testing.T) {
t.Parallel()
a := assert.New(t)
type testReply struct {
Five FlexInt `json:"five"`
Seven FlexInt `json:"seven"`
Auto FlexInt `json:"auto"`
Channel FlexInt `json:"channel"`
}
var r testReply
// test unmarshalling the custom type three times with different values.
a.Nil(json.Unmarshal([]byte(`{"five": "5", "seven": 7, "auto": "auto"}`), &r))
// test number in string.
a.EqualValues(5, r.Five.Number)
a.EqualValues("5", r.Five.String)
// test number.
a.EqualValues(7, r.Seven.Number)
a.EqualValues("7", r.Seven.String)
// test string.
a.EqualValues(0, r.Auto.Number)
a.EqualValues("auto", r.Auto.String)
// 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.Number)
}
func TestUniReq(t *testing.T) {
t.Parallel()
a := assert.New(t)
u := "/test/path"
url := "http://some.url:8443"
// Test empty parameters.
authReq := &AuthedReq{&http.Client{}, url}
r, err := authReq.UniReq(u, "")
a.Nil(err, "newrequest must not produce an error")
a.EqualValues(u, r.URL.Path,
"the provided apiPath was not added to http request")
a.EqualValues(url, 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
p := "key1=value9&key2=value7"
authReq = &AuthedReq{&http.Client{}, "http://some.url:8443"}
r, err = authReq.UniReq(u, p)
a.Nil(err, "newrequest must not produce an error")
a.EqualValues(u, r.URL.Path,
"the provided apiPath was not added to http request")
a.EqualValues(url, 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(p, string(d), "POST parameters improperly encoded")
}
func TestAuthController(t *testing.T) {
t.Parallel()
a := assert.New(t)
url := "http://127.0.0.1:64431"
authReq, err := AuthController("user1", "pass2", url, false)
a.NotNil(err)
a.EqualValues(url, authReq.baseURL)
a.Contains(err.Error(), "authReq.Do(req):", "an invalid destination should product a .Do(req) error.")
/* TODO: 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")
*/
}

View File

@ -1,154 +0,0 @@
package unidev
import (
"encoding/json"
"io/ioutil"
"log"
"github.com/pkg/errors"
)
// Debug ....
var Debug = false
const (
// ClientPath is Unifi Clients API Path
ClientPath = "/api/s/default/stat/sta"
// DevicePath is where we get data about Unifi devices.
DevicePath = "/api/s/default/stat/device"
// NetworkPath contains network-configuration data. Not really graphable.
NetworkPath = "/api/s/default/rest/networkconf"
// UserGroupPath contains usergroup configurations.
UserGroupPath = "/api/s/default/rest/usergroup"
)
// GetUnifiClients returns a response full of clients' data from the Unifi Controller.
func (c *AuthedReq) GetUnifiClients() ([]UCL, error) {
var response struct {
Clients []UCL `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
req, err := c.UniReq(ClientPath, "")
if err != nil {
return nil, errors.Wrap(err, "c.UniReq(ClientPath)")
}
resp, err := c.Do(req)
if err != nil {
return nil, errors.Wrap(err, "c.Do(req)")
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
}()
if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, errors.Wrap(err, "ioutil.ReadAll(resp.Body)")
} else if err = json.Unmarshal(body, &response); err != nil {
return nil, errors.Wrap(err, "json.Unmarshal([]UCL)")
}
return response.Clients, nil
}
// GetUnifiClientAssets provides an interface to return common asset types.
func (c *AuthedReq) GetUnifiClientAssets() ([]Asset, error) {
clients, err := c.GetUnifiClients()
assets := []Asset{}
if err == nil {
for _, r := range clients {
assets = append(assets, r)
}
}
return assets, err
}
// GetUnifiDevices returns a response full of devices' data from the Unifi Controller.
func (c *AuthedReq) GetUnifiDevices() ([]USG, []USW, []UAP, error) {
var parsed struct {
Data []json.RawMessage `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
req, err := c.UniReq(DevicePath, "")
if err != nil {
return nil, nil, nil, errors.Wrap(err, "c.UniReq(DevicePath)")
}
resp, err := c.Do(req)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "c.Do(req)")
}
defer func() {
if err := resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
}()
if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, nil, nil, errors.Wrap(err, "ioutil.ReadAll(resp.Body)")
} else if err = json.Unmarshal(body, &parsed); err != nil {
return nil, nil, nil, errors.Wrap(err, "json.Unmarshal([]json.RawMessage)")
}
var usgs []USG
var usws []USW
var uaps []UAP
// Loop each item in the raw JSON message, detect its type and unmarshal it.
for i, r := range parsed.Data {
var usg USG
var usw USW
var uap UAP
// Unamrshal into a map and check "type"
var obj map[string]interface{}
if err := json.Unmarshal(r, &obj); err != nil {
return nil, nil, nil, errors.Wrapf(err, "[%d] json.Unmarshal(interfce{})", i)
}
assetType := "<missing>"
if t, ok := obj["type"].(string); ok {
assetType = t
}
if Debug {
log.Println("Unmarshalling Device Type:", assetType)
}
// Unmarshal again into the correct type..
switch assetType {
case "uap":
if err := json.Unmarshal(r, &uap); err != nil {
return nil, nil, nil, errors.Wrapf(err, "[%d] json.Unmarshal([]UAP)", i)
}
uaps = append(uaps, uap)
case "ugw", "usg": // in case they ever fix the name in the api.
if err := json.Unmarshal(r, &usg); err != nil {
return nil, nil, nil, errors.Wrapf(err, "[%d] json.Unmarshal([]USG)", i)
}
usgs = append(usgs, usg)
case "usw":
if err := json.Unmarshal(r, &usw); err != nil {
return nil, nil, nil, errors.Wrapf(err, "[%d] json.Unmarshal([]USW)", i)
}
usws = append(usws, usw)
default:
log.Println("unknown asset type -", assetType, "- skipping")
continue
}
}
return usgs, usws, uaps, nil
}
// GetUnifiDeviceAssets provides an interface to return common asset types.
func (c *AuthedReq) GetUnifiDeviceAssets() ([]Asset, error) {
usgs, usws, uaps, err := c.GetUnifiDevices()
assets := []Asset{}
if err == nil {
for _, r := range usgs {
assets = append(assets, r)
}
for _, r := range usws {
assets = append(assets, r)
}
for _, r := range uaps {
assets = append(assets, r)
}
}
return assets, err
}

View File

@ -1,186 +0,0 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Points generates a device's datapoints for InfluxDB.
func (u USG) Points() ([]*influx.Point, error) {
var points []*influx.Point
tags := map[string]string{
"id": u.ID,
"mac": u.Mac,
"device_type": u.Stat.O,
"device_oid": u.Stat.Oid,
"site_id": u.SiteID,
"addopted": strconv.FormatBool(u.Adopted),
"name": u.Name,
"adopt_ip": u.AdoptIP,
"adopt_url": u.AdoptURL,
"cfgversion": u.Cfgversion,
"config_network_ip": u.ConfigNetwork.IP,
"config_network_type": u.ConfigNetwork.Type,
"connect_request_ip": u.ConnectRequestIP,
"connect_request_port": u.ConnectRequestPort,
"default": strconv.FormatBool(u.Default),
"device_id": u.DeviceID,
"discovered_via": u.DiscoveredVia,
"guest_token": u.GuestToken,
"inform_ip": u.InformIP,
"known_cfgversion": u.KnownCfgversion,
"led_override": u.LedOverride,
"locating": strconv.FormatBool(u.Locating),
"model": u.Model,
"outdoor_mode_override": u.OutdoorModeOverride,
"serial": u.Serial,
"type": u.Type,
"version_incompatible": strconv.FormatBool(u.VersionIncompatible),
"usg_caps": strconv.FormatFloat(u.UsgCaps, 'f', 6, 64),
"speedtest-status-saved": strconv.FormatBool(u.SpeedtestStatusSaved),
}
fields := map[string]interface{}{
"ip": u.IP,
"bytes": u.Bytes,
"last_seen": u.LastSeen,
"license_state": u.LicenseState,
"fw_caps": u.FwCaps,
"guest-num_sta": u.GuestNumSta,
"rx_bytes": u.RxBytes,
"tx_bytes": u.TxBytes,
"uptime": u.Uptime,
"considered_lost_at": u.ConsideredLostAt,
"next_heartbeat_at": u.NextHeartbeatAt,
"roll_upgrade": u.Rollupgrade,
"state": u.State,
"upgradable": u.Upgradable,
"user-num_sta": u.UserNumSta,
"version": u.Version,
"num_desktop": u.NumDesktop,
"num_handheld": u.NumHandheld,
"num_mobile": u.NumMobile,
"speedtest-status_latency": u.SpeedtestStatus.Latency,
"speedtest-status_rundate": u.SpeedtestStatus.Rundate,
"speedtest-status_runtime": u.SpeedtestStatus.Runtime,
"speedtest-status_download": u.SpeedtestStatus.StatusDownload,
"speedtest-status_ping": u.SpeedtestStatus.StatusPing,
"speedtest-status_summary": u.SpeedtestStatus.StatusSummary,
"speedtest-status_upload": u.SpeedtestStatus.StatusUpload,
"speedtest-status_xput_download": u.SpeedtestStatus.XputDownload,
"speedtest-status_xput_upload": u.SpeedtestStatus.XputUpload,
// have two WANs? mmmm, go ahead and add it. ;)
"config_network_wan_type": u.ConfigNetworkWan.Type,
"wan1_bytes-r": u.Wan1.BytesR,
"wan1_enable": u.Wan1.Enable,
"wan1_full_duplex": u.Wan1.FullDuplex,
"wan1_purpose": "uplink", // because it should have a purpose.
"wan1_gateway": u.Wan1.Gateway,
"wan1_ifname": u.Wan1.Ifname,
"wan1_ip": u.Wan1.IP,
"wan1_mac": u.Wan1.Mac,
"wan1_max_speed": u.Wan1.MaxSpeed,
"wan1_name": u.Wan1.Name,
"wan1_netmask": u.Wan1.Netmask,
"wan1_rx_bytes": u.Wan1.RxBytes,
"wan1_rx_bytes-r": u.Wan1.RxBytesR,
"wan1_rx_dropped": u.Wan1.RxDropped,
"wan1_rx_errors": u.Wan1.RxErrors,
"wan1_rx_multicast": u.Wan1.RxMulticast,
"wan1_rx_packets": u.Wan1.RxPackets,
"wan1_type": u.Wan1.Type,
"wan1_speed": u.Wan1.Speed,
"wan1_up": u.Wan1.Up,
"wan1_tx_bytes": u.Wan1.TxBytes,
"wan1_tx_bytes-r": u.Wan1.TxBytesR,
"wan1_tx_dropped": u.Wan1.TxDropped,
"wan1_tx_errors": u.Wan1.TxErrors,
"wan1_tx_packets": u.Wan1.TxPackets,
"loadavg_1": u.SysStats.Loadavg1,
"loadavg_5": u.SysStats.Loadavg5,
"loadavg_15": u.SysStats.Loadavg15,
"mem_used": u.SysStats.MemUsed,
"mem_buffer": u.SysStats.MemBuffer,
"mem_total": u.SysStats.MemTotal,
"cpu": u.SystemStats.CPU,
"mem": u.SystemStats.Mem,
"system_uptime": u.SystemStats.Uptime,
"stat_duration": u.Stat.Duration,
"stat_datetime": u.Stat.Datetime,
"gw": u.Stat.Gw,
"false": "false", // to fill holes in graphs.
"lan-rx_bytes": u.Stat.LanRxBytes,
"lan-rx_packets": u.Stat.LanRxPackets,
"lan-tx_bytes": u.Stat.LanTxBytes,
"lan-tx_packets": u.Stat.LanTxPackets,
"wan-rx_bytes": u.Stat.WanRxBytes,
"wan-rx_dropped": u.Stat.WanRxDropped,
"wan-rx_packets": u.Stat.WanRxPackets,
"wan-tx_bytes": u.Stat.WanTxBytes,
"wan-tx_packets": u.Stat.WanTxPackets,
"uplink_name": u.Uplink.Name,
"uplink_latency": u.Uplink.Latency,
"uplink_speed": u.Uplink.Speed,
"uplink_num_ports": u.Uplink.NumPort,
"uplink_max_speed": u.Uplink.MaxSpeed,
}
pt, err := influx.NewPoint("usg", tags, fields, time.Now())
if err != nil {
return nil, err
}
points = append(points, pt)
for _, p := range u.NetworkTable {
tags := map[string]string{
"device_name": u.Name,
"device_id": u.ID,
"device_mac": u.Mac,
"name": p.Name,
"dhcpd_dns_enabled": strconv.FormatBool(p.DhcpdDNSEnabled),
"dhcpd_enabled": strconv.FormatBool(p.DhcpdEnabled),
"dhcpd_ntp_enabled": strconv.FormatBool(p.DhcpdNtpEnabled),
"dhcpd_time_offset_enabled": strconv.FormatBool(p.DhcpdTimeOffsetEnabled),
"dhcp_relay_enabledy": strconv.FormatBool(p.DhcpRelayEnabled),
"dhcpd_gateway_enabled": strconv.FormatBool(p.DhcpdGatewayEnabled),
"dhcpd_wins_enabled": strconv.FormatBool(p.DhcpdWinsEnabled),
"dhcpguard_enabled": strconv.FormatBool(p.DhcpguardEnabled),
"enabled": strconv.FormatBool(p.Enabled),
"vlan_enabled": strconv.FormatBool(p.VlanEnabled),
"attr_no_delete": strconv.FormatBool(p.AttrNoDelete),
"upnp_lan_enabled": strconv.FormatBool(p.UpnpLanEnabled),
"igmp_snooping": strconv.FormatBool(p.IgmpSnooping),
"is_guest": strconv.FormatBool(p.IsGuest),
"is_nat": strconv.FormatBool(p.IsNat),
"networkgroup": p.Networkgroup,
"site_id": p.SiteID,
}
fields := map[string]interface{}{
"dhcpd_ip_1": p.DhcpdIP1,
"domain_name": p.DomainName,
"dhcpd_start": p.DhcpdStart,
"dhcpd_stop": p.DhcpdStop,
"ip": p.IP,
"ip_subnet": p.IPSubnet,
"mac": p.Mac,
"name": p.Name,
"num_sta": p.NumSta,
"purpose": p.Purpose,
"rx_bytes": p.RxBytes,
"rx_packets": p.RxPackets,
"tx_bytes": p.TxBytes,
"tx_packets": p.TxPackets,
"up": p.Up,
"vlan": p.Vlan,
"dhcpd_ntp_1": p.DhcpdNtp1,
"dhcpd_unifi_controller": p.DhcpdUnifiController,
"ipv6_interface_type": p.Ipv6InterfaceType,
"attr_hidden_id": p.AttrHiddenID,
}
pt, err = influx.NewPoint("usg_networks", tags, fields, time.Now())
if err != nil {
return points, err
}
points = append(points, pt)
}
return points, err
}

View File

@ -1,260 +0,0 @@
package unidev
import "encoding/json"
// USG is a Unifi Security Gateway
type USG struct {
ID string `json:"_id"`
UUptime float64 `json:"_uptime"`
AdoptIP string `json:"adopt_ip"`
AdoptURL string `json:"adopt_url"`
Adopted bool `json:"adopted"`
Bytes float64 `json:"bytes"`
Cfgversion string `json:"cfgversion"`
ConfigNetwork struct {
IP string `json:"ip"`
Type string `json:"type"`
} `json:"config_network"`
ConfigNetworkWan struct {
Type string `json:"type"`
} `json:"config_network_wan"`
ConnectRequestIP string `json:"connect_request_ip"`
ConnectRequestPort string `json:"connect_request_port"`
ConsideredLostAt float64 `json:"considered_lost_at"`
Default bool `json:"default"`
DeviceID string `json:"device_id"`
DiscoveredVia string `json:"discovered_via"`
EthernetTable []struct {
Mac string `json:"mac"`
Name string `json:"name"`
NumPort float64 `json:"num_port"`
} `json:"ethernet_table"`
FwCaps float64 `json:"fw_caps"`
GuestNumSta float64 `json:"guest-num_sta"`
GuestToken string `json:"guest_token"`
InformIP string `json:"inform_ip"`
InformURL string `json:"inform_url"`
IP string `json:"ip"`
KnownCfgversion string `json:"known_cfgversion"`
LastSeen float64 `json:"last_seen"`
LedOverride string `json:"led_override"`
LicenseState string `json:"license_state"`
Locating bool `json:"locating"`
Mac string `json:"mac"`
Model string `json:"model"`
Name string `json:"name"`
NetworkTable []struct {
ID string `json:"_id"`
DhcpdDNSEnabled bool `json:"dhcpd_dns_enabled"`
DhcpdEnabled bool `json:"dhcpd_enabled"`
DhcpdIP1 string `json:"dhcpd_ip_1,omitempty"`
DhcpdLeasetime json.Number `json:"dhcpd_leasetime,Number"`
DhcpdStart string `json:"dhcpd_start"`
DhcpdStop string `json:"dhcpd_stop"`
DhcpdWinsEnabled bool `json:"dhcpd_wins_enabled,omitempty"`
DhcpguardEnabled bool `json:"dhcpguard_enabled,omitempty"`
DomainName string `json:"domain_name"`
Enabled bool `json:"enabled"`
IgmpSnooping bool `json:"igmp_snooping,omitempty"`
IP string `json:"ip"`
IPSubnet string `json:"ip_subnet"`
IsGuest bool `json:"is_guest"`
IsNat bool `json:"is_nat"`
Mac string `json:"mac"`
Name string `json:"name"`
Networkgroup string `json:"networkgroup"`
NumSta float64 `json:"num_sta"`
Purpose string `json:"purpose"`
RxBytes float64 `json:"rx_bytes"`
RxPackets float64 `json:"rx_packets"`
SiteID string `json:"site_id"`
TxBytes float64 `json:"tx_bytes"`
TxPackets float64 `json:"tx_packets"`
Up string `json:"up"`
Vlan string `json:"vlan,omitempty"`
VlanEnabled bool `json:"vlan_enabled"`
DhcpRelayEnabled bool `json:"dhcp_relay_enabled,omitempty"`
DhcpdGatewayEnabled bool `json:"dhcpd_gateway_enabled,omitempty"`
DhcpdNtp1 string `json:"dhcpd_ntp_1,omitempty"`
DhcpdNtpEnabled bool `json:"dhcpd_ntp_enabled,omitempty"`
DhcpdTimeOffsetEnabled bool `json:"dhcpd_time_offset_enabled,omitempty"`
DhcpdUnifiController string `json:"dhcpd_unifi_controller,omitempty"`
Ipv6InterfaceType string `json:"ipv6_interface_type,omitempty"`
AttrHiddenID string `json:"attr_hidden_id,omitempty"`
AttrNoDelete bool `json:"attr_no_delete,omitempty"`
UpnpLanEnabled bool `json:"upnp_lan_enabled,omitempty"`
} `json:"network_table"`
NextHeartbeatAt float64 `json:"next_heartbeat_at"`
NumDesktop float64 `json:"num_desktop"`
NumHandheld float64 `json:"num_handheld"`
NumMobile float64 `json:"num_mobile"`
NumSta float64 `json:"num_sta"`
OutdoorModeOverride string `json:"outdoor_mode_override"`
PortTable []struct {
DNS []string `json:"dns,omitempty"`
Enable bool `json:"enable"`
FullDuplex bool `json:"full_duplex"`
Gateway string `json:"gateway,omitempty"`
Ifname string `json:"ifname"`
IP string `json:"ip"`
Mac string `json:"mac"`
Name string `json:"name"`
Netmask string `json:"netmask"`
RxBytes float64 `json:"rx_bytes"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Up bool `json:"up"`
} `json:"port_table"`
Rollupgrade bool `json:"rollupgrade"`
RxBytes float64 `json:"rx_bytes"`
Serial string `json:"serial"`
SiteID string `json:"site_id"`
SpeedtestStatus struct {
Latency float64 `json:"latency"`
Rundate float64 `json:"rundate"`
Runtime float64 `json:"runtime"`
StatusDownload float64 `json:"status_download"`
StatusPing float64 `json:"status_ping"`
StatusSummary float64 `json:"status_summary"`
StatusUpload float64 `json:"status_upload"`
XputDownload float64 `json:"xput_download"`
XputUpload float64 `json:"xput_upload"`
} `json:"speedtest-status"`
SpeedtestStatusSaved bool `json:"speedtest-status-saved"`
Stat struct {
Datetime string `json:"datetime"`
Duration float64 `json:"duration"`
Gw string `json:"gw"`
LanRxBytes float64 `json:"lan-rx_bytes"`
LanRxPackets float64 `json:"lan-rx_packets"`
LanTxBytes float64 `json:"lan-tx_bytes"`
LanTxPackets float64 `json:"lan-tx_packets"`
O string `json:"o"`
Oid string `json:"oid"`
SiteID string `json:"site_id"`
Time float64 `json:"time"`
WanRxBytes float64 `json:"wan-rx_bytes"`
WanRxDropped float64 `json:"wan-rx_dropped"`
WanRxPackets float64 `json:"wan-rx_packets"`
WanTxBytes float64 `json:"wan-tx_bytes"`
WanTxPackets float64 `json:"wan-tx_packets"`
} `json:"stat"`
State float64 `json:"state"`
SysStats struct {
Loadavg1 float64 `json:"loadavg_1,string"`
Loadavg15 float64 `json:"loadavg_15,string"`
Loadavg5 float64 `json:"loadavg_5,string"`
MemBuffer float64 `json:"mem_buffer"`
MemTotal float64 `json:"mem_total"`
MemUsed float64 `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU float64 `json:"cpu,string"`
Mem float64 `json:"mem,string"`
Uptime float64 `json:"uptime,string"`
} `json:"system-stats"`
TxBytes float64 `json:"tx_bytes"`
Type string `json:"type"`
Upgradable bool `json:"upgradable"`
Uplink struct {
BytesR float64 `json:"bytes-r"`
Drops float64 `json:"drops"`
Enable bool `json:"enable"`
FullDuplex bool `json:"full_duplex"`
Gateways []string `json:"gateways"`
IP string `json:"ip"`
Latency float64 `json:"latency"`
Mac string `json:"mac"`
MaxSpeed float64 `json:"max_speed"`
Name string `json:"name"`
Nameservers []string `json:"nameservers"`
Netmask string `json:"netmask"`
NumPort float64 `json:"num_port"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
SpeedtestLastrun float64 `json:"speedtest_lastrun"`
SpeedtestPing float64 `json:"speedtest_ping"`
SpeedtestStatus string `json:"speedtest_status"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
Uptime float64 `json:"uptime"`
XputDown float64 `json:"xput_down"`
XputUp float64 `json:"xput_up"`
} `json:"uplink"`
Uptime float64 `json:"uptime"`
UserNumSta float64 `json:"user-num_sta"`
UsgCaps float64 `json:"usg_caps"`
Version string `json:"version"`
VersionIncompatible bool `json:"version_incompatible"`
Wan1 struct {
BytesR float64 `json:"bytes-r"`
DNS []string `json:"dns"`
Enable bool `json:"enable"`
FullDuplex bool `json:"full_duplex"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
IP string `json:"ip"`
Mac string `json:"mac"`
MaxSpeed float64 `json:"max_speed"`
Name string `json:"name"`
Netmask string `json:"netmask"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
} `json:"wan1"`
Wan2 struct {
BytesR float64 `json:"bytes-r"`
DNS []string `json:"dns"`
Enable bool `json:"enable"`
FullDuplex bool `json:"full_duplex"`
Gateway string `json:"gateway"`
Ifname string `json:"ifname"`
IP string `json:"ip"`
Mac string `json:"mac"`
MaxSpeed float64 `json:"max_speed"`
Name string `json:"name"`
Netmask string `json:"netmask"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
} `json:"wan2"`
}

View File

@ -1,118 +0,0 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Points generates a device's datapoints for InfluxDB.
func (u USW) Points() ([]*influx.Point, error) {
var points []*influx.Point
tags := map[string]string{
"id": u.ID,
"mac": u.Mac,
"device_type": u.Stat.O,
"device_oid": u.Stat.Oid,
"site_id": u.SiteID,
"name": u.Name,
"addopted": strconv.FormatBool(u.Adopted),
"adopt_ip": u.AdoptIP,
"adopt_url": u.AdoptURL,
"cfgversion": u.Cfgversion,
"config_network_ip": u.ConfigNetwork.IP,
"config_network_type": u.ConfigNetwork.Type,
"connect_request_ip": u.ConnectRequestIP,
"connect_request_port": u.ConnectRequestPort,
"default": strconv.FormatBool(u.Default),
"device_id": u.DeviceID,
"discovered_via": u.DiscoveredVia,
"inform_ip": u.InformIP,
"last_uplink_mac": u.LastUplink.UplinkMac,
"known_cfgversion": u.KnownCfgversion,
"led_override": u.LedOverride,
"locating": strconv.FormatBool(u.Locating),
"model": u.Model,
"outdoor_mode_override": u.OutdoorModeOverride,
"serial": u.Serial,
"type": u.Type,
"version_incompatible": strconv.FormatBool(u.VersionIncompatible),
"dot1x_portctrl_enabled": strconv.FormatBool(u.Dot1XPortctrlEnabled),
"flowctrl_enabled": strconv.FormatBool(u.FlowctrlEnabled),
"has_fan": strconv.FormatBool(u.HasFan),
"has_temperature": strconv.FormatBool(u.HasTemperature),
"jumboframe_enabled": strconv.FormatBool(u.JumboframeEnabled),
"stp_priority": u.StpPriority,
"stp_version": u.StpVersion,
}
fields := map[string]interface{}{
"fw_caps": u.FwCaps,
"guest-num_sta": u.GuestNumSta,
"ip": u.IP,
"bytes": u.Bytes,
"fan_level": u.FanLevel,
"general_temperature": u.GeneralTemperature,
"last_seen": u.LastSeen,
"license_state": u.LicenseState,
"overheating": u.Overheating,
"rx_bytes": u.RxBytes,
"tx_bytes": u.TxBytes,
"uptime": u.Uptime,
"considered_lost_at": u.ConsideredLostAt,
"next_heartbeat_at": u.NextHeartbeatAt,
"roll_upgrade": u.Rollupgrade,
"state": u.State,
"upgradable": u.Upgradable,
"user-num_sta": u.UserNumSta,
"version": u.Version,
"loadavg_1": u.SysStats.Loadavg1,
"loadavg_5": u.SysStats.Loadavg5,
"loadavg_15": u.SysStats.Loadavg15,
"mem_buffer": u.SysStats.MemBuffer,
"mem_used": u.SysStats.MemUsed,
"mem_total": u.SysStats.MemTotal,
"cpu": u.SystemStats.CPU,
"mem": u.SystemStats.Mem,
"system_uptime": u.SystemStats.Uptime,
"stat_bytes": u.Stat.Bytes,
"stat_duration": u.Stat.Duration,
"stat_guest-rx_bytes": u.Stat.RxBytes,
"stat_guest-rx_crypts": u.Stat.RxCrypts,
"stat_guest-rx_dropped": u.Stat.RxDropped,
"stat_guest-rx_errors": u.Stat.RxErrors,
"stat_guest-rx_frags": u.Stat.RxFrags,
"stat_guest-rx_packets": u.Stat.RxPackets,
"stat_guest-tx_bytes": u.Stat.TxBytes,
"stat_guest-tx_dropped": u.Stat.TxDropped,
"stat_guest-tx_errors": u.Stat.TxErrors,
"stat_guest-tx_packets": u.Stat.TxPackets,
"stat_guest-tx_retries": u.Stat.TxRetries,
"stat_port_1-rx_broadcast": u.Stat.Port1RxBroadcast,
"stat_port_1-rx_bytes": u.Stat.Port1RxBytes,
"stat_port_1-rx_multicast": u.Stat.Port1RxMulticast,
"stat_port_1-rx_packets": u.Stat.Port1RxPackets,
"stat_port_1-tx_broadcast": u.Stat.Port1TxBroadcast,
"stat_port_1-tx_bytes": u.Stat.Port1TxBytes,
"stat_port_1-tx_multicast": u.Stat.Port1TxMulticast,
"stat_port_1-tx_packets": u.Stat.Port1TxPackets,
"stat_rx_bytes": u.Stat.RxBytes,
"stat_rx_crypts": u.Stat.RxCrypts,
"stat_rx_dropped": u.Stat.RxDropped,
"stat_rx_errors": u.Stat.RxErrors,
"stat_rx_frags": u.Stat.RxFrags,
"stat_rx_packets": u.Stat.TxPackets,
"stat_tx_bytes": u.Stat.TxBytes,
"stat_tx_dropped": u.Stat.TxDropped,
"stat_tx_errors": u.Stat.TxErrors,
"stat_tx_packets": u.Stat.TxPackets,
"stat_tx_retries": u.Stat.TxRetries,
"uplink_depth": strconv.FormatFloat(u.UplinkDepth, 'f', 6, 64),
// Add the port stats too.
}
pt, err := influx.NewPoint("usw", tags, fields, time.Now())
if err == nil {
points = append(points, pt)
}
return points, err
}

View File

@ -1,415 +0,0 @@
package unidev
// USW is a Unifi Switch
type USW struct {
ID string `json:"_id"`
UUptime float64 `json:"_uptime"`
AdoptIP string `json:"adopt_ip"`
AdoptURL string `json:"adopt_url"`
Adopted bool `json:"adopted"`
BoardRev float64 `json:"board_rev"`
Bytes float64 `json:"bytes"`
Cfgversion string `json:"cfgversion"`
ConfigNetwork struct {
IP string `json:"ip"`
Type string `json:"type"`
} `json:"config_network"`
ConnectRequestIP string `json:"connect_request_ip"`
ConnectRequestPort string `json:"connect_request_port"`
ConsideredLostAt float64 `json:"considered_lost_at"`
Default bool `json:"default"`
DeviceID string `json:"device_id"`
DhcpServerTable []interface{} `json:"dhcp_server_table"`
DiscoveredVia string `json:"discovered_via"`
Dot1XPortctrlEnabled bool `json:"dot1x_portctrl_enabled"`
DownlinkTable []struct {
FullDuplex bool `json:"full_duplex"`
Mac string `json:"mac"`
PortIdx float64 `json:"port_idx"`
Speed float64 `json:"speed"`
} `json:"downlink_table"`
EthernetTable []struct {
Mac string `json:"mac"`
Name string `json:"name"`
NumPort float64 `json:"num_port,omitempty"`
} `json:"ethernet_table"`
FanLevel float64 `json:"fan_level"`
FlowctrlEnabled bool `json:"flowctrl_enabled"`
FwCaps float64 `json:"fw_caps"`
GeneralTemperature float64 `json:"general_temperature"`
GuestNumSta float64 `json:"guest-num_sta"`
HasFan bool `json:"has_fan"`
HasTemperature bool `json:"has_temperature"`
InformIP string `json:"inform_ip"`
InformURL string `json:"inform_url"`
IP string `json:"ip"`
JumboframeEnabled bool `json:"jumboframe_enabled"`
KnownCfgversion string `json:"known_cfgversion"`
LastSeen float64 `json:"last_seen"`
LastUplink struct {
UplinkMac string `json:"uplink_mac"`
} `json:"last_uplink"`
LedOverride string `json:"led_override"`
LicenseState string `json:"license_state"`
Locating bool `json:"locating"`
Mac string `json:"mac"`
Model string `json:"model"`
Name string `json:"name"`
NextHeartbeatAt float64 `json:"next_heartbeat_at"`
NumSta float64 `json:"num_sta"`
OutdoorModeOverride string `json:"outdoor_mode_override"`
Overheating bool `json:"overheating"`
PortOverrides []struct {
Name string `json:"name,omitempty"`
PoeMode string `json:"poe_mode,omitempty"`
PortIdx float64 `json:"port_idx"`
PortconfID string `json:"portconf_id"`
} `json:"port_overrides"`
PortTable []struct {
AggregatedBy bool `json:"aggregated_by"`
Autoneg bool `json:"autoneg"`
BytesR float64 `json:"bytes-r"`
Dot1XMode string `json:"dot1x_mode"`
Dot1XStatus string `json:"dot1x_status"`
Enable bool `json:"enable"`
FlowctrlRx bool `json:"flowctrl_rx"`
FlowctrlTx bool `json:"flowctrl_tx"`
FullDuplex bool `json:"full_duplex"`
IsUplink bool `json:"is_uplink"`
Jumbo bool `json:"jumbo"`
LldpTable []interface{} `json:"lldp_table"`
Masked bool `json:"masked"`
Media string `json:"media"`
Name string `json:"name"`
OpMode string `json:"op_mode"`
PoeCaps float64 `json:"poe_caps"`
PoeClass string `json:"poe_class,omitempty"`
PoeCurrent string `json:"poe_current,omitempty"`
PoeEnable bool `json:"poe_enable,omitempty"`
PoeGood bool `json:"poe_good,omitempty"`
PoeMode string `json:"poe_mode,omitempty"`
PoePower string `json:"poe_power,omitempty"`
PoeVoltage string `json:"poe_voltage,omitempty"`
PortIdx float64 `json:"port_idx"`
PortPoe bool `json:"port_poe"`
PortconfID string `json:"portconf_id"`
RxBroadcast float64 `json:"rx_broadcast"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
StpPathcost float64 `json:"stp_pathcost"`
StpState string `json:"stp_state"`
TxBroadcast float64 `json:"tx_broadcast"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxMulticast float64 `json:"tx_multicast"`
TxPackets float64 `json:"tx_packets"`
Up bool `json:"up"`
SfpFound bool `json:"sfp_found,omitempty"`
} `json:"port_table"`
Rollupgrade bool `json:"rollupgrade"`
RxBytes float64 `json:"rx_bytes"`
Serial string `json:"serial"`
SiteID string `json:"site_id"`
SSHSessionTable []interface{} `json:"ssh_session_table"`
Stat struct {
Bytes float64 `json:"bytes"`
Datetime string `json:"datetime"`
Duration float64 `json:"duration"`
O string `json:"o"`
Oid string `json:"oid"`
Port1RxBroadcast float64 `json:"port_1-rx_broadcast"`
Port1RxBytes float64 `json:"port_1-rx_bytes"`
Port1RxDropped float64 `json:"port_1-rx_dropped"`
Port1RxMulticast float64 `json:"port_1-rx_multicast"`
Port1RxPackets float64 `json:"port_1-rx_packets"`
Port1TxBroadcast float64 `json:"port_1-tx_broadcast"`
Port1TxBytes float64 `json:"port_1-tx_bytes"`
Port1TxMulticast float64 `json:"port_1-tx_multicast"`
Port1TxPackets float64 `json:"port_1-tx_packets"`
Port2RxBroadcast float64 `json:"port_2-rx_broadcast"`
Port2RxBytes float64 `json:"port_2-rx_bytes"`
Port2RxDropped float64 `json:"port_2-rx_dropped"`
Port2RxMulticast float64 `json:"port_2-rx_multicast"`
Port2RxPackets float64 `json:"port_2-rx_packets"`
Port2TxBroadcast float64 `json:"port_2-tx_broadcast"`
Port2TxBytes float64 `json:"port_2-tx_bytes"`
Port2TxMulticast float64 `json:"port_2-tx_multicast"`
Port2TxPackets float64 `json:"port_2-tx_packets"`
Port3RxBroadcast float64 `json:"port_3-rx_broadcast"`
Port3RxBytes float64 `json:"port_3-rx_bytes"`
Port3RxDropped float64 `json:"port_3-rx_dropped"`
Port3RxMulticast float64 `json:"port_3-rx_multicast"`
Port3RxPackets float64 `json:"port_3-rx_packets"`
Port3TxBroadcast float64 `json:"port_3-tx_broadcast"`
Port3TxBytes float64 `json:"port_3-tx_bytes"`
Port3TxMulticast float64 `json:"port_3-tx_multicast"`
Port3TxPackets float64 `json:"port_3-tx_packets"`
Port4RxBroadcast float64 `json:"port_4-rx_broadcast"`
Port4RxBytes float64 `json:"port_4-rx_bytes"`
Port4RxDropped float64 `json:"port_4-rx_dropped"`
Port4RxMulticast float64 `json:"port_4-rx_multicast"`
Port4RxPackets float64 `json:"port_4-rx_packets"`
Port4TxBroadcast float64 `json:"port_4-tx_broadcast"`
Port4TxBytes float64 `json:"port_4-tx_bytes"`
Port4TxMulticast float64 `json:"port_4-tx_multicast"`
Port4TxPackets float64 `json:"port_4-tx_packets"`
Port5RxBroadcast float64 `json:"port_5-rx_broadcast"`
Port5RxBytes float64 `json:"port_5-rx_bytes"`
Port5RxDropped float64 `json:"port_5-rx_dropped"`
Port5RxMulticast float64 `json:"port_5-rx_multicast"`
Port5RxPackets float64 `json:"port_5-rx_packets"`
Port5TxBroadcast float64 `json:"port_5-tx_broadcast"`
Port5TxBytes float64 `json:"port_5-tx_bytes"`
Port5TxMulticast float64 `json:"port_5-tx_multicast"`
Port5TxPackets float64 `json:"port_5-tx_packets"`
Port6RxBroadcast float64 `json:"port_6-rx_broadcast"`
Port6RxBytes float64 `json:"port_6-rx_bytes"`
Port6RxDropped float64 `json:"port_6-rx_dropped"`
Port6RxMulticast float64 `json:"port_6-rx_multicast"`
Port6RxPackets float64 `json:"port_6-rx_packets"`
Port6TxBroadcast float64 `json:"port_6-tx_broadcast"`
Port6TxBytes float64 `json:"port_6-tx_bytes"`
Port6TxMulticast float64 `json:"port_6-tx_multicast"`
Port6TxPackets float64 `json:"port_6-tx_packets"`
Port7RxBroadcast float64 `json:"port_7-rx_broadcast"`
Port7RxBytes float64 `json:"port_7-rx_bytes"`
Port7RxDropped float64 `json:"port_7-rx_dropped"`
Port7RxMulticast float64 `json:"port_7-rx_multicast"`
Port7RxPackets float64 `json:"port_7-rx_packets"`
Port7TxBroadcast float64 `json:"port_7-tx_broadcast"`
Port7TxBytes float64 `json:"port_7-tx_bytes"`
Port7TxMulticast float64 `json:"port_7-tx_multicast"`
Port7TxPackets float64 `json:"port_7-tx_packets"`
Port8RxBroadcast float64 `json:"port_8-rx_broadcast"`
Port8RxBytes float64 `json:"port_8-rx_bytes"`
Port8RxDropped float64 `json:"port_8-rx_dropped"`
Port8RxMulticast float64 `json:"port_8-rx_multicast"`
Port8RxPackets float64 `json:"port_8-rx_packets"`
Port8TxBroadcast float64 `json:"port_8-tx_broadcast"`
Port8TxBytes float64 `json:"port_8-tx_bytes"`
Port8TxMulticast float64 `json:"port_8-tx_multicast"`
Port8TxPackets float64 `json:"port_8-tx_packets"`
Port9RxBroadcast float64 `json:"port_9-rx_broadcast"`
Port9RxBytes float64 `json:"port_9-rx_bytes"`
Port9RxDropped float64 `json:"port_9-rx_dropped"`
Port9RxMulticast float64 `json:"port_9-rx_multicast"`
Port9RxPackets float64 `json:"port_9-rx_packets"`
Port9TxBroadcast float64 `json:"port_9-tx_broadcast"`
Port9TxBytes float64 `json:"port_9-tx_bytes"`
Port9TxMulticast float64 `json:"port_9-tx_multicast"`
Port9TxPackets float64 `json:"port_9-tx_packets"`
Port10RxBroadcast float64 `json:"port_10-rx_broadcast"`
Port10RxBytes float64 `json:"port_10-rx_bytes"`
Port10RxDropped float64 `json:"port_10-rx_dropped"`
Port10RxMulticast float64 `json:"port_10-rx_multicast"`
Port10RxPackets float64 `json:"port_10-rx_packets"`
Port10TxBroadcast float64 `json:"port_10-tx_broadcast"`
Port10TxBytes float64 `json:"port_10-tx_bytes"`
Port10TxMulticast float64 `json:"port_10-tx_multicast"`
Port10TxPackets float64 `json:"port_10-tx_packets"`
Port11RxBroadcast float64 `json:"port_11-rx_broadcast"`
Port11RxBytes float64 `json:"port_11-rx_bytes"`
Port11RxDropped float64 `json:"port_11-rx_dropped"`
Port11RxMulticast float64 `json:"port_11-rx_multicast"`
Port11RxPackets float64 `json:"port_11-rx_packets"`
Port11TxBroadcast float64 `json:"port_11-tx_broadcast"`
Port11TxBytes float64 `json:"port_11-tx_bytes"`
Port11TxMulticast float64 `json:"port_11-tx_multicast"`
Port11TxPackets float64 `json:"port_11-tx_packets"`
Port12RxBroadcast float64 `json:"port_12-rx_broadcast"`
Port12RxBytes float64 `json:"port_12-rx_bytes"`
Port12RxDropped float64 `json:"port_12-rx_dropped"`
Port12RxMulticast float64 `json:"port_12-rx_multicast"`
Port12RxPackets float64 `json:"port_12-rx_packets"`
Port12TxBroadcast float64 `json:"port_12-tx_broadcast"`
Port12TxBytes float64 `json:"port_12-tx_bytes"`
Port12TxMulticast float64 `json:"port_12-tx_multicast"`
Port12TxPackets float64 `json:"port_12-tx_packets"`
Port13RxBroadcast float64 `json:"port_13-rx_broadcast"`
Port13RxBytes float64 `json:"port_13-rx_bytes"`
Port13RxDropped float64 `json:"port_13-rx_dropped"`
Port13RxMulticast float64 `json:"port_13-rx_multicast"`
Port13RxPackets float64 `json:"port_13-rx_packets"`
Port13TxBroadcast float64 `json:"port_13-tx_broadcast"`
Port13TxBytes float64 `json:"port_13-tx_bytes"`
Port13TxMulticast float64 `json:"port_13-tx_multicast"`
Port13TxPackets float64 `json:"port_13-tx_packets"`
Port14RxBroadcast float64 `json:"port_14-rx_broadcast"`
Port14RxBytes float64 `json:"port_14-rx_bytes"`
Port14RxDropped float64 `json:"port_14-rx_dropped"`
Port14RxMulticast float64 `json:"port_14-rx_multicast"`
Port14RxPackets float64 `json:"port_14-rx_packets"`
Port14TxBroadcast float64 `json:"port_14-tx_broadcast"`
Port14TxBytes float64 `json:"port_14-tx_bytes"`
Port14TxMulticast float64 `json:"port_14-tx_multicast"`
Port14TxPackets float64 `json:"port_14-tx_packets"`
Port15RxBroadcast float64 `json:"port_15-rx_broadcast"`
Port15RxBytes float64 `json:"port_15-rx_bytes"`
Port15RxDropped float64 `json:"port_15-rx_dropped"`
Port15RxMulticast float64 `json:"port_15-rx_multicast"`
Port15RxPackets float64 `json:"port_15-rx_packets"`
Port15TxBroadcast float64 `json:"port_15-tx_broadcast"`
Port15TxBytes float64 `json:"port_15-tx_bytes"`
Port15TxMulticast float64 `json:"port_15-tx_multicast"`
Port15TxPackets float64 `json:"port_15-tx_packets"`
Port16RxBroadcast float64 `json:"port_16-rx_broadcast"`
Port16RxBytes float64 `json:"port_16-rx_bytes"`
Port16RxDropped float64 `json:"port_16-rx_dropped"`
Port16RxMulticast float64 `json:"port_16-rx_multicast"`
Port16RxPackets float64 `json:"port_16-rx_packets"`
Port16TxBroadcast float64 `json:"port_16-tx_broadcast"`
Port16TxBytes float64 `json:"port_16-tx_bytes"`
Port16TxMulticast float64 `json:"port_16-tx_multicast"`
Port16TxPackets float64 `json:"port_16-tx_packets"`
Port17RxBroadcast float64 `json:"port_17-rx_broadcast"`
Port17RxBytes float64 `json:"port_17-rx_bytes"`
Port17RxDropped float64 `json:"port_17-rx_dropped"`
Port17RxMulticast float64 `json:"port_17-rx_multicast"`
Port17RxPackets float64 `json:"port_17-rx_packets"`
Port17TxBroadcast float64 `json:"port_17-tx_broadcast"`
Port17TxBytes float64 `json:"port_17-tx_bytes"`
Port17TxMulticast float64 `json:"port_17-tx_multicast"`
Port17TxPackets float64 `json:"port_17-tx_packets"`
Port18RxBroadcast float64 `json:"port_18-rx_broadcast"`
Port18RxBytes float64 `json:"port_18-rx_bytes"`
Port18RxDropped float64 `json:"port_18-rx_dropped"`
Port18RxMulticast float64 `json:"port_18-rx_multicast"`
Port18RxPackets float64 `json:"port_18-rx_packets"`
Port18TxBroadcast float64 `json:"port_18-tx_broadcast"`
Port18TxBytes float64 `json:"port_18-tx_bytes"`
Port18TxMulticast float64 `json:"port_18-tx_multicast"`
Port18TxPackets float64 `json:"port_18-tx_packets"`
Port19RxBroadcast float64 `json:"port_19-rx_broadcast"`
Port19RxBytes float64 `json:"port_19-rx_bytes"`
Port19RxDropped float64 `json:"port_19-rx_dropped"`
Port19RxMulticast float64 `json:"port_19-rx_multicast"`
Port19RxPackets float64 `json:"port_19-rx_packets"`
Port19TxBroadcast float64 `json:"port_19-tx_broadcast"`
Port19TxBytes float64 `json:"port_19-tx_bytes"`
Port19TxMulticast float64 `json:"port_19-tx_multicast"`
Port19TxPackets float64 `json:"port_19-tx_packets"`
Port20RxBroadcast float64 `json:"port_20-rx_broadcast"`
Port20RxBytes float64 `json:"port_20-rx_bytes"`
Port20RxDropped float64 `json:"port_20-rx_dropped"`
Port20RxMulticast float64 `json:"port_20-rx_multicast"`
Port20RxPackets float64 `json:"port_20-rx_packets"`
Port20TxBroadcast float64 `json:"port_20-tx_broadcast"`
Port20TxBytes float64 `json:"port_20-tx_bytes"`
Port20TxMulticast float64 `json:"port_20-tx_multicast"`
Port20TxPackets float64 `json:"port_20-tx_packets"`
Port21RxBroadcast float64 `json:"port_21-rx_broadcast"`
Port21RxBytes float64 `json:"port_21-rx_bytes"`
Port21RxDropped float64 `json:"port_21-rx_dropped"`
Port21RxMulticast float64 `json:"port_21-rx_multicast"`
Port21RxPackets float64 `json:"port_21-rx_packets"`
Port21TxBroadcast float64 `json:"port_21-tx_broadcast"`
Port21TxBytes float64 `json:"port_21-tx_bytes"`
Port21TxMulticast float64 `json:"port_21-tx_multicast"`
Port21TxPackets float64 `json:"port_21-tx_packets"`
Port22RxBroadcast float64 `json:"port_22-rx_broadcast"`
Port22RxBytes float64 `json:"port_22-rx_bytes"`
Port22RxDropped float64 `json:"port_22-rx_dropped"`
Port22RxMulticast float64 `json:"port_22-rx_multicast"`
Port22RxPackets float64 `json:"port_22-rx_packets"`
Port22TxBroadcast float64 `json:"port_22-tx_broadcast"`
Port22TxBytes float64 `json:"port_22-tx_bytes"`
Port22TxMulticast float64 `json:"port_22-tx_multicast"`
Port22TxPackets float64 `json:"port_22-tx_packets"`
Port23RxBroadcast float64 `json:"port_23-rx_broadcast"`
Port23RxBytes float64 `json:"port_23-rx_bytes"`
Port23RxDropped float64 `json:"port_23-rx_dropped"`
Port23RxMulticast float64 `json:"port_23-rx_multicast"`
Port23RxPackets float64 `json:"port_23-rx_packets"`
Port23TxBroadcast float64 `json:"port_23-tx_broadcast"`
Port23TxBytes float64 `json:"port_23-tx_bytes"`
Port23TxMulticast float64 `json:"port_23-tx_multicast"`
Port23TxPackets float64 `json:"port_23-tx_packets"`
Port24RxBroadcast float64 `json:"port_24-rx_broadcast"`
Port24RxBytes float64 `json:"port_24-rx_bytes"`
Port24RxDropped float64 `json:"port_24-rx_dropped"`
Port24RxMulticast float64 `json:"port_24-rx_multicast"`
Port24RxPackets float64 `json:"port_24-rx_packets"`
Port24TxBroadcast float64 `json:"port_24-tx_broadcast"`
Port24TxBytes float64 `json:"port_24-tx_bytes"`
Port24TxMulticast float64 `json:"port_24-tx_multicast"`
Port24TxPackets float64 `json:"port_24-tx_packets"`
// Have a 48 port switch? How 'bout a pull request. :D
RxBroadcast float64 `json:"rx_broadcast"`
RxBytes float64 `json:"rx_bytes"`
RxCrypts float64 `json:"rx_crypts"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxFrags float64 `json:"rx_frags"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
SiteID string `json:"site_id"`
Sw string `json:"sw"`
Time float64 `json:"time"`
TxBroadcast float64 `json:"tx_broadcast"`
TxBytes float64 `json:"tx_bytes"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxMulticast float64 `json:"tx_multicast"`
TxPackets float64 `json:"tx_packets"`
TxRetries float64 `json:"tx_retries"`
} `json:"stat"`
State float64 `json:"state"`
StpPriority string `json:"stp_priority"`
StpVersion string `json:"stp_version"`
SysStats struct {
Loadavg1 float64 `json:"loadavg_1,string"`
Loadavg15 float64 `json:"loadavg_15,string"`
Loadavg5 float64 `json:"loadavg_5,string"`
MemBuffer float64 `json:"mem_buffer"`
MemTotal float64 `json:"mem_total"`
MemUsed float64 `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU float64 `json:"cpu,string"`
Mem float64 `json:"mem,string"`
Uptime float64 `json:"uptime,string"`
} `json:"system-stats"`
TxBytes float64 `json:"tx_bytes"`
Type string `json:"type"`
Upgradable bool `json:"upgradable"`
Uplink struct {
FullDuplex bool `json:"full_duplex"`
IP string `json:"ip"`
Mac string `json:"mac"`
MaxSpeed float64 `json:"max_speed"`
Media string `json:"media"`
Name string `json:"name"`
Netmask string `json:"netmask"`
NumPort float64 `json:"num_port"`
PortIdx float64 `json:"port_idx"`
RxBytes float64 `json:"rx_bytes"`
RxBytesR float64 `json:"rx_bytes-r"`
RxDropped float64 `json:"rx_dropped"`
RxErrors float64 `json:"rx_errors"`
RxMulticast float64 `json:"rx_multicast"`
RxPackets float64 `json:"rx_packets"`
Speed float64 `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR float64 `json:"tx_bytes-r"`
TxDropped float64 `json:"tx_dropped"`
TxErrors float64 `json:"tx_errors"`
TxPackets float64 `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
UplinkMac string `json:"uplink_mac"`
} `json:"uplink"`
UplinkDepth float64 `json:"uplink_depth"`
Uptime float64 `json:"uptime"`
UserNumSta float64 `json:"user-num_sta"`
Version string `json:"version"`
VersionIncompatible bool `json:"version_incompatible"`
}