Monitoring your Unifi AP

The default Unifi AP integration is great for the presence detection part of your network.

I wanted to have a Unifi dashboard, with more info such as CPU, RAM, number of connected clients etc.
I recently found out this great python module with which you can pretty much access any info on your AP.

I wrote a python script that pulls some information using the above mentioned module:

from unificontrol import UnifiClient
from datetime import timedelta
import json

#### fill in your unifi controller credentials ####

host = ''
username = ''
password = ''
site = ''  
port = ''
mac = '' ## the mac address of your AP device

#### endpoints ####

client = UnifiClient(host=host,username=username,password=password,site=site,port=port)
stat = client.stat_sysinfo()
devs = client.list_devices(mac)
clients = client.list_clients()
guests = client.list_guests()

### supposed that you use both 2.4 and 5 ghz frequencies there should be wifi0 and wifi1, else edit accordingly

numclients = len(clients)
numguests = len(guests)
wifi0clients = []
wifi1clients = [] 
score = int(devs[0]['satisfaction'])
update = str(stat[0]['update_available'])
cpu = float(devs[0]['system-stats']['cpu'])
ram = float(devs[0]['system-stats']['mem'])
wifi0score = int(devs[0]['radio_table_stats'][0]['satisfaction'])
wifi1score = int(devs[0]['radio_table_stats'][1]['satisfaction'])

activity = float(round(devs[0]['uplink']['rx_bytes-r']/125000 + devs[0]['uplink']['tx_bytes-r']/125000,1))
seconds = int(devs[0]['uptime'])
days = seconds // 86400
hours = (seconds - (days * 86400)) // 3600
minutes = (seconds - (days * 86400) - (hours * 3600)) // 60
uptime = str(days)+'d '+str(hours)+'h '+str(minutes)+'m'

for i in [i for i,x in enumerate(clients) if (mac in str(x) and 'wifi0' in str(x))]:
    try:
        wifi0clients.append(clients[i]['name'])
    except:
        wifi0clients.append(clients[i]['mac'])  

for i in [i for i,x in enumerate(clients) if (mac in str(x) and 'wifi1' in str(x))]:
    try:
        wifi1clients.append(clients[i]['name'])
    except:
        wifi1clients.append(clients[i]['mac'])  

final = json.dumps({"Clients":numclients,"Guests":numguests,"Clients_wifi0":wifi0clients ,"Clients_wifi1":wifi1clients ,"Score":score,"CPU":str(cpu),"RAM":str(ram),"Uptime":uptime,"Score_wifi0":wifi0score ,"Score_wifi1":wifi1score ,\
                "Activity":str(activity)+' Mbps',"Update":update})

print (final)
                            

Afterwards, add a new command_line sensor on your configuration.yaml with the following:

- platform: command_line
  command: 'C:\Users\Administrator\AppData\Roaming\.homeassistant\python\unifi.py'
  name: unifi_ap
  value_template: '{{ value_json.Clients }}'
  unit_of_measurement: Clients
  scan_interval: 60
  json_attributes:
      - Guests
      - Clients_wifi0
      - Clients_wifi1
      - Score  
      - CPU
      - RAM
      - Uptime
      - Score_wifi0
      - Score_wifi1
      - Activity
      - Update

Remember to edit the command part to point it to the location where you saved the script.

Finally, you can make various template sensors to extract info such as CPU, RAM etc

For example,

- platform: template
  sensors:  
    unifi_ap_activity:
        value_template: >
            {{ states.sensor.unifi_ap.attributes.Activity }}
        unit_of_measurement: 'Mbps'
        friendly_name_template: Unifi AP Activity      
    unifi_ap_ram:
        value_template: >
            {{ states.sensor.unifi_ap.attributes.RAM }}
        unit_of_measurement: '%'
        friendly_name_template: Unifi AP RAM    
    unifi_ap_cpu:
        value_template: >
            {{ states.sensor.unifi_ap.attributes.CPU }}
        unit_of_measurement: '%'
        friendly_name_template: Unifi AP CPU

And here’s the final product

unifi

Of course the unificontrol module has many more possible sensors you can extract, so be sure to check the docs and big thanks to the developer.

28 Likes

Sounds pretty neat . I’ll have a look as a have 1 dram machine and 3 ap running. Maybe we can extend this with switches for reconnect clients or whatever.

I’ll have a look later what information I wanna pull

Hi,

Would you share your card config?

Thanks.

@revin Sure. It is an entities card, mostly based on the multiple-entity-row and the mini-graph-card:

type: entities
entities:
  - type: 'custom:multiple-entity-row'
    entity: sensor.unifi_ap
    name: Unifi AP
    show_entity_picture: true
    show_state: false
    secondary_info:
      attribute: Uptime
    entities:
      - entity: sensor.unifi_ap_cpu
        name: CPU
      - entity: sensor.unifi_ap_ram
        name: RAM
      - icon: 'mdi:restart'
        tap_action:
          action: call-service
          confirmation: true
          service: shell_command.reboot_ap_ac_lite
  - type: 'custom:multiple-entity-row'
    entity: sensor.unifi_ap
    icon: 'mdi:devices'
    name: ' '
    show_state: false
    secondary_info:
      entity: sensor.unifi_ap
      name: ' '
    entities:
      - entity: sensor.home_wifi_devices
        name: 2.4GhZ
        unit: ' '
      - entity: sensor.home5ghz_wifi_devices
        name: 5GhZ
        unit: ' '
      - entity: sensor.homenot_clients
        name: NoT
        unit: ' '
  - type: 'custom:multiple-entity-row'
    entity: sensor.unifi_ap_score
    name: ' '
    icon: 'mdi:percent-outline'
    show_state: false
    secondary_info:
      entity: sensor.unifi_ap_score
      name: ' '
      unit: '% satisfaction'
    entities:
      - entity: sensor.unifi_ap
        attribute: 2gHz
        name: 2gHz
        unit: '%'
        tap_action:
          action: none
      - entity: sensor.unifi_ap
        attribute: 5gHz
        name: 5gHz
        unit: '%'
        tap_action:
          action: none
  - type: 'custom:mini-graph-card'
    entities:
      - entity: sensor.unifi_ap_score
    group: true
    font_size: 85
    hours_to_show: 24
    style: |
      ha-card {
        border-radius: 0px;
        box-shadow: none;
        } 
    show:
      icon: false
      graph: false
      name: false
      state: false
      extrema: true
      average: true
  - type: 'custom:multiple-entity-row'
    entity: sensor.unifi_ap_activity
    name: Activity
    show_state: false
    icon: 'mdi:arrow-up-down'
    secondary_info:
      entity: sensor.unifi_ap_activity
      name: ' '
      unit: ' '
    entities:
      - entity: sensor.unifi_ap
        attribute: Update
        name: New Update
  - type: 'custom:mini-graph-card'
    entities:
      - entity: sensor.unifi_ap_activity
    group: true
    hours_to_show: 4
    line_width: 3
    points_per_hour: 15
    show:
      icon: false
      name: false
      state: false
      labels: true

3 Likes

hi @valvex

Thanks!

I’ve tried the python but it gives me an error:

admin@hass:~/hass/scripts$ python3 unifi_ap_1.py
Traceback (most recent call last):
  File "unifi_ap_1.py", line 28, in <module>
    clientlist = ",".join([str([x][0]['name']) for x in client.list_clients()])
  File "unifi_ap_1.py", line 28, in <listcomp>
    clientlist = ",".join([str([x][0]['name']) for x in client.list_clients()])
KeyError: 'name'

@revin
This line is supposed to give you a list with all the connected clients names.
If you have not specified any names for your clients in your Unifi dashboard, maybe that’s why this key is missing.

Try replacing it with this line, to get a list of the mac addresses.

clientlist = ",".join([str([x][0]['mac']) for x in client.list_clients()])

@valvex
If I go to that controller view, I see all the names. Maybe it’s a version issue as I’m using a very old controller version (5.13.32). will try to update later and report.

