3 UniFi-Client
Virgil edited this page 2026-02-19 17:02:51 +00:00

UniFi Client

Back to Home

The unifi package (forge.lthn.ai/core/go-netops/unifi) provides a Go client for UniFi network controllers. It wraps the unpoller/unifi SDK with config-aware authentication and a cleaner API for common operations.

Creating a Client

Direct Credentials

func New(url, user, pass, apikey string, insecure bool) (*Client, error)

Creates a client with explicit credentials. The insecure parameter disables TLS certificate verification (useful for self-signed certificates on home lab controllers). TLS 1.2 is the minimum version enforced.

client, err := unifi.New(
    "https://10.69.1.1",  // Controller URL
    "admin",               // Username
    "password",            // Password
    "",                    // API key (alternative to user/pass)
    true,                  // Skip TLS verification
)
func NewFromConfig(flagURL, flagUser, flagPass, flagAPIKey string, flagInsecure *bool) (*Client, error)

Creates a client using multi-source configuration resolution. Pass empty strings and nil to use defaults from the config file or environment. Pass non-empty values to override specific settings.

// Use all defaults from config file and environment
client, err := unifi.NewFromConfig("", "", "", "", nil)

// Override just the URL
client, err := unifi.NewFromConfig("https://192.168.1.1", "", "", "", nil)

// Override with API key authentication
client, err := unifi.NewFromConfig("", "", "", "my-api-key", nil)

See Configuration for details on config resolution priority.

Client Type

type Client struct {
    // unexported fields
}

Core Methods

// API exposes the underlying unpoller SDK client for direct access.
func (c *Client) API() *uf.Unifi

// URL returns the UniFi controller URL.
func (c *Client) URL() string

Use API() when you need to call SDK methods not wrapped by this package.


Sites

func (c *Client) GetSites() ([]*uf.Site, error)

Returns all sites configured on the UniFi controller.

sites, err := client.GetSites()
if err != nil {
    log.Fatal(err)
}
for _, site := range sites {
    fmt.Printf("Site: %s (%s)\n", site.Name, site.Desc)
}

Devices

DeviceInfo Type

type DeviceInfo struct {
    Name    string  // Device name
    IP      string  // IP address
    Mac     string  // MAC address
    Model   string  // Hardware model identifier
    Version string  // Firmware version
    Type    string  // Device type: uap, usw, usg, udm, uxg
    Status  int     // 1 = online
}

Get Raw Devices

func (c *Client) GetDevices(siteName string) (*uf.Devices, error)

Returns the raw device container from the SDK, grouped by device type (UAPs, USWs, USGs, UDMs, UXGs). Pass an empty string for siteName to query all sites.

devices, err := client.GetDevices("default")
fmt.Printf("Access points: %d\n", len(devices.UAPs))
fmt.Printf("Switches: %d\n", len(devices.USWs))

Get Flat Device List

func (c *Client) GetDeviceList(siteName, deviceType string) ([]DeviceInfo, error)

Returns a flat list of DeviceInfo structs, optionally filtered by device type. Pass empty strings to get all devices across all sites.

// All devices across all sites
allDevices, err := client.GetDeviceList("", "")

// Only access points on the default site
aps, err := client.GetDeviceList("default", "uap")

// Only switches on a specific site
switches, err := client.GetDeviceList("office", "usw")

for _, d := range allDevices {
    status := "offline"
    if d.Status == 1 {
        status = "online"
    }
    fmt.Printf("%-20s %-15s %-6s %-8s %s\n",
        d.Name, d.IP, d.Type, status, d.Version)
}

Device type codes:

Code Description
uap Wireless access points
usw Managed switches
usg Security gateways
udm Dream Machines (all-in-one)
uxg Next-generation gateways

Clients (Connected Devices)

ClientFilter Type

type ClientFilter struct {
    Site     string  // Filter by site name (empty = all sites)
    Wired    bool    // Show only wired clients
    Wireless bool    // Show only wireless clients
}

Get Connected Clients

func (c *Client) GetClients(filter ClientFilter) ([]*uf.Client, error)

Returns connected clients from the controller, optionally filtered by site and connection type. When both Wired and Wireless are false, all clients are returned.

// All clients across all sites
allClients, err := client.GetClients(unifi.ClientFilter{})

// Only wireless clients on the default site
wirelessClients, err := client.GetClients(unifi.ClientFilter{
    Site:     "default",
    Wireless: true,
})

// Only wired clients
wiredClients, err := client.GetClients(unifi.ClientFilter{
    Wired: true,
})

for _, cl := range allClients {
    fmt.Printf("%-20s %-15s %-18s\n", cl.Name, cl.IP, cl.Mac)
}

Networks

NetworkConf Type

type NetworkConf struct {
    ID                      string `json:"_id"`
    Name                    string `json:"name"`
    Purpose                 string `json:"purpose"`       // wan, corporate, remote-user-vpn
    IPSubnet                string `json:"ip_subnet"`     // CIDR (e.g. "10.69.1.1/24")
    VLAN                    int    `json:"vlan"`
    VLANEnabled             bool   `json:"vlan_enabled"`
    Enabled                 bool   `json:"enabled"`
    NetworkGroup            string `json:"networkgroup"`  // LAN, WAN, WAN2
    NetworkIsolationEnabled bool   `json:"network_isolation_enabled"`
    InternetAccessEnabled   bool   `json:"internet_access_enabled"`
    IsNAT                   bool   `json:"is_nat"`
    DHCPEnabled             bool   `json:"dhcpd_enabled"`
    DHCPStart               string `json:"dhcpd_start"`
    DHCPStop                string `json:"dhcpd_stop"`
    DHCPDNS1                string `json:"dhcpd_dns_1"`
    DHCPDNS2                string `json:"dhcpd_dns_2"`
    DHCPDNSEnabled          bool   `json:"dhcpd_dns_enabled"`
    MDNSEnabled             bool   `json:"mdns_enabled"`
    GatewayType             string `json:"gateway_type"`
    VPNType                 string `json:"vpn_type"`
    WANType                 string `json:"wan_type"`      // pppoe, dhcp, static
}

Get Networks

func (c *Client) GetNetworks(siteName string) ([]NetworkConf, error)

Returns all network configurations from the controller. Uses the raw controller REST API (/api/s/{site}/rest/networkconf). Defaults to the "default" site if siteName is empty.

networks, err := client.GetNetworks("default")
for _, net := range networks {
    fmt.Printf("%-20s %-20s VLAN:%-4d %s\n",
        net.Name, net.IPSubnet, net.VLAN, net.Purpose)
}

Routes

Route Type

type Route struct {
    Network   string `json:"pfx"`       // CIDR prefix (e.g. "10.69.1.0/24")
    NextHop   string `json:"nh"`        // Next-hop address or interface
    Interface string `json:"intf"`      // Interface name (e.g. "br0", "eth4")
    Type      string `json:"type"`      // Route type code
    Distance  int    `json:"distance"`  // Administrative distance
    Metric    int    `json:"metric"`    // Route metric
    Uptime    int    `json:"uptime"`    // Uptime in seconds
    Selected  bool   `json:"fib"`       // Whether route is in the forwarding table
}

Get Routing Table

func (c *Client) GetRoutes(siteName string) ([]Route, error)

Returns the active routing table from the gateway. Uses the raw controller REST API (/api/s/{site}/stat/routing). Defaults to the "default" site if siteName is empty.

routes, err := client.GetRoutes("default")
for _, r := range routes {
    fmt.Printf("%-20s via %-15s %-6s %s\n",
        r.Network, r.NextHop, r.Interface,
        unifi.RouteTypeName(r.Type))
}

Route Type Names

func RouteTypeName(code string) string

Converts route type codes to human-readable names:

Code Name
S static
C connected
K kernel
B bgp
O ospf

See Also

  • Home -- Package overview and quick start
  • Configuration -- Multi-source config resolution (file, env, flags)