diff --git a/integrations/inputunifi/Godeps/Godeps.json b/integrations/inputunifi/Godeps/Godeps.json index d5c6895b..ed2eeadb 100644 --- a/integrations/inputunifi/Godeps/Godeps.json +++ b/integrations/inputunifi/Godeps/Godeps.json @@ -1,5 +1,5 @@ { - "ImportPath": "github.com/davidnewhall/unifi", + "ImportPath": "github.com/davidnewhall/unifi-poller", "GoVersion": "go1.10", "GodepVersion": "v79", "Packages": [ diff --git a/integrations/inputunifi/MIT-LICENSE b/integrations/inputunifi/MIT-LICENSE index 1c77509a..42782d63 100644 --- a/integrations/inputunifi/MIT-LICENSE +++ b/integrations/inputunifi/MIT-LICENSE @@ -1,4 +1,5 @@ Copyright (c) 2016 Garrett Bjerkhoel +Copyright (c) 2018 David Newhall II Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/integrations/inputunifi/Makefile b/integrations/inputunifi/Makefile index 36e7dfa0..ad40a80e 100644 --- a/integrations/inputunifi/Makefile +++ b/integrations/inputunifi/Makefile @@ -1,5 +1,5 @@ PACKAGES=`find ./cmd -mindepth 1 -maxdepth 1 -type d` -LIBRARYS= +LIBRARYS=./unidev all: clean man build diff --git a/integrations/inputunifi/cmd/unifi-poller/clients.go b/integrations/inputunifi/cmd/unifi-poller/clients.go deleted file mode 100644 index 3d42057f..00000000 --- a/integrations/inputunifi/cmd/unifi-poller/clients.go +++ /dev/null @@ -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()) -} diff --git a/integrations/inputunifi/cmd/unifi-poller/config.go b/integrations/inputunifi/cmd/unifi-poller/config.go index b09fffac..a04de1d4 100644 --- a/integrations/inputunifi/cmd/unifi-poller/config.go +++ b/integrations/inputunifi/cmd/unifi-poller/config.go @@ -1,24 +1,14 @@ package main -import ( - "net/http" - "time" -) +import "time" // Version will be injected at build time. -var Version = "v0.1" +var ( + Version = "v0.1" + Debug = false +) 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. defaultConfFile = "/usr/local/etc/unifi-poller/up.conf" 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"` 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"` - uniClient *http.Client } // Dur is used to UnmarshalTOML into a time.Duration value. -type Dur struct { - value time.Duration -} +type Dur struct{ value time.Duration } // UnmarshalTOML parses a duration type from a config file. func (v *Dur) UnmarshalTOML(data []byte) error { diff --git a/integrations/inputunifi/cmd/unifi-poller/devices.go b/integrations/inputunifi/cmd/unifi-poller/devices.go deleted file mode 100644 index 3b5f8de2..00000000 --- a/integrations/inputunifi/cmd/unifi-poller/devices.go +++ /dev/null @@ -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()) -} diff --git a/integrations/inputunifi/cmd/unifi-poller/main.go b/integrations/inputunifi/cmd/unifi-poller/main.go index f038cdc1..cdfa86af 100644 --- a/integrations/inputunifi/cmd/unifi-poller/main.go +++ b/integrations/inputunifi/cmd/unifi-poller/main.go @@ -1,16 +1,14 @@ package main import ( - "bytes" - "crypto/tls" "fmt" "io/ioutil" "log" - "net/http" - "net/http/cookiejar" "os" "time" + "github.com/davidnewhall/unifi-poller/unidev" + influx "github.com/influxdata/influxdb/client/v2" "github.com/naoina/toml" flg "github.com/ogier/pflag" @@ -23,22 +21,25 @@ func main() { flg.PrintDefaults() } 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.") flg.Parse() if *version { fmt.Println("unifi-poller version:", Version) 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) + unidev.Debug = true } - config, errc := GetConfig(*configFile) - if errc != nil { + config, err := GetConfig(*configFile) + if err != nil { 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.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("Polling Unifi Controller, interval:", config.Interval.value) - config.PollUnifiController(infdb) + config.PollUnifiController(infdb, unifi) } // GetConfig parses and returns our configuration data. @@ -78,41 +79,18 @@ func GetConfig(configFile string) (Config, error) { 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. -func (c *Config) PollUnifiController(infdb influx.Client) { +func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedReq) { ticker := time.NewTicker(c.Interval.value) for range ticker.C { - clients, err := c.GetUnifiClients() + clients, err := unifi.GetUnifiClients() if err != nil { - log.Println("GetUnifiClients():", err) + log.Println("unifi.GetUnifiClients():", err) continue } - devices, err := c.GetUnifiDevices() + devices, err := unifi.GetUnifiDevices() if err != nil { - log.Println("GetUnifiDevices():", err) + log.Println("unifi.GetUnifiDevices():", err) continue } bp, err := influx.NewBatchPoints(influx.BatchPointsConfig{ @@ -123,20 +101,14 @@ func (c *Config) PollUnifiController(infdb influx.Client) { continue } - for _, client := range clients { - if pt, errr := client.Point(); errr != nil { - log.Println("client.Point():", errr) - } else { - bp.AddPoint(pt) - } - } - for _, device := range devices { - if pt, errr := device.Point(); errr != nil { - log.Println("device.Point():", errr) + for _, asset := range append(clients, devices...) { + if pt, errr := asset.Point(); errr != nil { + log.Println("asset.Point():", errr) } else { bp.AddPoint(pt) } } + if err = infdb.Write(bp); err != nil { log.Println("infdb.Write(bp):", err) continue @@ -144,16 +116,3 @@ func (c *Config) PollUnifiController(infdb influx.Client) { 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 -} diff --git a/integrations/inputunifi/unidev/clients.go b/integrations/inputunifi/unidev/clients.go new file mode 100644 index 00000000..3e58af58 --- /dev/null +++ b/integrations/inputunifi/unidev/clients.go @@ -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()) +} diff --git a/integrations/inputunifi/unidev/clients_type.go b/integrations/inputunifi/unidev/clients_type.go new file mode 100644 index 00000000..45ddf1dd --- /dev/null +++ b/integrations/inputunifi/unidev/clients_type.go @@ -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"` +} diff --git a/integrations/inputunifi/unidev/uap.go b/integrations/inputunifi/unidev/uap.go new file mode 100644 index 00000000..9e2847c1 --- /dev/null +++ b/integrations/inputunifi/unidev/uap.go @@ -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()) +} diff --git a/integrations/inputunifi/unidev/uap_type.go b/integrations/inputunifi/unidev/uap_type.go new file mode 100644 index 00000000..d2f6a55a --- /dev/null +++ b/integrations/inputunifi/unidev/uap_type.go @@ -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"` +} diff --git a/integrations/inputunifi/unidev/unidev.go b/integrations/inputunifi/unidev/unidev.go new file mode 100644 index 00000000..324ab329 --- /dev/null +++ b/integrations/inputunifi/unidev/unidev.go @@ -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 +} diff --git a/integrations/inputunifi/unidev/unifi.go b/integrations/inputunifi/unidev/unifi.go new file mode 100644 index 00000000..1cdad897 --- /dev/null +++ b/integrations/inputunifi/unidev/unifi.go @@ -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 +} diff --git a/integrations/inputunifi/unidev/usg.go b/integrations/inputunifi/unidev/usg.go new file mode 100644 index 00000000..dbad1a6c --- /dev/null +++ b/integrations/inputunifi/unidev/usg.go @@ -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()) +} diff --git a/integrations/inputunifi/unidev/usg_type.go b/integrations/inputunifi/unidev/usg_type.go new file mode 100644 index 00000000..8d6b4d82 --- /dev/null +++ b/integrations/inputunifi/unidev/usg_type.go @@ -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"` +} diff --git a/integrations/inputunifi/unidev/usw.go b/integrations/inputunifi/unidev/usw.go new file mode 100644 index 00000000..215bbc43 --- /dev/null +++ b/integrations/inputunifi/unidev/usw.go @@ -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()) +} diff --git a/integrations/inputunifi/unidev/usw_type.go b/integrations/inputunifi/unidev/usw_type.go new file mode 100644 index 00000000..5ed47065 --- /dev/null +++ b/integrations/inputunifi/unidev/usw_type.go @@ -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"` +}