uiprotect 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of uiprotect might be problematic. Click here for more details.

Files changed (36) hide show
  1. uiprotect-0.1.0/LICENSE +23 -0
  2. uiprotect-0.1.0/PKG-INFO +245 -0
  3. uiprotect-0.1.0/README.md +205 -0
  4. uiprotect-0.1.0/pyproject.toml +192 -0
  5. uiprotect-0.1.0/src/uiprotect/__init__.py +13 -0
  6. uiprotect-0.1.0/src/uiprotect/__main__.py +24 -0
  7. uiprotect-0.1.0/src/uiprotect/api.py +1936 -0
  8. uiprotect-0.1.0/src/uiprotect/cli/__init__.py +314 -0
  9. uiprotect-0.1.0/src/uiprotect/cli/backup.py +1103 -0
  10. uiprotect-0.1.0/src/uiprotect/cli/base.py +238 -0
  11. uiprotect-0.1.0/src/uiprotect/cli/cameras.py +574 -0
  12. uiprotect-0.1.0/src/uiprotect/cli/chimes.py +180 -0
  13. uiprotect-0.1.0/src/uiprotect/cli/doorlocks.py +125 -0
  14. uiprotect-0.1.0/src/uiprotect/cli/events.py +258 -0
  15. uiprotect-0.1.0/src/uiprotect/cli/lights.py +119 -0
  16. uiprotect-0.1.0/src/uiprotect/cli/liveviews.py +65 -0
  17. uiprotect-0.1.0/src/uiprotect/cli/nvr.py +154 -0
  18. uiprotect-0.1.0/src/uiprotect/cli/sensors.py +278 -0
  19. uiprotect-0.1.0/src/uiprotect/cli/viewers.py +76 -0
  20. uiprotect-0.1.0/src/uiprotect/data/__init__.py +157 -0
  21. uiprotect-0.1.0/src/uiprotect/data/base.py +1116 -0
  22. uiprotect-0.1.0/src/uiprotect/data/bootstrap.py +634 -0
  23. uiprotect-0.1.0/src/uiprotect/data/convert.py +77 -0
  24. uiprotect-0.1.0/src/uiprotect/data/devices.py +3384 -0
  25. uiprotect-0.1.0/src/uiprotect/data/nvr.py +1520 -0
  26. uiprotect-0.1.0/src/uiprotect/data/types.py +630 -0
  27. uiprotect-0.1.0/src/uiprotect/data/user.py +236 -0
  28. uiprotect-0.1.0/src/uiprotect/data/websocket.py +236 -0
  29. uiprotect-0.1.0/src/uiprotect/exceptions.py +41 -0
  30. uiprotect-0.1.0/src/uiprotect/py.typed +0 -0
  31. uiprotect-0.1.0/src/uiprotect/release_cache.json +1 -0
  32. uiprotect-0.1.0/src/uiprotect/stream.py +166 -0
  33. uiprotect-0.1.0/src/uiprotect/test_util/__init__.py +531 -0
  34. uiprotect-0.1.0/src/uiprotect/test_util/anonymize.py +257 -0
  35. uiprotect-0.1.0/src/uiprotect/utils.py +610 -0
  36. uiprotect-0.1.0/src/uiprotect/websocket.py +225 -0
@@ -0,0 +1,23 @@
1
+
2
+ MIT License
3
+
4
+ Copyright (c) 2024 UI Protect Maintainers
5
+ Copyright (c) 2020 Bjarne Riis
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ of this software and associated documentation files (the "Software"), to deal
9
+ in the Software without restriction, including without limitation the rights
10
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the Software is
12
+ furnished to do so, subject to the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included in all
15
+ copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
+ SOFTWARE.
@@ -0,0 +1,245 @@
1
+ Metadata-Version: 2.1
2
+ Name: uiprotect
3
+ Version: 0.1.0
4
+ Summary: Python API for Unifi Protect (Unofficial)
5
+ Home-page: https://github.com/uilibs/uiprotect
6
+ License: MIT
7
+ Author: UI Protect Maintainers
8
+ Author-email: ui@koston.org
9
+ Requires-Python: >=3.10
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries
20
+ Requires-Dist: aiofiles (>=23)
21
+ Requires-Dist: aiohttp (>=3.9.0)
22
+ Requires-Dist: aioshutil (>=1.3)
23
+ Requires-Dist: async-timeout (>=3.0.1)
24
+ Requires-Dist: dateparser (>=1.1.0)
25
+ Requires-Dist: orjson (>=3.9)
26
+ Requires-Dist: packaging (>=23)
27
+ Requires-Dist: pillow (>=10)
28
+ Requires-Dist: platformdirs (>=4)
29
+ Requires-Dist: pydantic (!=1.9.1)
30
+ Requires-Dist: pyjwt (>=2.6)
31
+ Requires-Dist: rich (>=10)
32
+ Requires-Dist: typer[all] (>0.6)
33
+ Requires-Dist: yarl (>=1.9)
34
+ Project-URL: Bug Tracker, https://github.com/uilibs/uiprotect/issues
35
+ Project-URL: Changelog, https://github.com/uilibs/uiprotect/blob/main/CHANGELOG.md
36
+ Project-URL: Documentation, https://uiprotect.readthedocs.io
37
+ Project-URL: Repository, https://github.com/uilibs/uiprotect
38
+ Description-Content-Type: text/markdown
39
+
40
+ # Unofficial UniFi Protect Python API and CLI
41
+
42
+ <p align="center">
43
+ <a href="https://github.com/uilibs/uiprotect/actions/workflows/ci.yml?query=branch%3Amain">
44
+ <img src="https://img.shields.io/github/actions/workflow/status/uilibs/uiprotect/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
45
+ </a>
46
+ <a href="https://uiprotect.readthedocs.io">
47
+ <img src="https://img.shields.io/readthedocs/uiprotect.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">
48
+ </a>
49
+ <a href="https://codecov.io/gh/uilibs/uiprotect">
50
+ <img src="https://img.shields.io/codecov/c/github/uilibs/uiprotect.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
51
+ </a>
52
+ </p>
53
+ <p align="center">
54
+ <a href="https://python-poetry.org/">
55
+ <img src="https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json" alt="Poetry">
56
+ </a>
57
+ <a href="https://github.com/astral-sh/ruff">
58
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
59
+ </a>
60
+ <a href="https://github.com/pre-commit/pre-commit">
61
+ <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">
62
+ </a>
63
+ </p>
64
+ <p align="center">
65
+ <a href="https://pypi.org/project/uiprotect/">
66
+ <img src="https://img.shields.io/pypi/v/uiprotect.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
67
+ </a>
68
+ <img src="https://img.shields.io/pypi/pyversions/uiprotect.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
69
+ <img src="https://img.shields.io/pypi/l/uiprotect.svg?style=flat-square" alt="License">
70
+ </p>
71
+
72
+ ---
73
+
74
+ **Documentation**: <a href="https://uiprotect.readthedocs.io" target="_blank">https://uiprotect.readthedocs.io </a>
75
+
76
+ **Source Code**: <a href="https://github.com/uilibs/uiprotect" target="_blank">https://github.com/uilibs/uiprotect </a>
77
+
78
+ ---
79
+
80
+ Python API for Unifi Protect (Unofficial)
81
+
82
+ ## Installation
83
+
84
+ Install this via pip (or your favorite package manager):
85
+
86
+ `pip install uiprotect`
87
+
88
+ ## Credits
89
+
90
+ - Bjarne Riis ([@briis](https://github.com/briis/)) for the original pyunifiprotect package
91
+ - Christopher Bailey ([@AngellusMortis](https://github.com/AngellusMortis/)) for the maintaining the pyunifiprotect package
92
+
93
+ ## Contributors ✨
94
+
95
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
96
+
97
+ <!-- prettier-ignore-start -->
98
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
99
+ <!-- markdownlint-disable -->
100
+ <!-- markdownlint-enable -->
101
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
102
+ <!-- prettier-ignore-end -->
103
+
104
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
105
+
106
+ `uiprotect` is an unofficial API for UniFi Protect. There is no affiliation with Ubiquiti.
107
+
108
+ This module communicates with UniFi Protect surveillance software installed on a UniFi OS Console such as a Ubiquiti CloudKey+ or UniFi Dream Machine Pro.
109
+
110
+ The API is not documented by Ubiquiti, so there might be misses and/or frequent changes in this module, as Ubiquiti evolves the software.
111
+
112
+ The module is primarily written for the purpose of being used in Home Assistant core [integration for UniFi Protect](https://www.home-assistant.io/integrations/unifiprotect) but might be used for other purposes also.
113
+
114
+ ## Smart Detections now Require Remote Access to enable
115
+
116
+ Smart Detections (person, vehicle, animal, face), a feature that previously could be used with local only console, [now requires you to enable remote access to enable](https://community.ui.com/questions/Cannot-enable-Smart-Detections/e3d50641-5c00-4607-9723-453cda557e35#answer/1d146426-89aa-4022-a0ae-fd5000846028).
117
+
118
+ Enabling Remote Access may grant other users access to your console [due to the fact Ubiquiti can reconfigure access controls at any time](https://community.ui.com/questions/Bug-Fix-Cloud-Access-Misconfiguration/fe8d4479-e187-4471-bf95-b2799183ceb7).
119
+
120
+ If you are not okay with the feature being locked behind Remote Access access, [let Ubiquiti know](https://community.ui.com/questions/Cannot-enable-Smart-Detections/e3d50641-5c00-4607-9723-453cda557e35).
121
+
122
+ ## Documentation
123
+
124
+ [Full documentation for the project](https://uilibs.github.io/uiprotect/).
125
+
126
+ ## Requirements
127
+
128
+ If you want to install `uiprotect` natively, the below are the requirements:
129
+
130
+ - [UniFi Protect](https://ui.com/camera-security) version 1.20+
131
+ - Latest version of library is generally only tested against the two latest minor version. This is either two latest stable versions (such as 1.21.x and 2.0.x) or the latest EA version and stable version (such as 2.2.x EA and 2.1.x).
132
+ - [Python](https://www.python.org/) 3.9+
133
+ - POSIX compatible system
134
+ - Library is only test on Linux, specifically the latest Debian version available for the official Python Docker images, but there is no reason the library should not work on any Linux distro or MacOS.
135
+ - [ffmpeg](https://ffmpeg.org/)
136
+ - ffmpeg is primarily only for streaming audio to Protect cameras, this can be considered a soft requirement
137
+
138
+ Alternatively you can use the [provided Docker container](#using-docker-container), in which case the only requirement is [Docker](https://docs.docker.com/desktop/) or another OCI compatible orchestrator (such as Kubernetes or podman).
139
+
140
+ Windows is **not supported**. If you need to use `uiprotect` on Windows, use Docker Desktop and the provided docker container or [WSL](https://docs.microsoft.com/en-us/windows/wsl/install).
141
+
142
+ ## Install
143
+
144
+ ### From PyPi
145
+
146
+ `uiprotect` is available on PyPi:
147
+
148
+ ```bash
149
+ pip install uiprotect
150
+ ```
151
+
152
+ ### From Github
153
+
154
+ ```bash
155
+ pip install git+https://github.com/uilibs/uiprotect.git#egg=uiprotect
156
+ ```
157
+
158
+ ### Using Docker Container
159
+
160
+ 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.
161
+
162
+ ```bash
163
+ function unifi-protect() {
164
+ docker run --rm -it \
165
+ -e UFP_USERNAME=YOUR_USERNAME_HERE \
166
+ -e UFP_PASSWORD=YOUR_PASSWORD_HERE \
167
+ -e UFP_ADDRESS=YOUR_IP_ADDRESS \
168
+ -e UFP_PORT=443 \
169
+ -e UFP_SSL_VERIFY=True \
170
+ -e TZ=America/New_York \
171
+ -v $PWD:/data ghcr.io/uilibs/uiprotect:latest "$@"
172
+ }
173
+ ```
174
+
175
+ Some notes about the Docker version since it is running inside of a container:
176
+
177
+ - You can update at any time using the command `docker pull ghcr.io/uilibs/uiprotect:latest`
178
+ - 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.
179
+ - The container supports `linux/amd64` and `linux/arm64` natively. This means it will also work well on MacOS or Windows using Docker Desktop.
180
+ - `TZ` should be the [Olson timezone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the timezone your UniFi Protect instance is in.
181
+ - For more details on `TZ` and other environment variables, check the [command line docs](https://uilibs.github.io/uiprotect/latest/cli/)
182
+
183
+ ## Quickstart
184
+
185
+ ### CLI
186
+
187
+ !!! warning "About Ubiquiti SSO accounts"
188
+ Ubiquiti SSO accounts are not supported and actively discouraged from being used. There is no option to use MFA. You are expected to use local access user. `uiprotect` is not designed to allow you to use your owner account to access the your console or to be used over the public Internet as both pose a security risk.
189
+
190
+ ```bash
191
+ export UFP_USERNAME=YOUR_USERNAME_HERE
192
+ export UFP_PASSWORD=YOUR_PASSWORD_HERE
193
+ export UFP_ADDRESS=YOUR_IP_ADDRESS
194
+ export UFP_PORT=443
195
+ # change to false if you do not have a valid HTTPS Certificate for your instance
196
+ export UFP_SSL_VERIFY=True
197
+
198
+ unifi-protect --help
199
+ unifi-protect nvr
200
+ ```
201
+
202
+ ### Python
203
+
204
+ UniFi Protect itself is 100% async, so as such this library is primarily designed to be used in an async context.
205
+
206
+ The main interface for the library is the `uiprotect.ProtectApiClient`:
207
+
208
+ ```python
209
+ from uiprotect import ProtectApiClient
210
+
211
+ protect = ProtectApiClient(host, port, username, password, verify_ssl=True)
212
+
213
+ await protect.update() # this will initialize the protect .bootstrap and open a Websocket connection for updates
214
+
215
+ # get names of your cameras
216
+ for camera in protect.bootstrap.cameras.values():
217
+ print(camera.name)
218
+
219
+ # subscribe to Websocket for updates to UFP
220
+ def callback(msg: WSSubscriptionMessage):
221
+ # do stuff
222
+
223
+ unsub = protect.subscribe_websocket(callback)
224
+
225
+ # remove subscription
226
+ unsub()
227
+
228
+ ```
229
+
230
+ ## TODO / Planned / Not Implemented
231
+
232
+ Generally any feature missing from the library is planned to be done eventually / nice to have with the following exceptions
233
+
234
+ ### UniFi OS Features
235
+
236
+ Anything that is strictly a UniFi OS feature. If it ever done, it will be in a separate library that interacts with this one. Examples include:
237
+
238
+ - Managing RAID and disks
239
+ - Creating and managing users
240
+
241
+ Examples include:
242
+
243
+ - Stream sharing
244
+ - Smart Detections, including person, vehicle, animals license plate and faces
245
+
@@ -0,0 +1,205 @@
1
+ # Unofficial UniFi Protect Python API and CLI
2
+
3
+ <p align="center">
4
+ <a href="https://github.com/uilibs/uiprotect/actions/workflows/ci.yml?query=branch%3Amain">
5
+ <img src="https://img.shields.io/github/actions/workflow/status/uilibs/uiprotect/ci.yml?branch=main&label=CI&logo=github&style=flat-square" alt="CI Status" >
6
+ </a>
7
+ <a href="https://uiprotect.readthedocs.io">
8
+ <img src="https://img.shields.io/readthedocs/uiprotect.svg?logo=read-the-docs&logoColor=fff&style=flat-square" alt="Documentation Status">
9
+ </a>
10
+ <a href="https://codecov.io/gh/uilibs/uiprotect">
11
+ <img src="https://img.shields.io/codecov/c/github/uilibs/uiprotect.svg?logo=codecov&logoColor=fff&style=flat-square" alt="Test coverage percentage">
12
+ </a>
13
+ </p>
14
+ <p align="center">
15
+ <a href="https://python-poetry.org/">
16
+ <img src="https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json" alt="Poetry">
17
+ </a>
18
+ <a href="https://github.com/astral-sh/ruff">
19
+ <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff">
20
+ </a>
21
+ <a href="https://github.com/pre-commit/pre-commit">
22
+ <img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" alt="pre-commit">
23
+ </a>
24
+ </p>
25
+ <p align="center">
26
+ <a href="https://pypi.org/project/uiprotect/">
27
+ <img src="https://img.shields.io/pypi/v/uiprotect.svg?logo=python&logoColor=fff&style=flat-square" alt="PyPI Version">
28
+ </a>
29
+ <img src="https://img.shields.io/pypi/pyversions/uiprotect.svg?style=flat-square&logo=python&amp;logoColor=fff" alt="Supported Python versions">
30
+ <img src="https://img.shields.io/pypi/l/uiprotect.svg?style=flat-square" alt="License">
31
+ </p>
32
+
33
+ ---
34
+
35
+ **Documentation**: <a href="https://uiprotect.readthedocs.io" target="_blank">https://uiprotect.readthedocs.io </a>
36
+
37
+ **Source Code**: <a href="https://github.com/uilibs/uiprotect" target="_blank">https://github.com/uilibs/uiprotect </a>
38
+
39
+ ---
40
+
41
+ Python API for Unifi Protect (Unofficial)
42
+
43
+ ## Installation
44
+
45
+ Install this via pip (or your favorite package manager):
46
+
47
+ `pip install uiprotect`
48
+
49
+ ## Credits
50
+
51
+ - Bjarne Riis ([@briis](https://github.com/briis/)) for the original pyunifiprotect package
52
+ - Christopher Bailey ([@AngellusMortis](https://github.com/AngellusMortis/)) for the maintaining the pyunifiprotect package
53
+
54
+ ## Contributors ✨
55
+
56
+ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
57
+
58
+ <!-- prettier-ignore-start -->
59
+ <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
60
+ <!-- markdownlint-disable -->
61
+ <!-- markdownlint-enable -->
62
+ <!-- ALL-CONTRIBUTORS-LIST:END -->
63
+ <!-- prettier-ignore-end -->
64
+
65
+ This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
66
+
67
+ `uiprotect` is an unofficial API for UniFi Protect. There is no affiliation with Ubiquiti.
68
+
69
+ This module communicates with UniFi Protect surveillance software installed on a UniFi OS Console such as a Ubiquiti CloudKey+ or UniFi Dream Machine Pro.
70
+
71
+ The API is not documented by Ubiquiti, so there might be misses and/or frequent changes in this module, as Ubiquiti evolves the software.
72
+
73
+ The module is primarily written for the purpose of being used in Home Assistant core [integration for UniFi Protect](https://www.home-assistant.io/integrations/unifiprotect) but might be used for other purposes also.
74
+
75
+ ## Smart Detections now Require Remote Access to enable
76
+
77
+ Smart Detections (person, vehicle, animal, face), a feature that previously could be used with local only console, [now requires you to enable remote access to enable](https://community.ui.com/questions/Cannot-enable-Smart-Detections/e3d50641-5c00-4607-9723-453cda557e35#answer/1d146426-89aa-4022-a0ae-fd5000846028).
78
+
79
+ Enabling Remote Access may grant other users access to your console [due to the fact Ubiquiti can reconfigure access controls at any time](https://community.ui.com/questions/Bug-Fix-Cloud-Access-Misconfiguration/fe8d4479-e187-4471-bf95-b2799183ceb7).
80
+
81
+ If you are not okay with the feature being locked behind Remote Access access, [let Ubiquiti know](https://community.ui.com/questions/Cannot-enable-Smart-Detections/e3d50641-5c00-4607-9723-453cda557e35).
82
+
83
+ ## Documentation
84
+
85
+ [Full documentation for the project](https://uilibs.github.io/uiprotect/).
86
+
87
+ ## Requirements
88
+
89
+ If you want to install `uiprotect` natively, the below are the requirements:
90
+
91
+ - [UniFi Protect](https://ui.com/camera-security) version 1.20+
92
+ - Latest version of library is generally only tested against the two latest minor version. This is either two latest stable versions (such as 1.21.x and 2.0.x) or the latest EA version and stable version (such as 2.2.x EA and 2.1.x).
93
+ - [Python](https://www.python.org/) 3.9+
94
+ - POSIX compatible system
95
+ - Library is only test on Linux, specifically the latest Debian version available for the official Python Docker images, but there is no reason the library should not work on any Linux distro or MacOS.
96
+ - [ffmpeg](https://ffmpeg.org/)
97
+ - ffmpeg is primarily only for streaming audio to Protect cameras, this can be considered a soft requirement
98
+
99
+ Alternatively you can use the [provided Docker container](#using-docker-container), in which case the only requirement is [Docker](https://docs.docker.com/desktop/) or another OCI compatible orchestrator (such as Kubernetes or podman).
100
+
101
+ Windows is **not supported**. If you need to use `uiprotect` on Windows, use Docker Desktop and the provided docker container or [WSL](https://docs.microsoft.com/en-us/windows/wsl/install).
102
+
103
+ ## Install
104
+
105
+ ### From PyPi
106
+
107
+ `uiprotect` is available on PyPi:
108
+
109
+ ```bash
110
+ pip install uiprotect
111
+ ```
112
+
113
+ ### From Github
114
+
115
+ ```bash
116
+ pip install git+https://github.com/uilibs/uiprotect.git#egg=uiprotect
117
+ ```
118
+
119
+ ### Using Docker Container
120
+
121
+ 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.
122
+
123
+ ```bash
124
+ function unifi-protect() {
125
+ docker run --rm -it \
126
+ -e UFP_USERNAME=YOUR_USERNAME_HERE \
127
+ -e UFP_PASSWORD=YOUR_PASSWORD_HERE \
128
+ -e UFP_ADDRESS=YOUR_IP_ADDRESS \
129
+ -e UFP_PORT=443 \
130
+ -e UFP_SSL_VERIFY=True \
131
+ -e TZ=America/New_York \
132
+ -v $PWD:/data ghcr.io/uilibs/uiprotect:latest "$@"
133
+ }
134
+ ```
135
+
136
+ Some notes about the Docker version since it is running inside of a container:
137
+
138
+ - You can update at any time using the command `docker pull ghcr.io/uilibs/uiprotect:latest`
139
+ - 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.
140
+ - The container supports `linux/amd64` and `linux/arm64` natively. This means it will also work well on MacOS or Windows using Docker Desktop.
141
+ - `TZ` should be the [Olson timezone name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) for the timezone your UniFi Protect instance is in.
142
+ - For more details on `TZ` and other environment variables, check the [command line docs](https://uilibs.github.io/uiprotect/latest/cli/)
143
+
144
+ ## Quickstart
145
+
146
+ ### CLI
147
+
148
+ !!! warning "About Ubiquiti SSO accounts"
149
+ Ubiquiti SSO accounts are not supported and actively discouraged from being used. There is no option to use MFA. You are expected to use local access user. `uiprotect` is not designed to allow you to use your owner account to access the your console or to be used over the public Internet as both pose a security risk.
150
+
151
+ ```bash
152
+ export UFP_USERNAME=YOUR_USERNAME_HERE
153
+ export UFP_PASSWORD=YOUR_PASSWORD_HERE
154
+ export UFP_ADDRESS=YOUR_IP_ADDRESS
155
+ export UFP_PORT=443
156
+ # change to false if you do not have a valid HTTPS Certificate for your instance
157
+ export UFP_SSL_VERIFY=True
158
+
159
+ unifi-protect --help
160
+ unifi-protect nvr
161
+ ```
162
+
163
+ ### Python
164
+
165
+ UniFi Protect itself is 100% async, so as such this library is primarily designed to be used in an async context.
166
+
167
+ The main interface for the library is the `uiprotect.ProtectApiClient`:
168
+
169
+ ```python
170
+ from uiprotect import ProtectApiClient
171
+
172
+ protect = ProtectApiClient(host, port, username, password, verify_ssl=True)
173
+
174
+ await protect.update() # this will initialize the protect .bootstrap and open a Websocket connection for updates
175
+
176
+ # get names of your cameras
177
+ for camera in protect.bootstrap.cameras.values():
178
+ print(camera.name)
179
+
180
+ # subscribe to Websocket for updates to UFP
181
+ def callback(msg: WSSubscriptionMessage):
182
+ # do stuff
183
+
184
+ unsub = protect.subscribe_websocket(callback)
185
+
186
+ # remove subscription
187
+ unsub()
188
+
189
+ ```
190
+
191
+ ## TODO / Planned / Not Implemented
192
+
193
+ Generally any feature missing from the library is planned to be done eventually / nice to have with the following exceptions
194
+
195
+ ### UniFi OS Features
196
+
197
+ Anything that is strictly a UniFi OS feature. If it ever done, it will be in a separate library that interacts with this one. Examples include:
198
+
199
+ - Managing RAID and disks
200
+ - Creating and managing users
201
+
202
+ Examples include:
203
+
204
+ - Stream sharing
205
+ - Smart Detections, including person, vehicle, animals license plate and faces
@@ -0,0 +1,192 @@
1
+ [tool.poetry]
2
+ name = "uiprotect"
3
+ version = "0.1.0"
4
+ description = "Python API for Unifi Protect (Unofficial)"
5
+ authors = ["UI Protect Maintainers <ui@koston.org>"]
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ repository = "https://github.com/uilibs/uiprotect"
9
+ documentation = "https://uiprotect.readthedocs.io"
10
+ classifiers = [
11
+ "Development Status :: 2 - Pre-Alpha",
12
+ "Intended Audience :: Developers",
13
+ "Natural Language :: English",
14
+ "Operating System :: OS Independent",
15
+ "Topic :: Software Development :: Libraries",
16
+ ]
17
+ packages = [
18
+ { include = "uiprotect", from = "src" },
19
+ ]
20
+
21
+ [tool.poetry.urls]
22
+ "Bug Tracker" = "https://github.com/uilibs/uiprotect/issues"
23
+ "Changelog" = "https://github.com/uilibs/uiprotect/blob/main/CHANGELOG.md"
24
+
25
+ [tool.poetry.scripts]
26
+ uiprotect = "uiprotect.cli:app"
27
+
28
+ [tool.poetry.dependencies]
29
+ python = ">=3.10"
30
+ rich = ">=10"
31
+ typer = {version = ">0.6", extras = ["all"]}
32
+ async-timeout = ">=3.0.1"
33
+ aiofiles = ">=23"
34
+ aiohttp = ">=3.9.0"
35
+ aioshutil = ">=1.3"
36
+ dateparser = ">=1.1.0"
37
+ orjson = ">=3.9"
38
+ packaging = ">=23"
39
+ pillow = ">=10"
40
+ platformdirs = ">=4"
41
+ pydantic = "!=1.9.1"
42
+ pyjwt = ">=2.6"
43
+ yarl = ">=1.9"
44
+
45
+ [tool.poetry.group.dev.dependencies]
46
+ pytest = "^7.0"
47
+ pytest-cov = "^3.0"
48
+ aiosqlite = ">=0.20.0"
49
+ asttokens = "^2.4.1"
50
+ pytest-asyncio = "^0.23.7"
51
+ pytest-benchmark = "^4.0.0"
52
+ pytest-sugar = "^1.0.0"
53
+ pytest-timeout = "^2.3.1"
54
+ pytest-xdist = "^3.6.1"
55
+ types-aiofiles = "^23.2.0.20240403"
56
+ types-dateparser = "^1.2.0.20240420"
57
+ mypy = "^1.10.0"
58
+
59
+ [tool.poetry.group.docs]
60
+ optional = true
61
+
62
+ [tool.poetry.group.docs.dependencies]
63
+ myst-parser = { version = ">=0.16", python = ">=3.11"}
64
+ sphinx = { version = ">=4.0", python = ">=3.11"}
65
+ furo = { version = ">=2023.5.20", python = ">=3.11"}
66
+ sphinx-autobuild = { version = ">=2024.0.0", python = ">=3.11"}
67
+
68
+ [tool.semantic_release]
69
+ version_toml = ["pyproject.toml:tool.poetry.version"]
70
+ version_variables = [
71
+ "src/uiprotect/__init__.py:__version__",
72
+ "docs/conf.py:release",
73
+ ]
74
+ build_command = "pip install poetry && poetry build"
75
+
76
+ [tool.semantic_release.changelog]
77
+ exclude_commit_patterns = [
78
+ "chore*",
79
+ "ci*",
80
+ ]
81
+
82
+ [tool.semantic_release.changelog.environment]
83
+ keep_trailing_newline = true
84
+
85
+ [tool.semantic_release.branches.main]
86
+ match = "main"
87
+
88
+ [tool.semantic_release.branches.noop]
89
+ match = "(?!main$)"
90
+ prerelease = true
91
+
92
+ [tool.pytest.ini_options]
93
+ addopts = "-v -Wdefault --cov=uiprotect --cov-report=term-missing:skip-covered -n=auto"
94
+ pythonpath = ["src"]
95
+
96
+ [tool.coverage.run]
97
+ branch = true
98
+
99
+ [tool.coverage.report]
100
+ exclude_lines = [
101
+ "pragma: no cover",
102
+ "@overload",
103
+ "if TYPE_CHECKING",
104
+ "raise NotImplementedError",
105
+ 'if __name__ == "__main__":',
106
+ ]
107
+
108
+ [tool.ruff]
109
+ target-version = "py38"
110
+ line-length = 88
111
+
112
+ [tool.ruff.lint]
113
+ ignore = [
114
+ "S101", # use of assert
115
+ "D203", # 1 blank line required before class docstring
116
+ "D212", # Multi-line docstring summary should start at the first line
117
+ "D100", # Missing docstring in public module
118
+ "D101", # Missing docstring in public module
119
+ "D102", # Missing docstring in public method
120
+ "D103", # Missing docstring in public module
121
+ "D104", # Missing docstring in public package
122
+ "D105", # Missing docstring in magic method
123
+ "D107", # Missing docstring in `__init__`
124
+ "D400", # First line should end with a period
125
+ "D401", # First line of docstring should be in imperative mood
126
+ "D205", # 1 blank line required between summary line and description
127
+ "D415", # First line should end with a period, question mark, or exclamation point
128
+ "D417", # Missing argument descriptions in the docstring
129
+ "E501", # Line too long
130
+ "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
131
+ "B008", # Do not perform function call
132
+ "S110", # `try`-`except`-`pass` detected, consider logging the exception
133
+ "D106", # Missing docstring in public nested class
134
+ "UP007", # typer needs Optional syntax
135
+ ]
136
+ select = [
137
+ "B", # flake8-bugbear
138
+ "D", # flake8-docstrings
139
+ "C4", # flake8-comprehensions
140
+ "S", # flake8-bandit
141
+ "F", # pyflake
142
+ "E", # pycodestyle
143
+ "W", # pycodestyle
144
+ "UP", # pyupgrade
145
+ "I", # isort
146
+ "RUF", # ruff specific
147
+ ]
148
+
149
+ [tool.ruff.lint.per-file-ignores]
150
+ "tests/**/*" = [
151
+ "D100",
152
+ "D101",
153
+ "D102",
154
+ "D103",
155
+ "D104",
156
+ "S101",
157
+ ]
158
+ "setup.py" = ["D100"]
159
+ "conftest.py" = ["D100"]
160
+ "docs/conf.py" = ["D100"]
161
+
162
+ [tool.ruff.isort]
163
+ known-first-party = ["uiprotect", "tests"]
164
+
165
+ [tool.mypy]
166
+ disable_error_code = "import-untyped,unused-ignore"
167
+ check_untyped_defs = true
168
+ ignore_missing_imports = true
169
+ disallow_any_generics = true
170
+ disallow_incomplete_defs = true
171
+ disallow_untyped_defs = true
172
+ mypy_path = "src/"
173
+ no_implicit_optional = true
174
+ show_error_codes = true
175
+ warn_unreachable = true
176
+ warn_unused_ignores = true
177
+ exclude = [
178
+ 'docs/.*',
179
+ 'setup.py',
180
+ ]
181
+
182
+ [[tool.mypy.overrides]]
183
+ module = "tests.*"
184
+ allow_untyped_defs = true
185
+
186
+ [[tool.mypy.overrides]]
187
+ module = "docs.*"
188
+ ignore_errors = true
189
+
190
+ [build-system]
191
+ requires = ["poetry-core>=1.0.0"]
192
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,13 @@
1
+ """Unofficial UniFi Protect Python API and Command Line Interface."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from uiprotect.api import ProtectApiClient
6
+ from uiprotect.exceptions import Invalid, NotAuthorized, NvrError
7
+
8
+ __all__ = [
9
+ "Invalid",
10
+ "NotAuthorized",
11
+ "NvrError",
12
+ "ProtectApiClient",
13
+ ]