diff --git a/app/wyzecam/api.py b/app/wyzecam/api.py index e1cd67a0..0f4c09fc 100644 --- a/app/wyzecam/api.py +++ b/app/wyzecam/api.py @@ -71,6 +71,8 @@ def login( password: str, phone_id: Optional[str] = None, mfa: Optional[dict] = None, + api_key: Optional[str] = None, + key_id: Optional[str] = None, ) -> WyzeCredential: """Authenticate with Wyze. @@ -92,14 +94,16 @@ def login( [get_camera_list()][wyzecam.api.get_camera_list]. """ phone_id = phone_id or str(uuid.uuid4()) - headers = _headers(phone_id) + key_id = key_id or getenv("API_ID") + api_key = api_key or getenv("API_KEY") + headers = _headers(phone_id, key_id=key_id, api_key=api_key) headers["content-type"] = "application/json" payload = sort_dict( {"email": email.strip(), "password": hash_password(password), **(mfa or {})} ) api_version = "v2" - if getenv("API_ID") and getenv("API_KEY"): + if key_id and api_key: api_version = "api" elif getenv("v3"): api_version = "v3" @@ -109,7 +113,10 @@ def login( resp = post(f"{AUTH_API}/{api_version}/user/login", data=payload, headers=headers) resp.raise_for_status() - return WyzeCredential.model_validate(dict(resp.json(), phone_id=phone_id)) + credential = WyzeCredential.model_validate(dict(resp.json(), phone_id=phone_id)) + credential.key_id = key_id + credential.api_key = api_key + return credential def send_sms_code(auth_info: WyzeCredential, phone: str = "Primary") -> str: @@ -130,7 +137,7 @@ def send_sms_code(auth_info: WyzeCredential, phone: str = "Primary") -> str: "sessionId": auth_info.sms_session_id, "userId": auth_info.user_id, }, - headers=_headers(auth_info.phone_id), + headers=_headers(auth_info=auth_info), ) resp.raise_for_status() @@ -154,7 +161,7 @@ def send_email_code(auth_info: WyzeCredential) -> str: "userId": auth_info.user_id, "sessionId": auth_info.email_session_id, }, - headers=_headers(auth_info.phone_id), + headers=_headers(auth_info=auth_info), ) resp.raise_for_status() @@ -361,14 +368,16 @@ def _payload( } -def _headers(phone_id: Optional[str] = None) -> dict[str, str]: +def _headers(phone_id: Optional[str] = None, key_id: Optional[str] = None, api_key: Optional[str] = None, auth_info: Optional[WyzeCredential] = None) -> dict[str, str]: + phone_id = phone_id or (auth_info and auth_info.phone_id) if not phone_id: return {"user-agent": SCALE_USER_AGENT} - id, key = getenv("API_ID"), getenv("API_KEY") - if id and key: + key_id = key_id or (auth_info and auth_info.api_key) or getenv("API_ID") + api_key = api_key or (auth_info and auth_info.key_id) or getenv("API_KEY") + if key_id and api_key: return { - "apikey": key, - "keyid": id, + "apikey": api_key, + "keyid": key_id, "user-agent": f"docker-wyze-bridge/{getenv('VERSION')}", } diff --git a/app/wyzecam/api_models.py b/app/wyzecam/api_models.py index 5c25e0c8..614e4c54 100644 --- a/app/wyzecam/api_models.py +++ b/app/wyzecam/api_models.py @@ -78,6 +78,8 @@ class WyzeCredential(BaseModel): sms_session_id: Optional[str] = None email_session_id: Optional[str] = None phone_id: Optional[str] = str(uuid.uuid4()) + key_id: Optional[str] = None + api_key: Optional[str] = None class WyzeAccount(BaseModel): diff --git a/app/wyzecam/tutk/tutk.py b/app/wyzecam/tutk/tutk.py index 51e786c6..8b7b78b6 100644 --- a/app/wyzecam/tutk/tutk.py +++ b/app/wyzecam/tutk/tutk.py @@ -44,6 +44,12 @@ A bitrate higher than the "HD" setting in the app. Approx 240 KB/s. """ +FRAME_SIZE_2K = 3 +""" +Represents the size of the video stream sent back from the server; 2K +or 2560x1440 pixels. +""" + FRAME_SIZE_1080P = 0 """ Represents the size of the video stream sent back from the server; 1080P diff --git a/app/wyzecam/tutk/tutk_protocol.py b/app/wyzecam/tutk/tutk_protocol.py index b0a66138..fd059783 100644 --- a/app/wyzecam/tutk/tutk_protocol.py +++ b/app/wyzecam/tutk/tutk_protocol.py @@ -1,8 +1,9 @@ import json import logging -import pathlib import time from ctypes import LittleEndianStructure, c_char, c_uint16, c_uint32 +from os import getenv +from pathlib import Path from struct import pack, unpack from typing import Any, Optional @@ -11,7 +12,8 @@ from . import tutk -project_root = pathlib.Path(__file__).parent +PROJECT_ROOT = Path(getenv("TUTK_PROJECT_ROOT", Path(__file__).parent)) + logger = logging.getLogger(__name__) @@ -1345,7 +1347,7 @@ def generate_challenge_response(camera_enr_b, enr, camera_status): def supports(product_model, protocol, command): - with open(project_root / "device_config.json") as f: + with open(PROJECT_ROOT / "device_config.json") as f: device_config = json.load(f) commands_db = device_config["supportedCommands"] supported_commands = []