diff --git a/docs/customservices.md b/docs/customservices.md index 492e03097..7706ffd08 100644 --- a/docs/customservices.md +++ b/docs/customservices.md @@ -55,6 +55,7 @@ Available services are located in `src/components/`: - [Traefik](#traefik) - [Transmission](#transmission) - [TrueNas Scale](#truenas-scale) +- [UniFi](#unifi) - [Uptime Kuma](#uptime-kuma) - [Vaultwarden](#vaultwarden) - [Wallabag](#wallabag) @@ -754,6 +755,44 @@ Displays TrueNAS version. api_token: "<---insert-api-key-here--->" ``` +## UniFi + +Displays information from your UniFi Network Controller including connected clients, access points, and other network devices. The service automatically handles UniFi's session-based authentication and CSRF protection. + +```yaml +- name: "UniFi Controller" + logo: "assets/tools/sample.png" + url: "https://unifi.local:8443" # Your UniFi Controller URL + type: "Unifi" + auth: "username:password" # UniFi Controller credentials + site: "default" # Optional: UniFi site name (default: "default") + legacy: true # Optional: Use legacy /api/login endpoint (default: true) + updateInterval: 30000 # Optional: Refresh interval in milliseconds + target: "_blank" # Optional: HTML a tag target attribute +``` + +**Configuration Options:** + +- `auth`: Required. UniFi Controller credentials in "username:password" format +- `site`: Optional. UniFi site name to monitor (default: "default") +- `udm`: Optional. Set to `true` for UniFi Dream Machine (UDM/UDM Pro) to use `/proxy/network` prefix instead of `/manage` (default: false) +- `legacy`: Optional. Set to `false` to use modern `/api/auth/login` endpoint instead of legacy `/api/login` (default: true) +- `updateInterval`: Optional. How often to refresh data in milliseconds (default: 30000) + +**Supported UniFi Controllers:** + +- UniFi Network Controller (self-hosted) +- UniFi Dream Machine (UDM/UDM Pro) +- UniFi Cloud Key + +**Displayed Information:** + +- **Connected Clients**: Total number of wireless and wired clients connected to the network +- **Access Points**: Number of UniFi access points (UAP devices) +- **Network Devices**: Number of other UniFi network devices (switches, gateways, etc.) + +The service uses UniFi's standard API endpoints and maintains session cookies automatically. For UDM/UDM Pro devices, the service will automatically use the `/proxy/network` prefix when `udm: true` is configured. + ## Uptime Kuma Displays overall status, uptime percentage, and incident information from your Uptime Kuma status page. diff --git a/dummy-data/unifi/api/auth/login b/dummy-data/unifi/api/auth/login new file mode 100644 index 000000000..32794d941 --- /dev/null +++ b/dummy-data/unifi/api/auth/login @@ -0,0 +1,31 @@ +{ + "meta": { + "rc": "ok" + }, + "data": [ + { + "unique_id": "admin", + "first_name": "Administrator", + "last_name": "", + "full_name": "Administrator", + "email": "admin@example.com", + "email_alert_enabled": false, + "email_alert_grouping_enabled": false, + "email_alert_grouping_delay": 60, + "push_alert_enabled": false, + "is_owner": true, + "time_created": 1234567890, + "last_login_ip": "192.168.1.100", + "last_login_time": 1640995200, + "ubic_uuid": "00000000-0000-0000-0000-000000000000", + "update_id": "5f9f1c1b0000000000000000", + "permissions": [ + "admin" + ], + "scopes": [ + "admin:read", + "admin:write" + ] + } + ] +} \ No newline at end of file diff --git a/dummy-data/unifi/api/login b/dummy-data/unifi/api/login new file mode 100644 index 000000000..5e5a8fd09 --- /dev/null +++ b/dummy-data/unifi/api/login @@ -0,0 +1,24 @@ +{ + "meta": { + "rc": "ok" + }, + "data": [ + { + "unique_id": "admin", + "first_name": "Administrator", + "last_name": "", + "full_name": "Administrator", + "email": "admin@example.com", + "email_alert_enabled": false, + "email_alert_grouping_enabled": false, + "email_alert_grouping_delay": 60, + "push_alert_enabled": false, + "is_owner": true, + "time_created": 1234567890, + "last_login_ip": "192.168.1.100", + "last_login_time": 1640995200, + "ubic_uuid": "00000000-0000-0000-0000-000000000000", + "update_id": "5f9f1c1b0000000000000000" + } + ] +} \ No newline at end of file diff --git a/dummy-data/unifi/api/s/default/stat/device b/dummy-data/unifi/api/s/default/stat/device new file mode 100644 index 000000000..234d99bcb --- /dev/null +++ b/dummy-data/unifi/api/s/default/stat/device @@ -0,0 +1,350 @@ +{ + "meta": { + "rc": "ok" + }, + "data": [ + { + "_id": "5f9f1c1b0000000000000001", + "adopted": true, + "cfgversion": "0123456789abcdef", + "config_network": { + "type": "dhcp" + }, + "connect_request_ip": "192.168.1.10", + "connect_request_port": "45678", + "considered_lost_at": 1640999999, + "device_id": "5f9f1c1b0000000000000001", + "disabled": false, + "discovered_via": "l2", + "downlink_table": [], + "ethernet_table": [ + { + "mac": "aa:bb:cc:dd:ee:01", + "name": "eth0", + "num_port": 1 + } + ], + "fw_caps": 123456789, + "guest_token": "abcdefghijklmnopqrstuvwxyz123456", + "has_eth1": false, + "has_speaker": false, + "inform_ip": "192.168.1.1", + "inform_url": "http://192.168.1.1:8080/inform", + "ip": "192.168.1.10", + "last_seen": 1640995200, + "led_override": "default", + "led_override_color": "#0066cc", + "led_override_color_brightness": 100, + "mac": "aa:bb:cc:dd:ee:01", + "model": "U6-Lite", + "name": "Living Room AP", + "next_interval": 30, + "num_sta": 8, + "port_table": [], + "radio_table": [ + { + "radio": "ng", + "name": "wifi0", + "channel": 6, + "ht": 20, + "tx_power": 17, + "min_rssi_enabled": false, + "min_rssi": -79, + "sens_level_enabled": false, + "antenna_gain": 2, + "builtin_antenna": true, + "builtin_ant_gain": 2, + "nss": 2, + "radio_caps": 7679 + }, + { + "radio": "na", + "name": "wifi1", + "channel": 36, + "ht": 80, + "tx_power": 20, + "min_rssi_enabled": false, + "min_rssi": -79, + "sens_level_enabled": false, + "antenna_gain": 2, + "builtin_antenna": true, + "builtin_ant_gain": 2, + "nss": 2, + "radio_caps": 7679 + } + ], + "serial": "ABC1234567890", + "state": 1, + "type": "uap", + "uplink": { + "type": "wire", + "mac": "aa:bb:cc:dd:ee:ff", + "speed": 1000, + "full_duplex": true + }, + "uptime": 86400, + "version": "6.2.35.14526", + "wifi_caps": 123456789, + "wlangroup_id_na": "5f9f1c1b0000000000000010", + "wlangroup_id_ng": "5f9f1c1b0000000000000010" + }, + { + "_id": "5f9f1c1b0000000000000002", + "adopted": true, + "cfgversion": "0123456789abcdef", + "config_network": { + "type": "dhcp" + }, + "connect_request_ip": "192.168.1.11", + "connect_request_port": "45678", + "considered_lost_at": 1640999999, + "device_id": "5f9f1c1b0000000000000002", + "disabled": false, + "discovered_via": "l2", + "downlink_table": [], + "ethernet_table": [ + { + "mac": "aa:bb:cc:dd:ee:02", + "name": "eth0", + "num_port": 1 + } + ], + "fw_caps": 123456789, + "guest_token": "abcdefghijklmnopqrstuvwxyz123457", + "has_eth1": false, + "has_speaker": false, + "inform_ip": "192.168.1.1", + "inform_url": "http://192.168.1.1:8080/inform", + "ip": "192.168.1.11", + "last_seen": 1640995200, + "led_override": "default", + "led_override_color": "#0066cc", + "led_override_color_brightness": 100, + "mac": "aa:bb:cc:dd:ee:02", + "model": "U6-Pro", + "name": "Office AP", + "next_interval": 30, + "num_sta": 12, + "port_table": [], + "radio_table": [ + { + "radio": "ng", + "name": "wifi0", + "channel": 11, + "ht": 40, + "tx_power": 20, + "min_rssi_enabled": false, + "min_rssi": -79, + "sens_level_enabled": false, + "antenna_gain": 2, + "builtin_antenna": true, + "builtin_ant_gain": 2, + "nss": 4, + "radio_caps": 7679 + }, + { + "radio": "na", + "name": "wifi1", + "channel": 44, + "ht": 160, + "tx_power": 22, + "min_rssi_enabled": false, + "min_rssi": -79, + "sens_level_enabled": false, + "antenna_gain": 2, + "builtin_antenna": true, + "builtin_ant_gain": 2, + "nss": 4, + "radio_caps": 7679 + } + ], + "serial": "DEF1234567890", + "state": 1, + "type": "uap", + "uplink": { + "type": "wire", + "mac": "aa:bb:cc:dd:ee:ff", + "speed": 1000, + "full_duplex": true + }, + "uptime": 172800, + "version": "6.2.35.14526", + "wifi_caps": 123456789, + "wlangroup_id_na": "5f9f1c1b0000000000000010", + "wlangroup_id_ng": "5f9f1c1b0000000000000010" + }, + { + "_id": "5f9f1c1b0000000000000003", + "adopted": true, + "cfgversion": "0123456789abcdef", + "connect_request_ip": "192.168.1.2", + "connect_request_port": "45678", + "considered_lost_at": 1640999999, + "device_id": "5f9f1c1b0000000000000003", + "disabled": false, + "discovered_via": "l2", + "downlink_table": [ + { + "mac": "aa:bb:cc:dd:ee:01", + "port_idx": 1, + "speed": 1000, + "full_duplex": true + }, + { + "mac": "aa:bb:cc:dd:ee:02", + "port_idx": 2, + "speed": 1000, + "full_duplex": true + } + ], + "ethernet_table": [ + { + "mac": "aa:bb:cc:dd:ee:03", + "name": "eth0", + "num_port": 1 + } + ], + "fw_caps": 123456789, + "inform_ip": "192.168.1.1", + "inform_url": "http://192.168.1.1:8080/inform", + "ip": "192.168.1.2", + "last_seen": 1640995200, + "led_override": "default", + "led_override_color": "#0066cc", + "led_override_color_brightness": 100, + "mac": "aa:bb:cc:dd:ee:03", + "model": "USW-24-POE", + "name": "Main Switch", + "next_interval": 30, + "num_sta": 0, + "port_overrides": [], + "port_table": [ + { + "port_idx": 1, + "media": "GE", + "port_poe": true, + "poe_caps": 7, + "poe_class": "Class 0", + "poe_enable": true, + "poe_mode": "auto", + "poe_power": "8.50", + "poe_voltage": "53.40", + "portconf_id": "5f9f1c1b0000000000000020", + "autoneg": true, + "enable": true, + "flowctrl_rx": false, + "flowctrl_tx": false, + "full_duplex": true, + "is_uplink": false, + "mac_table": [ + { + "age": 0, + "authorized": true, + "hostname": "living-room-ap", + "ip": "192.168.1.10", + "mac": "aa:bb:cc:dd:ee:01", + "oui": "Ubiquiti", + "uptime": 86400, + "vlan": 1 + } + ], + "name": "Port 1", + "op_mode": "switch", + "rx_broadcast": 1234, + "rx_bytes": 123456789, + "rx_dropped": 0, + "rx_errors": 0, + "rx_multicast": 5678, + "rx_packets": 987654, + "satisfaction": 100, + "speed": 1000, + "stp_pathcost": 0, + "stp_state": "forwarding", + "tx_broadcast": 1234, + "tx_bytes": 123456789, + "tx_dropped": 0, + "tx_errors": 0, + "tx_multicast": 5678, + "tx_packets": 987654, + "up": true + } + ], + "serial": "GHI1234567890", + "state": 1, + "type": "usw", + "uplink": { + "type": "wire", + "mac": "aa:bb:cc:dd:ee:ff", + "speed": 1000, + "full_duplex": true + }, + "uptime": 259200, + "version": "6.2.35.14526" + }, + { + "_id": "5f9f1c1b0000000000000004", + "adopted": true, + "cfgversion": "0123456789abcdef", + "connect_request_ip": "192.168.1.1", + "connect_request_port": "45678", + "considered_lost_at": 1640999999, + "device_id": "5f9f1c1b0000000000000004", + "disabled": false, + "discovered_via": "l2", + "ethernet_table": [ + { + "mac": "aa:bb:cc:dd:ee:04", + "name": "eth0", + "num_port": 1 + } + ], + "fw_caps": 123456789, + "inform_ip": "192.168.1.1", + "inform_url": "http://192.168.1.1:8080/inform", + "ip": "192.168.1.1", + "last_seen": 1640995200, + "led_override": "default", + "led_override_color": "#0066cc", + "led_override_color_brightness": 100, + "mac": "aa:bb:cc:dd:ee:04", + "model": "UDM-Pro", + "name": "Dream Machine Pro", + "next_interval": 30, + "num_sta": 0, + "port_table": [ + { + "port_idx": 1, + "media": "GE", + "port_poe": false, + "portconf_id": "5f9f1c1b0000000000000021", + "autoneg": true, + "enable": true, + "flowctrl_rx": false, + "flowctrl_tx": false, + "full_duplex": true, + "is_uplink": true, + "name": "Port 1", + "op_mode": "switch", + "rx_bytes": 123456789, + "rx_dropped": 0, + "rx_errors": 0, + "rx_packets": 987654, + "satisfaction": 100, + "speed": 1000, + "stp_pathcost": 0, + "stp_state": "forwarding", + "tx_bytes": 123456789, + "tx_dropped": 0, + "tx_errors": 0, + "tx_packets": 987654, + "up": true + } + ], + "serial": "JKL1234567890", + "state": 1, + "type": "udm", + "uptime": 345600, + "version": "2.4.27.14586" + } + ] +} \ No newline at end of file diff --git a/src/components/services/Unifi.vue b/src/components/services/Unifi.vue new file mode 100644 index 000000000..b9c045bd5 --- /dev/null +++ b/src/components/services/Unifi.vue @@ -0,0 +1,205 @@ + + + + +