Metadata-Version: 2.4 Name: ring-doorbell Version: 0.9.14 Summary: A Python library to communicate with Ring Door Bell (https://ring.com/) Project-URL: homepage, https://github.com/python-ring-doorbell/python-ring-doorbell Project-URL: repository, https://github.com/python-ring-doorbell/python-ring-doorbell Project-URL: documentation, http://python-ring-doorbell.readthedocs.io/ Project-URL: Bug Tracker, https://github.com/python-ring-doorbell/python-ring-doorbell/issues Author: python-ring-doorbell developers License: LGPL-3.0-or-later License-File: LICENSE Keywords: camera,door bell,home automation,ring Classifier: Environment :: Other Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Topic :: Home Automation Classifier: Topic :: Software Development :: Libraries :: Python Modules Requires-Python: >=3.9.0 Requires-Dist: aiofiles>=23 Requires-Dist: aiohttp>=3 Requires-Dist: async-timeout>=3.0.0 Requires-Dist: asyncclick>=8.1.7.1 Requires-Dist: firebase-messaging>=0.4.0 Requires-Dist: oauthlib<4,>=3.0.0 Requires-Dist: pytz>=2022.0 Requires-Dist: typing-extensions<5.0,>=4.12.2 Requires-Dist: websockets>=13.0.0 Provides-Extra: docs Requires-Dist: myst-parser; extra == 'docs' Requires-Dist: sphinx-rtd-theme~=1.3; extra == 'docs' Requires-Dist: sphinx<7.2.6; extra == 'docs' Description-Content-Type: text/x-rst ===================== Python Ring Door Bell ===================== .. image:: https://badge.fury.io/py/ring-doorbell.svg :alt: PyPI Version :target: https://badge.fury.io/py/ring-doorbell .. image:: https://github.com/python-ring-doorbell/python-ring-doorbell/actions/workflows/ci.yml/badge.svg?branch=master :alt: Build Status :target: https://github.com/python-ring-doorbell/python-ring-doorbell/actions/workflows/ci.yml?branch=master .. image:: https://coveralls.io/repos/github/python-ring-doorbell/python-ring-doorbell/badge.svg?branch=master :alt: Coverage :target: https://coveralls.io/github/python-ring-doorbell/python-ring-doorbell?branch=master .. image:: https://readthedocs.org/projects/python-ring-doorbell/badge/?version=latest :alt: Documentation Status :target: https://python-ring-doorbell.readthedocs.io/?badge=latest .. image:: https://img.shields.io/pypi/pyversions/ring-doorbell.svg :alt: Py Versions :target: https://pypi.python.org/pypi/ring-doorbell Python Ring Door Bell is a library written for Python that exposes the Ring.com devices as Python objects. There is also a command line interface that is work in progress. `Contributors welcome `_. *Currently Ring.com does not provide an official API. The results of this project are merely from reverse engineering.* Documentation: `http://python-ring-doorbell.readthedocs.io/ `_ Installation ------------ .. code-block:: bash # Installing from PyPi $ pip install ring_doorbell # Installing latest development $ pip install \ git+https://github.com/python-ring-doorbell/python-ring-doorbell@master Using the CLI ------------- The CLI is work in progress and currently has the following commands: 1. Show your devices:: $ ring-doorbell Or:: $ ring-doorbell show #. List your device names (with device kind):: $ ring-doorbell list #. Either count or download your vidoes or both:: $ ring-doorbell videos --count --download-all #. Enable disable motion detection:: $ ring-doorbell motion-detection --device-name "DEVICENAME" --on $ ring-doorbell motion-detection --device-name "DEVICENAME" --off #. Listen for push notifications like the ones sent to your phone:: $ ring-doorbell listen #. List your ring groups:: $ ring-doorbell groups #. Show your ding history:: $ ring-doorbell history --device-name "Front Door" #. Show your currently active dings:: $ ring-doorbell dings #. See or manage your doorbell in-home chime settings:: $ ring-doorbell in-home-chime --device-name "Front Door" $ ring-doorbell in-home-chime --device-name "Front Door" type Mechanical $ ring-doorbell in-home-chime --device-name "Front Door" enabled True $ ring-doorbell in-home-chime --device-name "Front Door" duration 5 #. Query a ring api url directly:: $ ring-doorbell raw-query --url /clients_api/dings/active #. Run ``ring-doorbell --help`` or ``ring-doorbell --help`` for full options Using the API ------------- The API has an async interface and a sync interface. All api calls starting `async` are asynchronous. This is the preferred method of interacting with the ring api and the sync versions are maintained for backwards compatability. *You cannot call sync api functions from inside a running event loop.* Initializing your Ring object +++++++++++++++++++++++++++++ This code example is in the `test.py `_ file. For the deprecated sync example see `test_sync.py `_. .. code-block:: python import getpass import asyncio import json from pathlib import Path from ring_doorbell import Auth, AuthenticationError, Requires2FAError, Ring user_agent = "YourProjectName-1.0" # Change this cache_file = Path(user_agent + ".token.cache") def token_updated(token): cache_file.write_text(json.dumps(token)) def otp_callback(): auth_code = input("2FA code: ") return auth_code async def do_auth(): username = input("Username: ") password = getpass.getpass("Password: ") auth = Auth(user_agent, None, token_updated) try: await auth.async_fetch_token(username, password) except Requires2FAError: await auth.async_fetch_token(username, password, otp_callback()) return auth async def main(): if cache_file.is_file(): # auth token is cached auth = Auth(user_agent, json.loads(cache_file.read_text()), token_updated) ring = Ring(auth) try: await ring.async_create_session() # auth token still valid except AuthenticationError: # auth token has expired auth = await do_auth() else: auth = await do_auth() # Get new auth token ring = Ring(auth) await ring.async_update_data() devices = ring.devices() pprint(devices.devices_combined) await auth.async_close() if __name__ == "__main__": asyncio.run(main()) Event Listener ++++++++++++++ .. code-block:: python event_listener = RingEventListener(ring, credentials, credentials_updated_callback) event_listener.add_notification_callback(_event_handler(ring).on_event) await event_listener.start() Listing devices linked to your account ++++++++++++++++++++++++++++++++++++++ .. code-block:: python # All devices devices = ring.devices() {'chimes': [], 'doorbots': []} # All doorbells doorbells = devices['doorbots'] [] # All chimes chimes = devices['chimes'] [] # All stickup cams stickup_cams = devices['stickup_cams'] [] Playing with the attributes and functions +++++++++++++++++++++++++++++++++++++++++ .. code-block:: python devices = ring.devices() for dev in list(devices['stickup_cams'] + devices['chimes'] + devices['doorbots']): await dev.async_update_health_data() print('Address: %s' % dev.address) print('Family: %s' % dev.family) print('ID: %s' % dev.id) print('Name: %s' % dev.name) print('Timezone: %s' % dev.timezone) print('Wifi Name: %s' % dev.wifi_name) print('Wifi RSSI: %s' % dev.wifi_signal_strength) # setting dev volume print('Volume: %s' % dev.volume) await dev.async_set_volume(5) print('Volume: %s' % dev.volume) # play dev test shound if dev.family == 'chimes': await dev.async_test_sound(kind = 'ding') await dev.async_test_sound(kind = 'motion') # turn on lights on floodlight cam if dev.family == 'stickup_cams' and dev.lights: await dev.async_lights('on') Showing door bell events ++++++++++++++++++++++++ .. code-block:: python devices = ring.devices() for doorbell in devices['doorbots']: # listing the last 15 events of any kind for event in await doorbell.async_history(limit=15): print('ID: %s' % event['id']) print('Kind: %s' % event['kind']) print('Answered: %s' % event['answered']) print('When: %s' % event['created_at']) print('--' * 50) # get a event list only the triggered by motion events = await doorbell.async_history(kind='motion') Downloading the last video triggered by a ding or motion event ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .. code-block:: python devices = ring.devices() doorbell = devices['doorbots'][0] await doorbell.async_recording_download( await doorbell.async_history(limit=100, kind='ding')[0]['id'], filename='last_ding.mp4', override=True) Displaying the last video capture URL +++++++++++++++++++++++++++++++++++++ .. code-block:: python print(await doorbell.async_recording_url(await doorbell.async_last_recording_id())) 'https://ring-transcoded-videos.s3.amazonaws.com/99999999.mp4?X-Amz-Expires=3600&X-Amz-Date=20170313T232537Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=TOKEN_SECRET/us-east-1/s3/aws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=secret' Controlling a Light Group +++++++++++++++++++++++++ .. code-block:: python groups = ring.groups() group = groups['the-group-you-want'] print(group.lights) # Prints True if lights are on, False if off # Turn on lights indefinitely await group.async_set_lights(True) # Turn off lights await group.async_set_lights(False) # Turn on lights for 30 seconds await group.async_set_lights(True, 30) How to contribute ----------------- See our `Contributing Page `_. Credits && Thanks ----------------- * This project was inspired and based on https://github.com/jeroenmoors/php-ring-api. Many thanks @jeroenmoors. * A guy named MadBagger at Prism19 for his initial research (http://www.prism19.com/doorbot/second-pass-and-comm-reversing/) * The creators of mitmproxy (https://mitmproxy.org/) great http and https traffic inspector * @mfussenegger for his post on mitmproxy and virtualbox https://zignar.net/2015/12/31/sniffing-vbox-traffic-mitmproxy/ * To the project http://www.android-x86.org/ which allowed me to install Android on KVM. * Many thanks to Carles Pina I Estany for creating the python-ring-doorbell Debian Package (https://tracker.debian.org/pkg/python-ring-doorbell).