Unofficial UniFi Protect Python API and CLI
Project description
Unofficial UniFi Protect Python API and CLI
This module communicates with UniFi Protect Surveillance software installed on a UniFi OS Console such as a Ubiquiti CloudKey+ or UniFi Dream Machine Pro.
The API is not documented by Ubiquiti, so there might be misses and/or frequent changes in this module, as Ubiquiti evolves the software.
The module is primarily written for the purpose of being used in Home Assistant core integration for UniFi Protect but might be used for other purposes also.
Requires UniFi Protect version 1.20 or higher and Python 3.9+.
Install
pyunifiprotect
is avaible on PyPi:
pip install pyunifiprotect
CLI Usage
The unifi-protect
command is provided to give a CLI interface to interact with your UniFi Protect instance as well. All
commands support JSON output so it works great with jq
for complex scripting.
Authentication
Following traditional twelve factor app design, the perfered way to provided authentication credentials to provided environment variables, but CLI args are also supported.
Environment Variables
export UFP_USERNAME=YOUR_USERNAME_HERE
export UFP_PASSWORD=YOUR_PASSWORD_HERE
export UFP_ADDRESS=YOUR_IP_ADDRESS
export UFP_PORT=443
# change to false if you do not have a valid HTTPS Certificate for your instance
export UFP_SSL_VERIFY=True
unifi-protect nvr
CLI Args
unifi-protect -U YOUR_USERNAME_HERE -P YOUR_PASSWORD_HERE -a YOUR_IP_ADDRESS -p 443 --no-verify nvr
Docker Container
A Docker container is also provided so you do not need to install/manage Python as well. You can add the following to your .bashrc
or similar.
function unifi-protect() {
docker run --rm -it \
-e UFP_USERNAME=YOUR_USERNAME_HERE \
-e UFP_PASSWORD=YOUR_PASSWORD_HERE \
-e UFP_ADDRESS=YOUR_IP_ADDRESS \
-e UFP_PORT=443 \
-e UFP_SSL_VERIFY=True \
-v $PWD:/data ghcr.io/briis/pyunifiprotect:latest "$@"
}
Some notes about the Docker version since it is running inside of a container:
- You can update at any time using the command
docker pull ghcr.io/briis/pyunifiprotect:latest
- Your local current working directory (
$PWD
) will automatically be mounted to/data
inside of the container. For commands that output files, this is the only path you can write to and have the file persist. - The container supports
linux/amd64
andlinux/arm64
natively. This means it will also work well on MacOS or Windows using Docker Desktop.
Subcommands
The command line has a fully featured help, so the best way to discovery and learn all of the possible commands is to use unifi-protect --help
nvr
- Interact with your NVR consoleevents
- Interact various events for the NVR console (like motion/smart detection events)liveviews
- Interact with liveviewscamera
,chimes
,doorlocks
,lights
,sensors
,viewers
- Interact with specific devices on adopted by your UniFi protect instanceshell
- Interactive IPyton shell (requirespyunifiprotect[shell]
extra to be installed) with `ProtectApiClient already initalizeddecode-ws-msg
- Mostly for debug purposes to debug a base64 binary Websocket message from UniFi Protectgenerate-sample-data
- Mostly for debug purposes to generate fake data for CI / testing. Can also be used to share the current state of your UniFi Protect instance.profile-ws
- Mostly for debug purposes to profile the number of ignored/processed Websocket messages
Examples
List All Cameras
$ unifi-protect cameras list-ids
61b3f5c7033ea703e7000424: G4 Bullet
61f9824e004adc03e700132c: G4 PTZ
61be1d2f004bda03e700ab12: G4 Dome
Check if a Camera is Online
$ unifi-protect cameras 61ddb66b018e2703e7008c19 | jq .isConnected
true
Take Snapshot of Camera
$ unifi-protect cameras 61ddb66b018e2703e7008c19 save-snapshot output.jpg
Export Video From Camera
$ unifi-protect cameras 61ddb66b018e2703e7008c19 save-video export.mp4 2022-6-1T00:00:00 2022-6-1T00:00:30
Any field that takes a datetime field uses the timezone from your system locale by default. If this is not configured
correctly, it will automatically default to UTC. If you would like to override the timezone, you can use the TZ
environment variable.
For example, use America/New_York
or US East timezone:
$ TZ="America/New_York" unifi-protect cameras 61ddb66b018e2703e7008c19 save-video export.mp4 2022-6-1T00:00:00 2022-6-1T00:00:30
Play Audio File to Cameras Speaker
$ unifi-protect cameras 61ddb66b018e2703e7008c19 play-audio test.mp3
Include Unadopted Cameras in list
$ unifi-protect -u cameras list-ids
Adopt an Unadopted Camera
$ unifi-protect -u cameras 61ddb66b018e2703e7008c19 adopt
Enable SSH on Camera
$ unifi-protect cameras 61ddb66b018e2703e7008c19 set-ssh true
# get current value to verify
$ unifi-protect cameras 61ddb66b018e2703e7008c19 | jq .isSshEnabled
true
Reboot Flood Light
$ unifi-protect lights 61b3f5c801f8a703e7000428 reboot
Reboot All Cameras
for id in $(unifi-protect cameras list-ids | awk '{ print $1 }'); do
unifi-protect cameras $id reboot
done
Library Usage
UniFi Protect itself is 100% async, so as such this library is primarily designed to be used in an async context.
The main interface for the library is the pyunifiprotect.ProtectApiClient
:
from pyunifiprotect import ProtectApiClient
protect = ProtectApiClient(host, port, username, password, verify_ssl=True)
await protect.update() # this will initalize the protect .bootstrap and open a Websocket connection for updates
# get names of your cameras
for camera in protect.bootstrap.cameras.values():
print(camera.name)
# subscribe to Websocket for updates to UFP
def callback(msg: WSSubscriptionMessage):
# do stuff
unsub = protect.subscribe_websocket(callback)
# remove subscription
unsub()
TODO / Planned / Not Implemented
The following the noticble features are that still missing from pyunifiprotect. All of them are planned for "some day" / "nice to have" except where noted.
- Animated thumbnails for events
- Timelapse video exporting
- Liveview creating/updating/deleting
- PTZ controls
- Creating WebRTC streaming connections
- Backups
- Device Groups
- Record Scheduling
- Battery powered cameras (G3 Battery, Aplify Vision)
- Camera analytics and live heatmaps
- Reconfiguring WiFi
- "Locate" feature for Lights/Sensors/Doorlocks
- The
/timeline
API endpoint - User/Group/Permission management -- partially implemented as users and groups are modeled, just not fleshed out
- Any strictly UniFi OS feature like managing RAID, creating users, etc. -- Out of Scope. If it ever done, it will be in a seperate library that interacts with this one
Development
Setup
Development with this project is designed to be done via VS Code + Docker. It is a pretty standard Python package, so feel free to use anything else, but all documentation assumes you are using VS Code.
- VS Code + Remote Containers extension
- Docker
- If you are using Linux, you need Docker Engine 19.0 or newer and you need to enable Docker Buildkit
- If you are using Docker Desktop on MacOS or Winows, you will need Docker Desktop 3.2.0 or newer
Once you have all three setup,
- Clone repo
- Open the main folder
- You should be prompted to "Reopen folder to develop in a container". If you are not, you can open the Command Palette run the "Remote-Containers: Reopen in Container" command.
This should be all you need to do to get a working development environment. The docker container will automatically be build and VS Code will attach itself to it. The integrated terminal in VS Code will already be set up with the unifi-protect
command.
Authenticating with your Local Protect Instance
The project allows you to create an environment file to put your local protect instance data into so you do not need to constantly enter in or accidentally commit it to the Git repo.
Make a file in the root of the project named .env
with the following and change accordingly:
UFP_USERNAME=YOUR_USERNAME_HERE
UFP_PASSWORD=YOUR_PASSWORD_HERE
UFP_ADDRESS=YOUR_IP_ADDRESS
UFP_PORT=443
# change to false if you do not have a valid HTTPS Certificate for your instance
UFP_SSL_VERIFY=True
Generating Test Data
All of the tests in the project are ran against that is generated from a real UniFi Protect instance and then anonymized so it is safe to commit to a Git repo. To generate new sample test data:
unifi-protect generate-sample-data
This will gather test data for 30 seconds and write it all into the tests/sample_data
directory. During this time, it is a good idea to generate some good events that can tested. An example would be to generate a motion event for a FloodLight, Camera and/or Doorbell and then also ring a Doorbell.
Linting and Testing
The following scripts exist to easily format, lint and test code in the same fashion as CI:
.bin/format-code
.bin/lint-code
.bin/test-code
Updating Requirements
To generate an updated pinned requirements file to be used for testing and CI using the .bin/update-requirements
script.
There is also a VS Code task to run this as well.
VS Code Integration
Tests can also be ran directly from within VS Code using the testing side panel.
Generating and Testing with Real Data
You can also generate and run tests against real non-anonymized data to help troubleshoot issues and see real results. You can also increase the gather time for events to give you more time to generate events for testing as well.
export UFP_SAMPLE_DIR=/workspaces/pyunifiprotect/test-data
unifi-protect generate-sample-data -w 300 --actual
You can then make pytest
use this real data as well:
export UFP_SAMPLE_DIR=/workspaces/pyunifiprotect/test-data
pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for pyunifiprotect-4.0.6-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c377a09ee5e0cd4916c5bc8d0a1c4180f869586f04734131a1579cd3db538b19 |
|
MD5 | e47ca61501ab6c0db037ceca9e1eb027 |
|
BLAKE2b-256 | 1e3adaec01b66ab17e3e49de02545fd161bfffb5cd8b7d41a3635ac5c407468a |