BTW, It works perfecto with mac address list.

Hi @valvex

I’ve updated APs and Controller but error remains trying to obtain full name list. From my side, it’s not a problem as I’m not interested on Mac/name list.

I’ve some APs and I obtain the same number of clients on all APs. Is it possible to see only the clients on the AP?

Thanks for sharing the code!

Would it be possible to get a custom_pomponen for this?

1 Like

Thank you for sharing this script.
I have 3 APs. To add their macs, do i add them with coma separation?

mac = '' ## the mac address of your AP device

Hola @juan11perez ,

I’m on the same boat as I also have 3 APs. I’m using 3 different python scripts.

Hi @revin. I’ve updated the code in the first post.

Try replacing

numclients = health[0]['num_user']

with

numclients = len(clients)

And see if it is solved.

@thundergreen Sure it is, but I am not that experienced in python to build it myself.

@juan11perez After having read the docs of the module’s developer, I do not think you can read 3 APs with the same script. So it is better to make 3 different scripts.

Thank you for your help

will this automaticall download the library? u use this library if i well understand from unificontrol import UnifiClient

any helo here? Getting this error:

bash-5.0# python3 unifi.py 
Traceback (most recent call last):
  File "unifi.py", line 18, in <module>
    stat = client.stat_sysinfo()
  File "/usr/local/lib/python3.8/site-packages/unificontrol/metaprogram.py", line 125, in wrapper
    return instance(client, *a, **kw)
  File "/usr/local/lib/python3.8/site-packages/unificontrol/metaprogram.py", line 103, in __call__
    return client._execute(url, self._method, rest_dict, need_login=self._need_login)
  File "/usr/local/lib/python3.8/site-packages/unificontrol/unifi.py", line 110, in _execute
    response = resp.json()
  File "/usr/local/lib/python3.8/site-packages/requests/models.py", line 900, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/simplejson/__init__.py", line 525, in loads
    return _default_decoder.decode(s)
  File "/usr/local/lib/python3.8/site-packages/simplejson/decoder.py", line 370, in decode
    obj, end = self.raw_decode(s)
  File "/usr/local/lib/python3.8/site-packages/simplejson/decoder.py", line 400, in raw_decode
    return self.scan_once(s, idx=_w(s, idx).end())
simplejson.errors.JSONDecodeError: Expecting value: line 2 column 1 (char 1)

my config:

host = '192.168.1.1'
username = 'hassio'
password = 'HassIo123'
site = 'default'  
port = '443'
mac = 'E0:63:DA:CE:08:C1' ## the mac address of your AP device

Hi @thundergreen ,

I downloaded manually the module, copied to the same script directory and added this lines to the script:

import sys
sys.path.append('/config/scripts/modules/')
1 Like

Can you please prcie exactly what u did? I fear i dit not understand well :frowning: Dos it work for you? I am running

6.0.43.0 << network controller on UDM 1.8.5 firmware

@thundergreen,

at least for me, it didn’t download the module automatically. I’m running the first version of the script.

So these are the steps I followed:

  1. copied the python script to /config/scripts/ several times as I have 3 APs (UniFi_ap_1.py, UniFi_ap_2.py and unifi_ap_3.py
  2. I downloaded the module (pip3 install unificontrol) on another server and copied the files to /config/scripts/module/

  1. add these lines to each python script:
import sys
sys.path.append('/config/scripts/modules/')

aaa all right … nice way to solve depencies problem but I get those connection or json errors. :frowning:

You will have to pip3 install unificontrol the module first.
As for the other part, I am running home assistant core on windows, so i cannot really help if you’re running the hassOs on raspberry pi etc. as I have zero experience with that. Sorry.

Also, I’ve updated the script in the first post, so check if this solves any problems. Make sure to read the whole script and perhaps comment out anything that might not work for you.

@revin Hey, have you tried with my suggested edit numclients = len(clients) to see if the clients are reported correctly?

I only have one AP so I cannot really test your situation.
After reading the developer’s docs, I assume that this change will only return the clients per AP.