### Install pyunifiprotect via pip Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Install the library using the standard pip package manager. ```bash pip install pyunifiprotect ``` -------------------------------- ### Install pyunifiprotect Source: https://github.com/bdraco/pyunifiprotect/blob/master/TESTDATA.md Install the package via pip for environments without Home Assistant. ```bash pip3 install pyunifiprotect ``` -------------------------------- ### Initialize ProtectApiClient and Access NVR Info Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Initialize the ProtectApiClient to connect to Unifi Protect instances. This example shows how to access NVR information and list cameras with their details. ```python import asyncio from pyunifiprotect import ProtectApiClient async def main(): # Initialize the client protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password", verify_ssl=True, minimum_score=0, # Minimum event score threshold debug=False ) # Initialize bootstrap and connect WebSocket await protect.update() # Access NVR information print(f"NVR Name: {protect.bootstrap.nvr.name}") print(f"NVR Version: {protect.bootstrap.nvr.version}") print(f"Timezone: {protect.bootstrap.nvr.timezone}") # List all cameras for camera_id, camera in protect.bootstrap.cameras.items(): print(f"Camera: {camera.name} ({camera.id})") print(f" Model: {camera.type}") print(f" Recording Mode: {camera.recording_settings.mode}") print(f" Is Recording: {camera.is_recording}") # Clean up await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Subscribe to WebSocket Events Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Subscribe to real-time device updates via WebSocket. This example defines a callback to handle device updates and additions, and ensures proper unsubscription. ```python import asyncio from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import WSSubscriptionMessage, WSAction async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Define callback for WebSocket events def handle_event(msg: WSSubscriptionMessage): if msg.action == WSAction.UPDATE: print(f"Device updated: {msg.new_obj.name if hasattr(msg.new_obj, 'name') else msg.new_obj.id}") print(f"Changed data: {msg.changed_data}") elif msg.action == WSAction.ADD: print(f"New event/device added: {msg.new_obj}") # Subscribe to events unsub = protect.subscribe_websocket(handle_event) # Keep running to receive events try: while True: await asyncio.sleep(1) except KeyboardInterrupt: pass finally: unsub() # Unsubscribe when done await protect.async_disconnect_ws() await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Perform Camera Audio Talkback Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Stream audio to cameras with speakers using play_audio or manual talkback streams. Requires ffmpeg to be installed and accessible. ```python import asyncio from pathlib import Path from pyunifiprotect import ProtectApiClient from pyunifiprotect.exceptions import StreamError async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Find camera with speaker camera = None for cam in protect.bootstrap.cameras.values(): if cam.feature_flags.has_speaker: camera = cam break if camera: try: # Play audio file through camera speaker await camera.play_audio( content_url="/path/to/audio.mp3", ffmpeg_path=Path("/usr/bin/ffmpeg") # Optional ) print(f"Audio played on {camera.name}") except StreamError as e: print(f"Audio playback failed: {e}") # Alternative: manual stream control stream = camera.create_talkback_stream( content_url="http://example.com/audio.wav", ffmpeg_path=None # Uses default ffmpeg ) await stream.start() # Do other things while audio plays await stream.wait() if stream.is_error: print(f"Errors: {stream.stderr}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Initialize and Use UpvServer Legacy Client Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Initialize the legacy UpvServer client, update device information, and perform camera operations. Requires asyncio and UpvServer. Ensure correct host, port, username, and password are provided. SSL verification is enabled by default. ```python import asyncio from pyunifiprotect.unifi_protect_server import UpvServer async def main(): server = UpvServer( session=None, # Will create its own session host="192.168.1.1", port=443, username="admin", password="your_password", verify_ssl=True, minimum_score=0 ) # Update and get all devices devices = await server.update(force_camera_update=True) for device_id, device in devices.items(): print(f"Device: {device.get('name', device_id)}") print(f" Type: {device.get('type')}") print(f" Recording: {device.get('recording_mode')}") # Get server information server_info = await server.server_information() print(f"Server: {server_info['server_name']}") print(f"Version: {server_info['server_version']}") # Camera operations camera_id = list(devices.keys())[0] await server.set_camera_recording(camera_id, "detections") await server.set_camera_ir(camera_id, "auto") await server.set_mic_volume(camera_id, 50) # Get snapshots snapshot = await server.get_snapshot_image(camera_id, width=1920, height=1080) thumbnail = await server.get_thumbnail(camera_id, width=640) heatmap = await server.get_heatmap(camera_id) # Light operations if server.devices.get("light_id"): await server.set_light_on_off("light_id", turn_on=True, led_level=4) await server.light_settings( "light_id", mode="motion", enable_at="dark", duration=60000, sensitivity=80 ) # Subscribe to websocket updates def on_update(update): for device_id, data in update.items(): print(f"Update for {device_id}: {data}") unsub = server.subscribe_websocket(on_update) # Clean up unsub() await server.close_session() asyncio.run(main()) ``` -------------------------------- ### Interactive Shell for Exploration Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Launch an interactive shell for exploring Unifi Protect with a new client connection. ```bash unifi-protect shell --new-client ``` -------------------------------- ### Generate Sample Data Source: https://github.com/bdraco/pyunifiprotect/blob/master/TESTDATA.md Execute the data generation tool to capture UniFi Protect state information. Replace placeholders with actual credentials and IP address. ```bash unifi-protect generate-sample-data -o /path/to/ufp-data --actual -w 300 -v -U your-unifi-protect-username -P your-unifi-protect-password -a ip-address-to-unifi-protect ``` -------------------------------- ### Configure environment variables for authentication Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Store local instance credentials in a .env file to avoid hardcoding them in scripts. ```text 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 ``` -------------------------------- ### Initialize and use ProtectApiClient Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md The main entry point for interacting with the Unifi Protect API. Requires an async context to perform updates and manage websocket subscriptions. ```python 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() ``` -------------------------------- ### Run linting and tests Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Commands to verify code quality and ensure test suite passes. ```bash tox -e lint ``` ```bash pytest ``` -------------------------------- ### Camera Operations: Snapshots, Video, and Configuration Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Perform various operations on cameras, including retrieving snapshots and video clips, and configuring settings like recording mode, IR LEDs, and audio volumes. This also shows how to access RTSP stream URLs. ```python import asyncio from datetime import datetime, timedelta from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import RecordingMode, IRLEDMode, VideoMode async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Get first camera camera = list(protect.bootstrap.cameras.values())[0] # Get camera snapshot snapshot = await camera.get_snapshot(width=1920, height=1080) if snapshot: with open("snapshot.jpg", "wb") as f: f.write(snapshot) print(f"Saved snapshot from {camera.name}") # Get video clip from the last hour end_time = datetime.utcnow() start_time = end_time - timedelta(hours=1) video = await camera.get_video(start=start_time, end=end_time, channel_index=0) if video: with open("clip.mp4", "wb") as f: f.write(video) # Configure camera settings await camera.set_recording_mode(RecordingMode.DETECTIONS) await camera.set_ir_led_model(IRLEDMode.AUTO) await camera.set_status_light(enabled=True) await camera.set_hdr(enabled=True) await camera.set_mic_volume(level=50) await camera.set_speaker_volume(level=75) # Access RTSP streams for channel in camera.channels: if channel.is_rtsp_enabled: print(f"RTSP URL: {channel.rtsp_url}") print(f"RTSPS URL: {channel.rtsps_url}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Generate Sample Data for PyUnifiProtect Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Set the UFP_SAMPLE_DIR environment variable to specify the directory for sample data. Then, use the 'unifi-protect generate-sample-data' command with a specified gather time to create test data. This is useful for troubleshooting and testing with real, non-anonymized data. ```bash export UFP_SAMPLE_DIR=/workspaces/pyunifiprotect/test-data unifi-protect generate-sample-data -w 300 --actual ``` -------------------------------- ### Access Device Inventory via Bootstrap Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Utilize the Bootstrap object to retrieve authenticated user details, device lists, liveviews, and user groups. Requires an active ProtectApiClient session. ```python import asyncio from pyunifiprotect import ProtectApiClient async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() bootstrap = protect.bootstrap # Access authenticated user print(f"Logged in as: {bootstrap.auth_user.name}") print(f"Email: {bootstrap.auth_user.email}") print(f"Is Owner: {bootstrap.auth_user.is_owner}") # Inventory summary print(f"Cameras: {len(bootstrap.cameras)}") print(f"Lights: {len(bootstrap.lights)}") print(f"Sensors: {len(bootstrap.sensors)}") print(f"Viewers: {len(bootstrap.viewers)}") print(f"Bridges: {len(bootstrap.bridges)}") # Access devices by ID for camera_id, camera in bootstrap.cameras.items(): print(f"Camera {camera_id}: {camera.name}") print(f" Feature Flags:") print(f" Has Mic: {camera.feature_flags.has_mic}") print(f" Has Speaker: {camera.feature_flags.has_speaker}") print(f" Has Smart Detect: {camera.feature_flags.has_smart_detect}") print(f" Smart Types: {camera.feature_flags.smart_detect_types}") # Access liveviews for liveview in bootstrap.liveviews.values(): print(f"Liveview: {liveview.name}") print(f" URL: {liveview.protect_url}") for slot in liveview.slots: print(f" Slot Cameras: {[c.name for c in slot.cameras]}") # Access users and groups for user in bootstrap.users.values(): print(f"User: {user.name} ({user.email})") print(f" Groups: {[g.name for g in user.groups]}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Configure Unifi Protect NVR Settings Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Access and configure NVR settings including doorbell messages and system information. Requires importing ProtectApiClient and timedelta. ```python import asyncio from datetime import timedelta from pyunifiprotect import ProtectApiClient async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() nvr = protect.bootstrap.nvr # NVR Information print(f"NVR Name: {nvr.name}") print(f"Version: {nvr.version}") print(f"Hardware: {nvr.hardware_platform}") print(f"Timezone: {nvr.timezone}") print(f"Host: {nvr.hosts}") # System stats print(f"CPU Load: {nvr.system_info.cpu.average_load}") print(f"CPU Temp: {nvr.system_info.cpu.temperature}°C") print(f"Memory Used: {nvr.system_info.memory.used}/{nvr.system_info.memory.total}") print(f"Storage Used: {nvr.system_info.storage.used}/{nvr.system_info.storage.size}") # Ports configuration print(f"RTSP Port: {nvr.ports.rtsp}") print(f"RTSPS Port: {nvr.ports.rtsps}") # Manage custom doorbell messages await nvr.add_custom_doorbell_message("Please Leave Package") await nvr.set_default_doorbell_message("Welcome!") await nvr.set_default_reset_timeout(timedelta(minutes=5)) # List all doorbell messages for msg in nvr.doorbell_settings.all_messages: print(f"Doorbell Message: {msg.text} ({msg.type})") # Remove custom message await nvr.remove_custom_doorbell_message("Please Leave Package") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Execute CLI Debugging Commands Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Use environment variables for authentication and run CLI commands to fetch sensor data, raw info, or events. Useful for testing and development. ```bash # Set environment variables for authentication export UFP_USERNAME=admin export UFP_PASSWORD=your_password export UFP_ADDRESS=192.168.1.1 export UFP_PORT=443 export UFP_SSL_VERIFY=True # Get device sensor data unifi-protect sensor # Get raw device information unifi-protect raw-data # Get event data for specified seconds unifi-protect event-data --seconds 30 # Listen to websocket messages unifi-protect websocket-data # Generate sample test data (for development) unifi-protect generate-sample-data --wait 60 --output ./test-data ``` -------------------------------- ### Control Unifi Protect Light Device Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Control smart lights, including brightness, motion settings, and PIR configuration. Requires importing ProtectApiClient and LightModeType/LightModeEnableType. ```python import asyncio from datetime import timedelta from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import LightModeType, LightModeEnableType async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Get first light device if protect.bootstrap.lights: light = list(protect.bootstrap.lights.values())[0] print(f"Light: {light.name}") print(f" Is On: {light.is_light_on}") print(f" Motion Detected: {light.is_pir_motion_detected}") # Turn light on with brightness level (1-6) await light.set_light(enabled=True, led_level=4) # Configure light mode settings await light.set_light_settings( mode=LightModeType.MOTION, # motion, off, always enable_at=LightModeEnableType.DARK, # dark, fulltime duration=timedelta(seconds=60), # 15s to 900s sensitivity=80 # 0-100 ) # Set status LED indicator await light.set_status_light(enabled=True) # Set LED brightness await light.set_led_level(led_level=5) # Turn light off await light.set_light(enabled=False) # Access paired camera if any if light.camera: print(f" Paired Camera: {light.camera.name}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Access Home Assistant Container Source: https://github.com/bdraco/pyunifiprotect/blob/master/TESTDATA.md Use this command within the SSH & Web Terminal Add-On to enter the Home Assistant container environment. ```bash docker exec -it homeassistant bash ``` -------------------------------- ### Run Pytest with Real Data in PyUnifiProtect Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Ensure the UFP_SAMPLE_DIR environment variable is set to the directory containing your real test data. Then, execute the 'pytest' command to run tests using this data. This allows for testing with actual, non-anonymized results. ```bash export UFP_SAMPLE_DIR=/workspaces/pyunifiprotect/test-data pytest ``` -------------------------------- ### Update project requirements Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Generate pinned requirements files for testing and CI environments. ```bash pip-compile --upgrade --extra=shell --output-file=requirements_all.txt setup.cfg pip-compile --upgrade --extra=dev --output-file=requirements_test.txt --pip-args='-c requirements_all.txt' setup.cfg ``` -------------------------------- ### Generate sample test data Source: https://github.com/bdraco/pyunifiprotect/blob/master/README.md Collects anonymized data from a live Unifi Protect instance for testing purposes. ```bash unifi-protect generate-sample-data ``` -------------------------------- ### Run Docker GHA Runner Source: https://github.com/bdraco/pyunifiprotect/blob/master/LIVE_DATA_CI.md Use this command to run the GitHub Actions runner using Docker. Ensure you replace placeholder values with your actual repository URL, runner name, labels, token, and a host path for data storage. The WORKDIR is set to \/data within the container. ```bash docker run --rm -it \ -e REPO_URL=REPO_URL \ -e RUNNER_NAME=RUNNER_NAME \ -e LABELS=LABELS \ -e RUNNER_TOKEN=RUNNER_TOKEN \ -e RUNNER_WORKDIR=\/data \ -v \/path\/to\/host\/folder\/for\/data:\/data \ myoung34\/github-runner:ubuntu-bionic ``` -------------------------------- ### Manage Camera Privacy Mode Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Use set_privacy to toggle a full-screen privacy zone, control microphone levels, and adjust recording behavior. ```python import asyncio from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import RecordingMode async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() camera = list(protect.bootstrap.cameras.values())[0] # Enable privacy mode - creates a privacy zone covering entire frame # Optionally mute mic and disable recording await camera.set_privacy( enabled=True, mic_level=0, # Mute microphone recording_mode=RecordingMode.NEVER # Stop recording ) print(f"Privacy mode enabled on {camera.name}") print(f"Is privacy on: {camera.is_privacy_on}") # Later, disable privacy mode await camera.set_privacy( enabled=False, mic_level=100, # Restore microphone recording_mode=RecordingMode.DETECTIONS # Resume recording ) print(f"Privacy mode disabled on {camera.name}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Update Device Configurations Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Modify device settings or trigger reboots using patch endpoints. Use caution with low-level update_device calls. ```python import asyncio from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import ModelType async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() camera = list(protect.bootstrap.cameras.values())[0] # Low-level device update (use with caution) await protect.update_device( model_type=ModelType.CAMERA, device_id=camera.id, data={ "recordingSettings": {"mode": "detections"}, "micVolume": 75, "ledSettings": {"isEnabled": True} } ) # Reboot a device await protect.reboot_device( model_type=ModelType.CAMERA, device_id=camera.id ) # Update NVR settings await protect.update_nvr( data={"isRecordingDisabled": False} ) await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Access Unifi Protect Sensor Data Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Access sensor data including motion, open/close, temperature, humidity, and light levels. Requires importing ProtectApiClient. ```python import asyncio from pyunifiprotect import ProtectApiClient async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() for sensor in protect.bootstrap.sensors.values(): print(f"Sensor: {sensor.name}") print(f" Motion Detected: {sensor.is_motion_detected}") print(f" Is Opened: {sensor.is_opened}") print(f" Battery: {sensor.battery_status.percentage}%") print(f" Battery Low: {sensor.battery_status.is_low}") # Environmental readings stats = sensor.stats if stats.temperature.value is not None: print(f" Temperature: {stats.temperature.value}°C") if stats.humidity.value is not None: print(f" Humidity: {stats.humidity.value}%") if stats.light.value is not None: print(f" Light Level: {stats.light.value} lux") # Timestamps for recent events if sensor.motion_detected_at: print(f" Last Motion: {sensor.motion_detected_at}") if sensor.open_status_changed_at: print(f" Last Open/Close: {sensor.open_status_changed_at}") if sensor.alarm_triggered_at: print(f" Last Alarm: {sensor.alarm_triggered_at}") # Access paired camera if any if sensor.camera: print(f" Paired Camera: {sensor.camera.name}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Configure Doorbell LCD Text Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Update doorbell displays with custom messages or predefined types, supporting optional auto-reset timeouts. ```python import asyncio from datetime import datetime, timedelta from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import DoorbellMessageType, DEFAULT async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Find doorbell camera doorbell = None for camera in protect.bootstrap.cameras.values(): if camera.feature_flags.has_lcd_screen: doorbell = camera break if doorbell: # Set custom message with auto-reset after default timeout await doorbell.set_lcd_text( text_type=DoorbellMessageType.CUSTOM_MESSAGE, text="Welcome Home!", reset_at=DEFAULT # Uses NVR default timeout ) # Set predefined message type await doorbell.set_lcd_text( text_type=DoorbellMessageType.LEAVE_PACKAGE_AT_DOOR ) # Set message with specific reset time reset_time = datetime.utcnow() + timedelta(hours=2) await doorbell.set_lcd_text( text_type=DoorbellMessageType.CUSTOM_MESSAGE, text="Ring for Entry", reset_at=reset_time ) # Clear LCD message await doorbell.set_lcd_text(text_type=None) await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Retrieve NVR Events Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Fetch historical events and process associated media assets like thumbnails, heatmaps, and video clips. ```python import asyncio from datetime import datetime, timedelta from pyunifiprotect import ProtectApiClient from pyunifiprotect.data import EventType async def main(): protect = ProtectApiClient( host="192.168.1.1", port=443, username="admin", password="your_password" ) await protect.update() # Get events from last 24 hours end = datetime.utcnow() start = end - timedelta(hours=24) events = await protect.get_events(start=start, end=end, limit=100) for event in events: print(f"Event: {event.type.value}") print(f" Start: {event.start}") print(f" End: {event.end}") print(f" Score: {event.score}") if event.camera: print(f" Camera: {event.camera.name}") # Get event thumbnail if event.thumbnail_id: thumbnail = await event.get_thumbnail(width=640, height=360) if thumbnail: with open(f"event_{event.id}_thumb.jpg", "wb") as f: f.write(thumbnail) # Get event heatmap if event.heatmap_id: heatmap = await event.get_heatmap() if heatmap: with open(f"event_{event.id}_heatmap.png", "wb") as f: f.write(heatmap) # Get video clip for completed events if event.end and event.camera: video = await event.get_video(channel_index=0) if video: with open(f"event_{event.id}_video.mp4", "wb") as f: f.write(video) # Smart detection details if event.type == EventType.SMART_DETECT: print(f" Smart Types: {event.smart_detect_types}") track = await event.get_smart_detect_track() zones = await event.get_smart_detect_zones() print(f" Detection Zones: {[z.name for z in zones.values()]}") await protect.close_session() asyncio.run(main()) ``` -------------------------------- ### Decode WebSocket Message Source: https://context7.com/bdraco/pyunifiprotect/llms.txt Decode a WebSocket message from a file or base64 encoded string using the unifi-protect CLI. ```bash unifi-protect decode-ws-msg --file message.bin ``` ```bash unifi-protect decode-ws-msg "base64encodeddata..." ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.