Offload Unifi work to dedicated module.

This commit is contained in:
DN2 2018-04-23 03:49:00 -07:00
parent d1c6e87276
commit f752a5076a
17 changed files with 1815 additions and 1042 deletions

2
Godeps/Godeps.json generated
View File

@ -1,5 +1,5 @@
{ {
"ImportPath": "github.com/davidnewhall/unifi", "ImportPath": "github.com/davidnewhall/unifi-poller",
"GoVersion": "go1.10", "GoVersion": "go1.10",
"GodepVersion": "v79", "GodepVersion": "v79",
"Packages": [ "Packages": [

View File

@ -1,4 +1,5 @@
Copyright (c) 2016 Garrett Bjerkhoel Copyright (c) 2016 Garrett Bjerkhoel
Copyright (c) 2018 David Newhall II
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the

View File

@ -1,5 +1,5 @@
PACKAGES=`find ./cmd -mindepth 1 -maxdepth 1 -type d` PACKAGES=`find ./cmd -mindepth 1 -maxdepth 1 -type d`
LIBRARYS= LIBRARYS=./unidev
all: clean man build all: clean man build

View File

@ -1,219 +0,0 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// ClientResponse marshalls the payload from the controller.
type ClientResponse struct {
Clients []Client `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
// DpiStat is for deep packet inspection stats.
// Does not seem to exist in Unifi 5.7.20.
type DpiStat struct {
App int64
Cat int64
RxBytes int64
RxPackets int64
TxBytes int64
TxPackets int64
}
// Client defines all the data a connected-network client contains.
type Client 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 []DpiStat `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"`
}
// GetUnifiClients returns a response full of clients' data from the Unifi Controller.
func (c *Config) GetUnifiClients() ([]Client, error) {
response := &ClientResponse{}
if req, err := c.uniRequest(ClientPath, ""); err != nil {
return nil, err
} else if resp, err := c.uniClient.Do(req); err != nil {
return nil, err
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, err
} else if err = json.Unmarshal(body, response); err != nil {
return nil, err
} else if err = resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
return response.Clients, nil
}
// Point generates a client's datapoint for InfluxDB.
func (c Client) Point() (*influx.Point, error) {
if c.Name == "" && c.Hostname != "" {
c.Name = c.Hostname
} else if c.Hostname == "" && c.Name != "" {
c.Hostname = c.Name
} else if c.Hostname == "" && c.Name == "" {
c.Hostname = "-no-name-"
c.Name = "-no-name-"
}
tags := map[string]string{
"id": c.ID,
"mac": c.Mac,
"user_id": c.UserID,
"site_id": c.SiteID,
"network_id": c.NetworkID,
"usergroup_id": c.UserGroupID,
"ap_mac": c.ApMac,
"gw_mac": c.GwMac,
"sw_mac": c.SwMac,
"oui": c.Oui,
"radio_name": c.RadioName,
"radio": c.Radio,
"radio_proto": c.RadioProto,
"name": c.Name,
"fixed_ip": c.FixedIP,
"sw_port": strconv.Itoa(c.SwPort),
"os_class": strconv.Itoa(c.OsClass),
"os_name": strconv.Itoa(c.OsName),
"dev_cat": strconv.Itoa(c.DevCat),
"dev_id": strconv.Itoa(c.DevID),
"dev_family": strconv.Itoa(c.DevFamily),
"authorized": strconv.FormatBool(c.Authorized),
"is_11r": strconv.FormatBool(c.Is11R),
"is_wired": strconv.FormatBool(c.IsWired),
"is_guest": strconv.FormatBool(c.IsGuest),
"is_guest_by_uap": strconv.FormatBool(c.IsGuestByUAP),
"is_guest_by_ugw": strconv.FormatBool(c.IsGuestByUGW),
"is_guest_by_usw": strconv.FormatBool(c.IsGuestByUSW),
"noted": strconv.FormatBool(c.Noted),
"powersave_enabled": strconv.FormatBool(c.PowersaveEnabled),
"qos_policy_applied": strconv.FormatBool(c.QosPolicyApplied),
"use_fixedip": strconv.FormatBool(c.UseFixedIP),
"channel": strconv.Itoa(c.Channel),
"vlan": strconv.Itoa(c.Vlan),
}
fields := map[string]interface{}{
"ip": c.IP,
"essid": c.Essid,
"bssid": c.Bssid,
"hostname": c.Hostname,
"dpi_stats_last_updated": c.DpiStatsLastUpdated,
"last_seen_by_uap": c.LastSeenByUAP,
"last_seen_by_ugw": c.LastSeenByUGW,
"last_seen_by_usw": c.LastSeenByUSW,
"uptime_by_uap": c.UptimeByUAP,
"uptime_by_ugw": c.UptimeByUGW,
"uptime_by_usw": c.UptimeByUSW,
"assoc_time": c.AssocTime,
"bytes_r": c.BytesR,
"ccq": c.Ccq,
"first_seen": c.FirstSeen,
"idle_time": c.IdleTime,
"last_seen": c.LastSeen,
"latest_assoc_time": c.LatestAssocTime,
"network": c.Network,
"noise": c.Noise,
"note": c.Note,
"roam_count": c.RoamCount,
"rssi": c.Rssi,
"rx_bytes": c.RxBytes,
"rx_bytes_r": c.RxBytesR,
"rx_packets": c.RxPackets,
"rx_rate": c.RxRate,
"signal": c.Signal,
"tx_bytes": c.TxBytes,
"tx_bytes_r": c.TxBytesR,
"tx_packets": c.TxPackets,
"tx_power": c.TxPower,
"tx_rate": c.TxRate,
"uptime": c.Uptime,
"wired-rx_bytes": c.WiredRxBytes,
"wired-rx_bytes-r": c.WiredRxBytesR,
"wired-rx_packets": c.WiredRxPackets,
"wired-tx_bytes": c.WiredTxBytes,
"wired-tx_bytes-r": c.WiredTxBytesR,
"wired-tx_packets": c.WiredTxPackets,
}
return influx.NewPoint("clients", tags, fields, time.Now())
}

View File

@ -1,24 +1,14 @@
package main package main
import ( import "time"
"net/http"
"time"
)
// Version will be injected at build time. // Version will be injected at build time.
var Version = "v0.1" var (
Version = "v0.1"
Debug = false
)
const ( const (
// LoginPath is Unifi Controller Login API Path
LoginPath = "/api/login"
// 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"
// App defaults in case they're missing from the config. // App defaults in case they're missing from the config.
defaultConfFile = "/usr/local/etc/unifi-poller/up.conf" defaultConfFile = "/usr/local/etc/unifi-poller/up.conf"
defaultInterval = 30 * time.Second defaultInterval = 30 * time.Second
@ -40,13 +30,10 @@ type Config struct {
UnifiUser string `json:"unifi_user" toml:"unifi_user" xml:"unifi_user" yaml:"unifi_user"` UnifiUser string `json:"unifi_user" toml:"unifi_user" xml:"unifi_user" yaml:"unifi_user"`
UnifiPass string `json:"unifi_pass" toml:"unifi_pass" xml:"unifi_pass" yaml:"unifi_pass"` UnifiPass string `json:"unifi_pass" toml:"unifi_pass" xml:"unifi_pass" yaml:"unifi_pass"`
UnifiBase string `json:"unifi_url" toml:"unifi_url" xml:"unifi_url" yaml:"unifi_url"` UnifiBase string `json:"unifi_url" toml:"unifi_url" xml:"unifi_url" yaml:"unifi_url"`
uniClient *http.Client
} }
// Dur is used to UnmarshalTOML into a time.Duration value. // Dur is used to UnmarshalTOML into a time.Duration value.
type Dur struct { type Dur struct{ value time.Duration }
value time.Duration
}
// UnmarshalTOML parses a duration type from a config file. // UnmarshalTOML parses a duration type from a config file.
func (v *Dur) UnmarshalTOML(data []byte) error { func (v *Dur) UnmarshalTOML(data []byte) error {

View File

@ -1,740 +0,0 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// DeviceResponse represents the payload from Unifi Controller.
type DeviceResponse struct {
Devices []Device `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
// Device represents all the information a device may contain. oh my..
type Device struct {
// created using https://mholt.github.io/json-to-go
// with data from https://unifi.ctrlr/api/s/default/stat/device
ID string `json:"_id"`
UUptime int `json:"_uptime"`
AdoptIP string `json:"adopt_ip,omitempty"`
AdoptURL string `json:"adopt_url,omitempty"`
Adopted bool `json:"adopted"`
AntennaTable []struct {
ID int `json:"id"`
Name string `json:"name"`
Wifi0Gain int `json:"wifi0_gain"`
Wifi1Gain int `json:"wifi1_gain"`
} `json:"antenna_table,omitempty"`
BandsteeringMode string `json:"bandsteering_mode,omitempty"`
BoardRev int `json:"board_rev,omitempty"`
Bytes float64 `json:"bytes"`
BytesD int `json:"bytes-d,omitempty"`
BytesR int `json:"bytes-r,omitempty"`
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 int `json:"considered_lost_at"`
CountrycodeTable []int `json:"countrycode_table,omitempty"`
Default bool `json:"default,omitempty"`
DeviceID string `json:"device_id"`
DiscoveredVia string `json:"discovered_via,omitempty"`
DownlinkTable []interface{} `json:"downlink_table,omitempty"`
EthernetTable []struct {
Mac string `json:"mac"`
Name string `json:"name"`
NumPort int `json:"num_port"`
} `json:"ethernet_table"`
FwCaps int `json:"fw_caps"`
GuestNumSta int `json:"guest-num_sta"`
GuestToken string `json:"guest_token,omitempty"`
HasEth1 bool `json:"has_eth1,omitempty"`
HasSpeaker bool `json:"has_speaker,omitempty"`
InformIP string `json:"inform_ip"`
InformURL string `json:"inform_url"`
IP string `json:"ip"`
Isolated bool `json:"isolated,omitempty"`
KnownCfgversion string `json:"known_cfgversion"`
LastSeen int `json:"last_seen"`
LastUplink struct {
UplinkMac string `json:"uplink_mac"`
UplinkRemotePort int `json:"uplink_remote_port"`
} `json:"last_uplink,omitempty"`
LedOverride string `json:"led_override"`
Locating bool `json:"locating"`
Mac string `json:"mac"`
Model string `json:"model"`
Name string `json:"name"`
NextHeartbeatAt int `json:"next_heartbeat_at"`
NumSta int `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 int `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 int `json:"age"`
Mac string `json:"mac"`
Static bool `json:"static"`
Uptime int `json:"uptime"`
Vlan int `json:"vlan"`
} `json:"mac_table"`
Masked bool `json:"masked"`
Media string `json:"media"`
Name string `json:"name"`
OpMode string `json:"op_mode"`
PoeCaps int `json:"poe_caps"`
PortDelta struct {
RxBytes int `json:"rx_bytes"`
RxPackets int `json:"rx_packets"`
TimeDelta int `json:"time_delta"`
TxBytes int `json:"tx_bytes"`
TxPackets int `json:"tx_packets"`
} `json:"port_delta"`
PortIdx int `json:"port_idx"`
PortPoe bool `json:"port_poe"`
PortconfID string `json:"portconf_id"`
RxBroadcast int `json:"rx_broadcast"`
RxBytes int64 `json:"rx_bytes"`
RxBytesR int `json:"rx_bytes-r"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxMulticast int `json:"rx_multicast"`
RxPackets int `json:"rx_packets"`
Speed int `json:"speed"`
StpPathcost int `json:"stp_pathcost"`
StpState string `json:"stp_state"`
TxBroadcast int `json:"tx_broadcast"`
TxBytes int64 `json:"tx_bytes"`
TxBytesR int `json:"tx_bytes-r"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxMulticast int `json:"tx_multicast"`
TxPackets int `json:"tx_packets"`
Up bool `json:"up"`
} `json:"port_table"`
RadioTable []struct {
BuiltinAntGain int `json:"builtin_ant_gain"`
BuiltinAntenna bool `json:"builtin_antenna"`
Channel string `json:"channel"`
CurrentAntennaGain int `json:"current_antenna_gain"`
Ht string `json:"ht"`
MaxTxpower int `json:"max_txpower"`
MinRssiEnabled bool `json:"min_rssi_enabled"`
MinTxpower int `json:"min_txpower"`
Name string `json:"name"`
Nss int `json:"nss"`
Radio string `json:"radio"`
RadioCaps int `json:"radio_caps"`
TxPower string `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,omitempty"`
RadioTableStats []struct {
AstBeXmit interface{} `json:"ast_be_xmit"`
AstCst interface{} `json:"ast_cst"`
AstTxto interface{} `json:"ast_txto"`
Channel int `json:"channel"`
CuSelfRx int `json:"cu_self_rx"`
CuSelfTx int `json:"cu_self_tx"`
CuTotal int `json:"cu_total"`
Extchannel int `json:"extchannel"`
Gain int `json:"gain"`
GuestNumSta int `json:"guest-num_sta"`
Name string `json:"name"`
NumSta int `json:"num_sta"`
Radio string `json:"radio"`
State string `json:"state"`
TxPackets float64 `json:"tx_packets"`
TxPower int `json:"tx_power"`
TxRetries int `json:"tx_retries"`
UserNumSta int `json:"user-num_sta"`
} `json:"radio_table_stats,omitempty"`
Rollupgrade bool `json:"rollupgrade"`
RxBytes float64 `json:"rx_bytes"`
RxBytesD float64 `json:"rx_bytes-d,omitempty"`
ScanRadioTable []interface{} `json:"scan_radio_table,omitempty"`
Scanning bool `json:"scanning,omitempty"`
Serial string `json:"serial"`
SiteID string `json:"site_id"`
SpectrumScanning bool `json:"spectrum_scanning,omitempty"`
SSHSessionTable []interface{} `json:"ssh_session_table,omitempty"`
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 int64 `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 string `json:"loadavg_1"`
Loadavg15 string `json:"loadavg_15"`
Loadavg5 string `json:"loadavg_5"`
MemBuffer int `json:"mem_buffer"`
MemTotal int `json:"mem_total"`
MemUsed int `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU string `json:"cpu"`
Mem string `json:"mem"`
Uptime string `json:"uptime"`
} `json:"system-stats"`
TxBytes int64 `json:"tx_bytes"`
TxBytesD int `json:"tx_bytes-d,omitempty"`
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 int `json:"rx_bytes"`
RxBytesR int `json:"rx_bytes-r"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxMulticast int `json:"rx_multicast"`
RxPackets int `json:"rx_packets"`
Speed int `json:"speed"`
TxBytes int64 `json:"tx_bytes"`
TxBytesR int `json:"tx_bytes-r"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxPackets int `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,omitempty"`
Uptime int `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 interface{} `json:"map_id"`
Name string `json:"name"`
NumSta int `json:"num_sta"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
RxBytes int `json:"rx_bytes"`
RxCrypts int `json:"rx_crypts"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxFrags int `json:"rx_frags"`
RxNwids int `json:"rx_nwids"`
RxPackets int `json:"rx_packets"`
SiteID string `json:"site_id"`
State string `json:"state"`
T string `json:"t"`
TxBytes int `json:"tx_bytes"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxLatencyAvg int `json:"tx_latency_avg"`
TxLatencyMax int `json:"tx_latency_max"`
TxLatencyMin int `json:"tx_latency_min"`
TxPackets int `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,omitempty"`
Version string `json:"version"`
VersionIncompatible bool `json:"version_incompatible"`
VwireEnabled bool `json:"vwireEnabled,omitempty"`
VwireTable []interface{} `json:"vwire_table,omitempty"`
VwireVapTable []struct {
Bssid string `json:"bssid"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
State string `json:"state"`
} `json:"vwire_vap_table,omitempty"`
WifiCaps int `json:"wifi_caps,omitempty"`
DhcpServerTable []interface{} `json:"dhcp_server_table,omitempty"`
Dot1XPortctrlEnabled bool `json:"dot1x_portctrl_enabled,omitempty"`
FanLevel int `json:"fan_level,omitempty"`
FlowctrlEnabled bool `json:"flowctrl_enabled,omitempty"`
GeneralTemperature int `json:"general_temperature,omitempty"`
HasFan bool `json:"has_fan,omitempty"`
HasTemperature bool `json:"has_temperature,omitempty"`
JumboframeEnabled bool `json:"jumboframe_enabled,omitempty"`
LicenseState string `json:"license_state,omitempty"`
Overheating bool `json:"overheating,omitempty"`
PortOverrides []struct {
Name string `json:"name,omitempty"`
PoeMode string `json:"poe_mode,omitempty"`
PortIdx int `json:"port_idx"`
PortconfID string `json:"portconf_id"`
} `json:"port_overrides,omitempty"`
StpPriority string `json:"stp_priority,omitempty"`
StpVersion string `json:"stp_version,omitempty"`
UplinkDepth int `json:"uplink_depth,omitempty"`
ConfigNetworkWan struct {
Type string `json:"type"`
} `json:"config_network_wan,omitempty"`
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 int `json:"num_sta"`
Purpose string `json:"purpose"`
RxBytes int `json:"rx_bytes"`
RxPackets int `json:"rx_packets"`
SiteID string `json:"site_id"`
TxBytes int `json:"tx_bytes"`
TxPackets int `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,omitempty"`
NumDesktop int `json:"num_desktop,omitempty"`
NumHandheld int `json:"num_handheld,omitempty"`
NumMobile int `json:"num_mobile,omitempty"`
SpeedtestStatus struct {
Latency int `json:"latency"`
Rundate int `json:"rundate"`
Runtime int `json:"runtime"`
StatusDownload int `json:"status_download"`
StatusPing int `json:"status_ping"`
StatusSummary int `json:"status_summary"`
StatusUpload int `json:"status_upload"`
XputDownload float64 `json:"xput_download"`
XputUpload float64 `json:"xput_upload"`
} `json:"speedtest-status,omitempty"`
SpeedtestStatusSaved bool `json:"speedtest-status-saved,omitempty"`
UsgCaps int `json:"usg_caps,omitempty"`
Wan1 struct {
BytesR int `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 int `json:"max_speed"`
Name string `json:"name"`
Netmask string `json:"netmask"`
RxBytes int64 `json:"rx_bytes"`
RxBytesR int `json:"rx_bytes-r"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxMulticast int `json:"rx_multicast"`
RxPackets int `json:"rx_packets"`
Speed int `json:"speed"`
TxBytes int64 `json:"tx_bytes"`
TxBytesR int `json:"tx_bytes-r"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxPackets int `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
} `json:"wan1,omitempty"`
Wan2 struct {
BytesR int `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 int `json:"max_speed"`
Name string `json:"name"`
Netmask string `json:"netmask"`
RxBytes int64 `json:"rx_bytes"`
RxBytesR int `json:"rx_bytes-r"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxMulticast int `json:"rx_multicast"`
RxPackets int `json:"rx_packets"`
Speed int `json:"speed"`
TxBytes int64 `json:"tx_bytes"`
TxBytesR int `json:"tx_bytes-r"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxPackets int `json:"tx_packets"`
Type string `json:"type"`
Up bool `json:"up"`
} `json:"wan2,omitempty"`
}
// GetUnifiDevices returns a response full of devices' data from the Unifi Controller.
func (c *Config) GetUnifiDevices() ([]Device, error) {
response := &DeviceResponse{}
if req, err := c.uniRequest(DevicePath, ""); err != nil {
return nil, err
} else if resp, err := c.uniClient.Do(req); err != nil {
return nil, err
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, err
} else if err = json.Unmarshal(body, response); err != nil {
return nil, err
} else if err = resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
return response.Devices, nil
}
// Point generates a device's datapoint for InfluxDB.
func (d Device) Point() (*influx.Point, error) {
tags := map[string]string{
"id": d.ID,
"mac": d.Mac,
"device_type": d.Stat.O,
"device_oid": d.Stat.Oid,
"device_ap": d.Stat.Ap,
"site_id": d.SiteID,
"name": d.Name,
"addopted": strconv.FormatBool(d.Adopted),
"adopt_ip": d.AdoptIP,
"adopt_url": d.AdoptURL,
"bandsteering_mode": d.BandsteeringMode,
"board_rev": strconv.Itoa(d.BoardRev),
"cfgversion": d.Cfgversion,
"config_network_ip": d.ConfigNetwork.IP,
"config_network_type": d.ConfigNetwork.Type,
"connect_request_ip": d.ConnectRequestIP,
"connect_request_port": d.ConnectRequestPort,
"default": strconv.FormatBool(d.Default),
"device_id": d.DeviceID,
"discovered_via": d.DiscoveredVia,
"fw_caps": strconv.Itoa(d.FwCaps),
"guest-num_sta": strconv.Itoa(d.GuestNumSta),
"guest_token": d.GuestToken,
"has_eth1": strconv.FormatBool(d.HasEth1),
"has_speaker": strconv.FormatBool(d.HasSpeaker),
"inform_ip": d.InformIP,
"isolated": strconv.FormatBool(d.Isolated),
"last_seen": strconv.Itoa(d.LastSeen),
"last_uplink_mac": d.LastUplink.UplinkMac,
"last_uplink_remote_port": strconv.Itoa(d.LastUplink.UplinkRemotePort),
"known_cfgversion": d.KnownCfgversion,
"led_override": d.LedOverride,
"locating": strconv.FormatBool(d.Locating),
"model": d.Model,
"outdoor_mode_override": d.OutdoorModeOverride,
"serial": d.Serial,
"type": d.Type,
"version_incompatible": strconv.FormatBool(d.VersionIncompatible),
"vwireEnabled": strconv.FormatBool(d.VwireEnabled),
"wifi_caps": strconv.Itoa(d.WifiCaps),
"dot1x_portctrl_enabled": strconv.FormatBool(d.Dot1XPortctrlEnabled),
"flowctrl_enabled": strconv.FormatBool(d.FlowctrlEnabled),
"has_fan": strconv.FormatBool(d.HasFan),
"has_temperature": strconv.FormatBool(d.HasTemperature),
"jumboframe_enabled": strconv.FormatBool(d.JumboframeEnabled),
"stp_priority": d.StpPriority,
"stp_version": d.StpVersion,
"uplink_depth": strconv.Itoa(d.UplinkDepth),
"config_network_wan_type": d.ConfigNetworkWan.Type,
"usg_caps": strconv.Itoa(d.UsgCaps),
"speedtest-status-saved": strconv.FormatBool(d.SpeedtestStatusSaved),
}
fields := map[string]interface{}{
"ip": d.IP,
"bytes": d.Bytes,
"bytes_d": d.BytesD,
"bytes_r": d.BytesR,
"fan_level": d.FanLevel,
"general_temperature": d.GeneralTemperature,
"last_seen": d.LastSeen,
"license_state": d.LicenseState,
"overheating": d.Overheating,
"rx_bytes": d.RxBytes,
"rx_bytes-d": d.RxBytesD,
"tx_bytes": d.TxBytes,
"tx_bytes-d": d.TxBytesD,
"uptime": d.Uptime,
"considered_lost_at": d.ConsideredLostAt,
"next_heartbeat_at": d.NextHeartbeatAt,
"scanning": d.Scanning,
"spectrum_scanning": d.SpectrumScanning,
"roll_upgrade": d.Rollupgrade,
"state": d.State,
"upgradable": d.Upgradable,
"user-num_sta": d.UserNumSta,
"version": d.Version,
"num_desktop": d.NumDesktop,
"num_handheld": d.NumHandheld,
"num_mobile": d.NumMobile,
"speedtest-status_latency": d.SpeedtestStatus.Latency,
"speedtest-status_rundate": d.SpeedtestStatus.Rundate,
"speedtest-status_runtime": d.SpeedtestStatus.Runtime,
"speedtest-status_download": d.SpeedtestStatus.StatusDownload,
"speedtest-status_ping": d.SpeedtestStatus.StatusPing,
"speedtest-status_summary": d.SpeedtestStatus.StatusSummary,
"speedtest-status_upload": d.SpeedtestStatus.StatusUpload,
"speedtest-status_xput_download": d.SpeedtestStatus.XputDownload,
"speedtest-status_xput_upload": d.SpeedtestStatus.XputUpload,
"wan1_bytes-r": d.Wan1.BytesR,
"wan1_enable": d.Wan1.Enable,
"wan1_full_duplex": d.Wan1.FullDuplex,
"wan1_gateway": d.Wan1.Gateway,
"wan1_ifname": d.Wan1.Ifname,
"wan1_ip": d.Wan1.IP,
"wan1_mac": d.Wan1.Mac,
"wan1_max_speed": d.Wan1.MaxSpeed,
"wan1_name": d.Wan1.Name,
"wan1_netmask": d.Wan1.Netmask,
"wan1_rx_bytes": d.Wan1.RxBytes,
"wan1_rx_bytes-r": d.Wan1.RxBytesR,
"wan1_rx_dropped": d.Wan1.RxDropped,
"wan1_rx_errors": d.Wan1.RxErrors,
"wan1_rx_multicast": d.Wan1.RxMulticast,
"wan1_rx_packets": d.Wan1.RxPackets,
"wan1_type": d.Wan1.Type,
"wan1_speed": d.Wan1.Speed,
"wan1_up": d.Wan1.Up,
"wan1_tx_bytes": d.Wan1.TxBytes,
"wan1_tx_bytes-r": d.Wan1.TxBytesR,
"wan1_tx_dropped": d.Wan1.TxDropped,
"wan1_tx_errors": d.Wan1.TxErrors,
"wan1_tx_packets": d.Wan1.TxPackets,
"loadavg_1": d.SysStats.Loadavg1,
"loadavg_5": d.SysStats.Loadavg5,
"loadavg_15": d.SysStats.Loadavg15,
"mem_buffer": d.SysStats.MemBuffer,
"mem_total": d.SysStats.MemTotal,
"cpu": d.SystemStats.CPU,
"mem": d.SystemStats.Mem,
"system_uptime": d.SystemStats.Uptime,
"stat_bytes": d.Stat.Bytes,
"stat_duration": d.Stat.Duration,
"stat_guest-rx_bytes": d.Stat.RxBytes,
"stat_guest-rx_crypts": d.Stat.RxCrypts,
"stat_guest-rx_dropped": d.Stat.RxDropped,
"stat_guest-rx_errors": d.Stat.RxErrors,
"stat_guest-rx_frags": d.Stat.RxFrags,
"stat_guest-rx_packets": d.Stat.RxPackets,
"stat_guest-tx_bytes": d.Stat.TxBytes,
"stat_guest-tx_dropped": d.Stat.TxDropped,
"stat_guest-tx_errors": d.Stat.TxErrors,
"stat_guest-tx_packets": d.Stat.TxPackets,
"stat_guest-tx_retries": d.Stat.TxRetries,
"stat_port_1-rx_broadcast": d.Stat.Port1RxBroadcast,
"stat_port_1-rx_bytes": d.Stat.Port1RxBytes,
"stat_port_1-rx_multicast": d.Stat.Port1RxMulticast,
"stat_port_1-rx_packets": d.Stat.Port1RxPackets,
"stat_port_1-tx_broadcast": d.Stat.Port1TxBroadcast,
"stat_port_1-tx_bytes": d.Stat.Port1TxBytes,
"stat_port_1-tx_multicast": d.Stat.Port1TxMulticast,
"stat_port_1-tx_packets": d.Stat.Port1TxPackets,
"stat_rx_bytes": d.Stat.RxBytes,
"stat_rx_crypts": d.Stat.RxCrypts,
"stat_rx_dropped": d.Stat.RxDropped,
"stat_rx_errors": d.Stat.RxErrors,
"stat_rx_frags": d.Stat.RxFrags,
"stat_rx_packets": d.Stat.TxPackets,
"stat_tx_bytes": d.Stat.TxBytes,
"stat_tx_dropped": d.Stat.TxDropped,
"stat_tx_errors": d.Stat.TxErrors,
"stat_tx_packets": d.Stat.TxPackets,
"stat_tx_retries": d.Stat.TxRetries,
"stat_user-rx_bytes": d.Stat.UserRxBytes,
"stat_user-rx_crypts": d.Stat.UserRxCrypts,
"stat_user-rx_dropped": d.Stat.UserRxDropped,
"stat_user-rx_errors": d.Stat.UserRxErrors,
"stat_user-rx_frags": d.Stat.UserRxFrags,
"stat_user-rx_packets": d.Stat.UserRxPackets,
"stat_user-tx_bytes": d.Stat.UserTxBytes,
"stat_user-tx_dropped": d.Stat.UserTxDropped,
"stat_user-tx_errors": d.Stat.UserTxErrors,
"stat_user-tx_packets": d.Stat.UserTxPackets,
"stat_user-tx_retries": d.Stat.UserTxRetries,
"stat_user-wifi0-rx_bytes": d.Stat.UserWifi0RxBytes,
"stat_user-wifi0-rx_crypts": d.Stat.UserWifi0RxCrypts,
"stat_user-wifi0-rx_dropped": d.Stat.UserWifi0RxDropped,
"stat_user-wifi0-rx_errors": d.Stat.UserWifi0RxErrors,
"stat_user-wifi0-rx_frags": d.Stat.UserWifi0RxFrags,
"stat_user-wifi0-rx_packets": d.Stat.UserWifi0RxPackets,
"stat_user-wifi0-tx_bytes": d.Stat.UserWifi0TxBytes,
"stat_user-wifi0-tx_dropped": d.Stat.UserWifi0TxDropped,
"stat_user-wifi0-tx_errors": d.Stat.UserWifi0TxErrors,
"stat_user-wifi0-tx_packets": d.Stat.UserWifi0TxPackets,
"stat_user-wifi0-tx_retries": d.Stat.UserWifi0TxRetries,
"stat_user-wifi1-rx_bytes": d.Stat.UserWifi1RxBytes,
"stat_user-wifi1-rx_crypts": d.Stat.UserWifi1RxCrypts,
"stat_user-wifi1-rx_dropped": d.Stat.UserWifi1RxDropped,
"stat_user-wifi1-rx_errors": d.Stat.UserWifi1RxErrors,
"stat_user-wifi1-rx_frags": d.Stat.UserWifi1RxFrags,
"stat_user-wifi1-rx_packets": d.Stat.UserWifi1RxPackets,
"stat_user-wifi1-tx_bytes": d.Stat.UserWifi1TxBytes,
"stat_user-wifi1-tx_dropped": d.Stat.UserWifi1TxDropped,
"stat_user-wifi1-tx_errors": d.Stat.UserWifi1TxErrors,
"stat_user-wifi1-tx_packets": d.Stat.UserWifi1TxPackets,
"stat_user-wifi1-tx_retries": d.Stat.UserWifi1TxRetries,
"stat_wifi0-rx_bytes": d.Stat.Wifi0RxBytes,
"stat_wifi0-rx_crypts": d.Stat.Wifi0RxCrypts,
"stat_wifi0-rx_dropped": d.Stat.Wifi0RxDropped,
"stat_wifi0-rx_errors": d.Stat.Wifi0RxErrors,
"stat_wifi0-rx_frags": d.Stat.Wifi0RxFrags,
"stat_wifi0-rx_packets": d.Stat.Wifi0RxPackets,
"stat_wifi0-tx_bytes": d.Stat.Wifi0TxBytes,
"stat_wifi0-tx_dropped": d.Stat.Wifi0TxDropped,
"stat_wifi0-tx_errors": d.Stat.Wifi0TxErrors,
"stat_wifi0-tx_packets": d.Stat.Wifi0TxPackets,
"stat_wifi0-tx_retries": d.Stat.Wifi0TxRetries,
"stat_wifi1-rx_bytes": d.Stat.Wifi1RxBytes,
"stat_wifi1-rx_crypts": d.Stat.Wifi1RxCrypts,
"stat_wifi1-rx_dropped": d.Stat.Wifi1RxDropped,
"stat_wifi1-rx_errors": d.Stat.Wifi1RxErrors,
"stat_wifi1-rx_frags": d.Stat.Wifi1RxFrags,
"stat_wifi1-rx_packets": d.Stat.Wifi1RxPackets,
"stat_wifi1-tx_bytes": d.Stat.Wifi1TxBytes,
"stat_wifi1-tx_dropped": d.Stat.Wifi1TxDropped,
"stat_wifi1-tx_errors": d.Stat.Wifi1TxErrors,
"stat_wifi1-tx_packets": d.Stat.Wifi1TxPackets,
"stat_wifi1-tx_retries": d.Stat.Wifi1TxRetries,
}
return influx.NewPoint("devices", tags, fields, time.Now())
}

View File

@ -1,16 +1,14 @@
package main package main
import ( import (
"bytes"
"crypto/tls"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http"
"net/http/cookiejar"
"os" "os"
"time" "time"
"github.com/davidnewhall/unifi-poller/unidev"
influx "github.com/influxdata/influxdb/client/v2" influx "github.com/influxdata/influxdb/client/v2"
"github.com/naoina/toml" "github.com/naoina/toml"
flg "github.com/ogier/pflag" flg "github.com/ogier/pflag"
@ -23,22 +21,25 @@ func main() {
flg.PrintDefaults() flg.PrintDefaults()
} }
configFile := flg.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)") configFile := flg.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)")
debug := flg.BoolP("debug", "D", false, "Turn on the Spam (default false)") flg.BoolVarP(&Debug, "debug", "D", false, "Turn on the Spam (default false)")
version := flg.BoolP("version", "v", false, "Print the version and exit.") version := flg.BoolP("version", "v", false, "Print the version and exit.")
flg.Parse() flg.Parse()
if *version { if *version {
fmt.Println("unifi-poller version:", Version) fmt.Println("unifi-poller version:", Version)
os.Exit(0) // don't run anything else. os.Exit(0) // don't run anything else.
} }
if log.SetFlags(0); *debug { if log.SetFlags(0); Debug {
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate) log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
unidev.Debug = true
} }
config, errc := GetConfig(*configFile) config, err := GetConfig(*configFile)
if errc != nil { if err != nil {
flg.Usage() flg.Usage()
log.Fatalln("Config Error:", errc) log.Fatalln("Config Error:", err)
} }
if err := config.AuthController(); err != nil { // Create an authenticated session to the Unifi Controller.
unifi, err := unidev.AuthController(config.UnifiUser, config.UnifiPass, config.UnifiBase)
if err != nil {
log.Fatal(err) log.Fatal(err)
} }
log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser) log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser)
@ -53,7 +54,7 @@ func main() {
} }
log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser) log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser)
log.Println("Polling Unifi Controller, interval:", config.Interval.value) log.Println("Polling Unifi Controller, interval:", config.Interval.value)
config.PollUnifiController(infdb) config.PollUnifiController(infdb, unifi)
} }
// GetConfig parses and returns our configuration data. // GetConfig parses and returns our configuration data.
@ -78,41 +79,18 @@ func GetConfig(configFile string) (Config, error) {
return config, nil return config, nil
} }
// AuthController creates a http.Client with authenticated cookies.
// Used to make additional, authenticated requests to the APIs.
func (c *Config) AuthController() error {
json := `{"username": "` + c.UnifiUser + `","password": "` + c.UnifiPass + `"}`
jar, err := cookiejar.New(nil)
if err != nil {
return errors.Wrap(err, "cookiejar.New(nil)")
}
c.uniClient = &http.Client{
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
Jar: jar,
}
if req, err := c.uniRequest(LoginPath, json); err != nil {
return errors.Wrap(err, "c.uniRequest(LoginPath, json)")
} else if resp, err := c.uniClient.Do(req); err != nil {
return errors.Wrap(err, "c.uniClient.Do(req)")
} else if resp.StatusCode != http.StatusOK {
return errors.Errorf("authentication failed (%v): %v (status: %v/%v)",
c.UnifiUser, c.UnifiBase+LoginPath, resp.StatusCode, resp.Status)
}
return nil
}
// PollUnifiController runs forever, polling and pushing. // PollUnifiController runs forever, polling and pushing.
func (c *Config) PollUnifiController(infdb influx.Client) { func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedReq) {
ticker := time.NewTicker(c.Interval.value) ticker := time.NewTicker(c.Interval.value)
for range ticker.C { for range ticker.C {
clients, err := c.GetUnifiClients() clients, err := unifi.GetUnifiClients()
if err != nil { if err != nil {
log.Println("GetUnifiClients():", err) log.Println("unifi.GetUnifiClients():", err)
continue continue
} }
devices, err := c.GetUnifiDevices() devices, err := unifi.GetUnifiDevices()
if err != nil { if err != nil {
log.Println("GetUnifiDevices():", err) log.Println("unifi.GetUnifiDevices():", err)
continue continue
} }
bp, err := influx.NewBatchPoints(influx.BatchPointsConfig{ bp, err := influx.NewBatchPoints(influx.BatchPointsConfig{
@ -123,20 +101,14 @@ func (c *Config) PollUnifiController(infdb influx.Client) {
continue continue
} }
for _, client := range clients { for _, asset := range append(clients, devices...) {
if pt, errr := client.Point(); errr != nil { if pt, errr := asset.Point(); errr != nil {
log.Println("client.Point():", errr) log.Println("asset.Point():", errr)
} else {
bp.AddPoint(pt)
}
}
for _, device := range devices {
if pt, errr := device.Point(); errr != nil {
log.Println("device.Point():", errr)
} else { } else {
bp.AddPoint(pt) bp.AddPoint(pt)
} }
} }
if err = infdb.Write(bp); err != nil { if err = infdb.Write(bp); err != nil {
log.Println("infdb.Write(bp):", err) log.Println("infdb.Write(bp):", err)
continue continue
@ -144,16 +116,3 @@ func (c *Config) PollUnifiController(infdb influx.Client) {
log.Println("Logged client state. Clients:", len(clients), "- Devices:", len(devices)) log.Println("Logged client state. Clients:", len(clients), "- Devices:", len(devices))
} }
} }
// uniRequest is a small helper function that adds an Accept header.
func (c *Config) uniRequest(url string, params string) (req *http.Request, err error) {
if params != "" {
req, err = http.NewRequest("POST", c.UnifiBase+url, bytes.NewBufferString(params))
} else {
req, err = http.NewRequest("GET", c.UnifiBase+url, nil)
}
if err == nil {
req.Header.Add("Accept", "application/json")
}
return
}

100
unidev/clients.go Normal file
View File

@ -0,0 +1,100 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Point generates a client's datapoint for InfluxDB.
func (u UCL) Point() (*influx.Point, error) {
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,
}
return influx.NewPoint("clients", tags, fields, time.Now())
}

88
unidev/clients_type.go Normal file
View File

@ -0,0 +1,88 @@
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"`
}

169
unidev/uap.go Normal file
View File

@ -0,0 +1,169 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Point generates a device's datapoint for InfluxDB.
func (u UAP) Point() (*influx.Point, error) {
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_seen": strconv.Itoa(u.LastSeen),
"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,
"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,
"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,
}
return influx.NewPoint("uap", tags, fields, time.Now())
}

356
unidev/uap_type.go Normal file
View File

@ -0,0 +1,356 @@
package unidev
// UAP is a Unifi Access Point
type UAP struct {
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 int `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 string `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 string `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 interface{} `json:"ast_be_xmit"`
AstCst interface{} `json:"ast_cst"`
AstTxto interface{} `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 int `json:"rx_bytes"`
RxBytesD int `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 string `json:"loadavg_1"`
Loadavg15 string `json:"loadavg_15"`
Loadavg5 string `json:"loadavg_5"`
MemBuffer int `json:"mem_buffer"`
MemTotal int `json:"mem_total"`
MemUsed int `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU string `json:"cpu"`
Mem string `json:"mem"`
Uptime string `json:"uptime"`
} `json:"system-stats"`
TxBytes float64 `json:"tx_bytes"`
TxBytesD int `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 int `json:"rx_bytes-r"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxMulticast int `json:"rx_multicast"`
RxPackets int `json:"rx_packets"`
Speed int `json:"speed"`
TxBytes float64 `json:"tx_bytes"`
TxBytesR int `json:"tx_bytes-r"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxPackets int `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 int `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 interface{} `json:"map_id"`
Name string `json:"name"`
NumSta int `json:"num_sta"`
Radio string `json:"radio"`
RadioName string `json:"radio_name"`
RxBytes int `json:"rx_bytes"`
RxCrypts int `json:"rx_crypts"`
RxDropped int `json:"rx_dropped"`
RxErrors int `json:"rx_errors"`
RxFrags int `json:"rx_frags"`
RxNwids int `json:"rx_nwids"`
RxPackets int `json:"rx_packets"`
SiteID string `json:"site_id"`
State string `json:"state"`
T string `json:"t"`
TxBytes int `json:"tx_bytes"`
TxDropped int `json:"tx_dropped"`
TxErrors int `json:"tx_errors"`
TxLatencyAvg float64 `json:"tx_latency_avg"`
TxLatencyMax float64 `json:"tx_latency_max"`
TxLatencyMin float64 `json:"tx_latency_min"`
TxPackets int `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"`
}

62
unidev/unidev.go Normal file
View File

@ -0,0 +1,62 @@
package unidev
import (
"bytes"
"crypto/tls"
influx "github.com/influxdata/influxdb/client/v2"
"github.com/pkg/errors"
"net/http"
"net/http/cookiejar"
)
// LoginPath is Unifi Controller Login API Path
const LoginPath = "/api/login"
// Asset provides a common interface to retreive metrics from a device or client.
type Asset interface {
// Point() means this is useful to influxdb..
Point() (*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
}
// AuthController creates a http.Client with authenticated cookies.
// Used to make additional, authenticated requests to the APIs.
func AuthController(user, pass, url string) (*AuthedReq, error) {
json := `{"username": "` + user + `","password": "` + pass + `"}`
jar, err := cookiejar.New(nil)
if err != nil {
return nil, errors.Wrap(err, "cookiejar.New(nil)")
}
authReq := &AuthedReq{&http.Client{
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
Jar: jar,
}, url}
if req, err := authReq.UniReq(LoginPath, json); err != nil {
return nil, errors.Wrap(err, "uniRequest(LoginPath, json)")
} else if resp, err := authReq.Do(req); err != nil {
return nil, errors.Wrap(err, "c.uniClient.Do(req)")
} else if resp.StatusCode != http.StatusOK {
return nil, errors.Errorf("authentication failed (%v): %v (status: %v/%v)",
user, url+LoginPath, resp.StatusCode, resp.Status)
}
return authReq, nil
}
// UniReq is a small helper function that adds an Accept header.
func (c AuthedReq) UniReq(apiURL string, params string) (req *http.Request, err error) {
if params != "" {
req, err = http.NewRequest("POST", c.baseURL+apiURL, bytes.NewBufferString(params))
} else {
req, err = http.NewRequest("GET", c.baseURL+apiURL, nil)
}
if err == nil {
req.Header.Add("Accept", "application/json")
}
return
}

101
unidev/unifi.go Normal file
View File

@ -0,0 +1,101 @@
package unidev
import (
"encoding/json"
"io/ioutil"
"log"
)
// 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() ([]Asset, error) {
var response struct {
Clients []UCL `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
if req, err := c.UniReq(ClientPath, ""); err != nil {
return nil, err
} else if resp, err := c.Do(req); err != nil {
return nil, err
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, err
} else if err = json.Unmarshal(body, response); err != nil {
return nil, err
} else if err = resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
clients := []Asset{}
for _, r := range response.Clients {
clients = append(clients, r)
}
return clients, nil
}
// GetUnifiDevices returns a response full of devices' data from the Unifi Controller.
func (c *AuthedReq) GetUnifiDevices() ([]Asset, error) {
var parsed struct {
Data []json.RawMessage `json:"data"`
Meta struct {
Rc string `json:"rc"`
} `json:"meta"`
}
assets := []Asset{}
if req, err := c.UniReq(DevicePath, ""); err != nil {
return nil, err
} else if resp, err := c.Do(req); err != nil {
return nil, err
} else if body, err := ioutil.ReadAll(resp.Body); err != nil {
return nil, err
} else if err = json.Unmarshal(body, &parsed); err != nil {
return nil, err
} else if err = resp.Body.Close(); err != nil {
log.Println("resp.Body.Close():", err) // Not fatal? Just log it.
}
for _, r := range parsed.Data {
// Unamrshal into a map and check "type"
var obj map[string]interface{}
if err := json.Unmarshal(r, &obj); err != nil {
return nil, err
}
assetType := ""
if t, ok := obj["type"].(string); ok {
assetType = t
}
// Unmarshal again into the correct type..
var asset Asset
switch assetType {
case "uap":
asset = &UAP{}
case "ugw":
asset = &USG{}
case "usw":
asset = &USW{}
default:
log.Println("unknown asset type -", assetType, "- skipping")
continue
}
if Debug {
log.Println("Unmarshalling", assetType)
}
if err := json.Unmarshal(r, asset); err != nil {
return nil, err
}
assets = append(assets, asset)
}
return assets, nil
}

121
unidev/usg.go Normal file
View File

@ -0,0 +1,121 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Point generates a device's datapoint for InfluxDB.
func (u USG) Point() (*influx.Point, error) {
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,
"fw_caps": strconv.FormatFloat(u.FwCaps, 'f', 6, 64),
"guest-num_sta": strconv.FormatFloat(u.GuestNumSta, 'f', 6, 64),
"guest_token": u.GuestToken,
"inform_ip": u.InformIP,
"last_seen": strconv.FormatFloat(u.LastSeen, 'f', 6, 64),
"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),
"config_network_wan_type": u.ConfigNetworkWan.Type,
"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,
"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. ;)
"wan1_bytes-r": u.Wan1.BytesR,
"wan1_enable": u.Wan1.Enable,
"wan1_full_duplex": u.Wan1.FullDuplex,
"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_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,
"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,
}
return influx.NewPoint("usg", tags, fields, time.Now())
}

260
unidev/usg_type.go Normal file
View File

@ -0,0 +1,260 @@
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"`
Ipv6float64erfaceType string `json:"ipv6_float64erface_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 string `json:"loadavg_1"`
Loadavg15 string `json:"loadavg_15"`
Loadavg5 string `json:"loadavg_5"`
MemBuffer float64 `json:"mem_buffer"`
MemTotal float64 `json:"mem_total"`
MemUsed float64 `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU string `json:"cpu"`
Mem string `json:"mem"`
Uptime string `json:"uptime"`
} `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"`
}

113
unidev/usw.go Normal file
View File

@ -0,0 +1,113 @@
package unidev
import (
"strconv"
"time"
influx "github.com/influxdata/influxdb/client/v2"
)
// Point generates a device's datapoint for InfluxDB.
func (u USW) Point() (*influx.Point, error) {
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,
"fw_caps": strconv.FormatFloat(u.FwCaps, 'f', 6, 64),
"guest-num_sta": strconv.FormatFloat(u.GuestNumSta, 'f', 6, 64),
"inform_ip": u.InformIP,
"last_seen": strconv.FormatFloat(u.LastSeen, 'f', 6, 64),
"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,
"uplink_depth": strconv.FormatFloat(u.UplinkDepth, 'f', 6, 64),
}
fields := map[string]interface{}{
"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_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,
// Add the port stats too.
}
return influx.NewPoint("usw", tags, fields, time.Now())
}

415
unidev/usw_type.go Normal file
View File

@ -0,0 +1,415 @@
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 string `json:"loadavg_1"`
Loadavg15 string `json:"loadavg_15"`
Loadavg5 string `json:"loadavg_5"`
MemBuffer float64 `json:"mem_buffer"`
MemTotal float64 `json:"mem_total"`
MemUsed float64 `json:"mem_used"`
} `json:"sys_stats"`
SystemStats struct {
CPU string `json:"cpu"`
Mem string `json:"mem"`
Uptime string `json:"uptime"`
} `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"`
}