Last active
July 30, 2022 12:59
-
-
Save danricho/5db1dfde8bdac766ed79883e20d7a483 to your computer and use it in GitHub Desktop.
Unifi API Access
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
# BASED ON ALCHEMYDC'S GREAT SCRIPT HERE: | |
# https://github.com/alchemydc/unifi_device_manager | |
# | |
# > ADDED FUNCTIONS FOR GETTING CLIENT LIST AND ACTIVE CLIENT LIST | |
# > HAD TO ADD "verify=False" TO ALL REQUESTS CALLS | |
# BECAUSE I HAVEN'T GOT A CERT SORTED IN UNIFI YET | |
# > TESTED ON CLOUD KEY GEN2 PLUS | |
# > FIRMARE: v2.0.27 | |
# > NETWORK CONTROLLER UI: v6.0.44 | |
# > NETWORK CONTROLLER BACKEND: v6.0.45 | |
import requests | |
import json | |
USERNAME = "<unifi local username>" | |
PASSWORD = "<unifi local password>" | |
BASEURL = "<unifi url>" | |
SITE = "<unifi site>" | |
# THIS IS USED TO DETERMINE IF SOMEONE IS HERE. | |
MOBILE_PHONES = { # "MAC" : "NAME" | |
"aa:bb:cc:dd:ee:ff": "Son", | |
"ff:ee:dd:cc:bb:aa": "Daughter", | |
} | |
# constants | |
LOGINURL = BASEURL + '/api/auth/login' | |
LOGOUTURL = BASEURL + '/api/auth/logout' | |
# create a custom requests object, modifying the global module throws an error | |
http = requests.Session() | |
assert_status_hook = lambda response, *args, **kwargs: response.raise_for_status() | |
http.hooks["response"] = [assert_status_hook] | |
#setup Requests to log request and response to stdout verbosely | |
http = requests.Session() | |
# set required headers | |
http.headers.update({ | |
"Content-Type": "application/json; charset=utf-8" | |
}) | |
def login(): | |
creds = json.dumps({'username': USERNAME,'password': PASSWORD}) | |
response = http.post(LOGINURL, data=creds, verify=False) | |
# new API requires the CSRF token going forward else we get 401's or 404's | |
http.headers.update({ | |
"X-CSRF-Token": response.headers['X-CSRF-Token'] | |
}) | |
def logout(): | |
response = http.post(LOGOUTURL) | |
def toggleAP(guid, action): | |
""" | |
Toggles an AP into 'disabled' mode and back. Perhaps useful for reducing RF exposure during sleep. | |
Note the guid is NOT the MAC addr of the AP. | |
To get the guid call FIXME $baseurl/api/s/$site/stat/device | |
""" | |
APURL = BASEURL + '/proxy/network/api/s/' + SITE + '/rest/device/' + guid | |
if action == "enable": | |
disableFlag = False | |
elif action == "disable": | |
disableFlag = True | |
payload = json.dumps({'disabled': disableFlag}) | |
response = http.put(APURL, data = payload, verify=False) | |
def listUsers(hours=8760): | |
""" | |
Gets a list of all clients in the given time period. | |
""" | |
APURL = BASEURL + '/proxy/network/api/s/' + SITE + '/stat/alluser' | |
payload = json.dumps({'type': 'all', 'conn': 'all', 'within': int(hours)}) | |
response = dict(http.put(APURL, data = payload, verify=False).json()) | |
return response["data"] | |
def activeUsers(): | |
""" | |
Gets a list of clients currently connected. | |
""" | |
APURL = BASEURL + '/proxy/network/api/s/' + SITE + '/stat/sta/' | |
payload = json.dumps({}) | |
response = dict(http.put(APURL, data = payload, verify=False).json()) | |
return response["data"] | |
def main(): | |
login() | |
allUsers = listUsers() | |
activeClients = activeUsers() | |
logout() | |
userDict = {} | |
print("\n------------------------------------------------------") | |
print("ALL USERS (LAST 365 DAYS)") | |
print("------------------------------------------------------") | |
for user in allUsers: | |
if "name" in user: | |
print(user["mac"], "alias: " + user["name"]) | |
elif "hostname" in user: | |
print(user["mac"], "hostname: " + user["hostname"]) | |
else: | |
print(user["mac"],"!!!unknown!!!") | |
userDict[user["mac"]] = user | |
print("\n------------------------------------------------------") | |
print("PHONES") | |
print("------------------------------------------------------") | |
for user in activeClients: | |
if user["mac"] in userDict: | |
userDict[user["mac"]]["online"] = True | |
for mac in MOBILE_PHONES: | |
if mac in userDict: | |
if "online" in userDict[mac]: | |
print(MOBILE_PHONES[mac] + " IS here.") | |
else: | |
print(MOBILE_PHONES[mac] + " IS NOT here.") | |
else: | |
print(MOBILE_PHONES[mac] + "? Never heard of 'em!") | |
print() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment