Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add custom port support for protect archiver #76

Merged
merged 2 commits into from
Feb 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
475 changes: 188 additions & 287 deletions poetry.lock

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions protect_archiver/cli/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
required=True,
help="IP address or hostname of the UniFi Protect Server",
)
@click.option(
"--port",
default=Config.PORT,
show_default=True,
required=False,
help="The port of the UniFi Protect Server",
)
@click.option(
"--not-unifi-os",
is_flag=True,
Expand Down Expand Up @@ -147,6 +154,7 @@
def download(
dest,
address,
port,
not_unifi_os,
username,
password,
Expand Down Expand Up @@ -174,6 +182,7 @@ def download(

client = ProtectClient(
address=address,
port=port,
not_unifi_os=not_unifi_os,
username=username,
password=password,
Expand Down
9 changes: 9 additions & 0 deletions protect_archiver/cli/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@
required=True,
help="IP address or hostname of the UniFi Protect Server",
)
@click.option(
"--port",
default=Config.PORT,
show_default=True,
required=False,
help="The port of the UniFi Protect Server",
)
@click.option(
"--not-unifi-os",
is_flag=True,
Expand Down Expand Up @@ -143,6 +150,7 @@
def events(
dest,
address,
port,
not_unifi_os,
username,
password,
Expand All @@ -160,6 +168,7 @@ def events(
):
client = ProtectClient(
address=address,
port=port,
not_unifi_os=not_unifi_os,
username=username,
password=password,
Expand Down
31 changes: 21 additions & 10 deletions protect_archiver/cli/sync.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import click

from os import path

import click

from protect_archiver.cli.base import cli
from protect_archiver.client import ProtectClient
from protect_archiver.config import Config
from protect_archiver.sync import ProtectSync
from protect_archiver.utils import print_download_stats


@cli.command(
"sync", help="Synchronize your UniFi Protect footage to a local destination"
)
@cli.command("sync", help="Synchronize your UniFi Protect footage to a local destination")
@click.argument("dest", type=click.Path(exists=True, writable=True, resolve_path=True))
@click.option(
"--address",
Expand All @@ -19,6 +18,13 @@
required=True,
help="CloudKey IP address or hostname",
)
@click.option(
"--port",
default=Config.PORT,
show_default=True,
required=False,
help="CloudKey port",
)
@click.option(
"--not-unifi-os",
is_flag=True,
Expand All @@ -40,10 +46,15 @@
hide_input=True,
)
@click.option(
"--statefile", default="sync.state", show_default=True,
"--statefile",
default="sync.state",
show_default=True,
)
@click.option(
"--ignore-state", is_flag=True, default=False, show_default=True,
"--ignore-state",
is_flag=True,
default=False,
show_default=True,
)
@click.option(
"--verify-ssl",
Expand Down Expand Up @@ -71,6 +82,7 @@
def sync(
dest,
address,
port,
not_unifi_os,
username,
password,
Expand All @@ -83,13 +95,12 @@ def sync(
# normalize path to destination directory and check if it exists
dest = path.abspath(dest)
if not path.isdir(dest):
click.echo(
f"Video file destination directory '{dest} is invalid or does not exist!"
)
click.echo(f"Video file destination directory '{dest} is invalid or does not exist!")
exit(1)

client = ProtectClient(
address=address,
port=port,
not_unifi_os=not_unifi_os,
username=username,
password=password,
Expand Down
2 changes: 2 additions & 0 deletions protect_archiver/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ProtectClient:
def __init__(
self,
address: str = Config.ADDRESS,
port: int = Config.PORT,
protocol: str = Config.PROTOCOL,
username: str = Config.USERNAME,
password: str = Config.PASSWORD,
Expand All @@ -27,6 +28,7 @@ def __init__(
):
self.protocol = protocol
self.address = address
self.port = port if port is not None else 7443 if not_unifi_os else 443
self.not_unifi_os = not_unifi_os
self.username = username
self.password = password
Expand Down
1 change: 1 addition & 0 deletions protect_archiver/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ def __init__(self):
pass

ADDRESS: str = "unifi"
PORT: int = 443
PROTOCOL: str = "https"
USERNAME: str = "ubnt"
PASSWORD: str = None
Expand Down
16 changes: 10 additions & 6 deletions protect_archiver/downloader/get_motion_event_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from protect_archiver.dataclasses import MotionEvent, Camera


def get_motion_event_list(session, start: datetime, end: datetime, camera_list: List[Camera]) -> List[MotionEvent]:
def get_motion_event_list(
session, start: datetime, end: datetime, camera_list: List[Camera]
) -> List[MotionEvent]:
motion_events_uri = (
f"{session.authority}{session.base_path}/events?type=motion"
f"&start={int(start.timestamp()) * 1000}&end={int(end.timestamp()) * 1000}"
Expand Down Expand Up @@ -43,11 +45,13 @@ def get_motion_event_list(session, start: datetime, end: datetime, camera_list:
event_count_by_camera = Counter(e.camera_id for e in motion_event_list)
logging.info(
"Events found:\n{}".format(
"\n".join(f"{event_count_by_camera[x]} motion "
f"event{'s' if event_count_by_camera[x] > 1 else ''} "
f"found for camera "
f"'{next(c.name for c in camera_list if c.id == x)}' ({x}) between {start} and {end}"
for x in event_count_by_camera)
"\n".join(
f"{event_count_by_camera[x]} motion "
f"event{'s' if event_count_by_camera[x] > 1 else ''} "
f"found for camera "
f"'{next(c.name for c in camera_list if c.id == x)}' ({x}) between {start} and {end}"
for x in event_count_by_camera
)
)
)

Expand Down
4 changes: 3 additions & 1 deletion protect_archiver/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ def run(self, camera_list: list, ignore_state: bool = False):
)
end = datetime.now().replace(minute=0, second=0, microsecond=0)
for interval_start, interval_end in calculate_intervals(start, end):
Downloader.download_footage(self.client, interval_start, interval_end, camera)
Downloader.download_footage(
self.client, interval_start, interval_end, camera
)
state["cameras"][camera.id] = {
"last": interval_end,
"name": camera.name,
Expand Down