一个用于与Ring Door Bell(https://ring.com/)通信的Python库
项目描述
Python Ring 门铃是一个为 Python 编写的库,它将 Ring.com 设备公开为 Python 对象。
还有一个正在开发中的命令行界面。欢迎贡献者(点击此处)。
目前,Ring.com 不提供官方 API。本项目的成果仅来自逆向工程。
文档:http://python-ring-doorbell.readthedocs.io/
安装
# Installing from PyPi
$ pip install ring_doorbell
# Installing latest development
$ pip install \
git+https://github.com/python-ring-doorbell/python-ring-doorbell@master
使用 CLI
CLI 正在开发中,目前有以下命令
显示您的设备
$ ring-doorbell
或者
$ ring-doorbell show
列出您的设备名称(包括设备类型)
$ ring-doorbell list
计数或下载视频,或两者都进行
$ ring-doorbell videos --count --download-all
启用/禁用运动检测
$ ring-doorbell motion-detection --device-name "DEVICENAME" --on $ ring-doorbell motion-detection --device-name "DEVICENAME" --off
监听像发送到您的手机的通知推送
$ ring-doorbell listen
列出您的铃声组
$ ring-doorbell groups
显示您的铃声历史记录
$ ring-doorbell history --device-name "Front Door"
显示当前正在响铃的设备
$ ring-doorbell dings
查看或管理您的门铃在家中的铃声设置
$ 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
直接查询 ring api url
$ ring-doorbell raw-query --url /clients_api/dings/active
运行 ring-doorbell --help 或 ring-doorbell <command> --help 以获取完整选项
使用 API
API 有异步接口和同步接口。所有以 async 开头的 API 调用都是异步的。这是与 ring api 交互的首选方法,同步版本是为了保持向后兼容性而维护的。
您不能在运行的事件循环中调用同步 API 函数。
初始化您的 Ring 对象
此代码示例位于 test.py 文件中。有关已弃用的同步示例,请参阅 test_sync.py。
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 = RingEventListener(ring, credentials, credentials_updated_callback)
event_listener.add_notification_callback(_event_handler(ring).on_event)
await event_listener.start()
列出与您的帐户关联的设备
# All devices
devices = ring.devices()
{'chimes': [<RingChime: Downstairs>],
'doorbots': [<RingDoorBell: Front Door>]}
# All doorbells
doorbells = devices['doorbots']
[<RingDoorBell: Front Door>]
# All chimes
chimes = devices['chimes']
[<RingChime: Downstairs>]
# All stickup cams
stickup_cams = devices['stickup_cams']
[<RingStickUpCam: Driveway>]
与属性和函数玩耍
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')
显示门铃事件
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')
下载由铃声或运动事件触发的最后一个视频
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)
显示最后一个视频捕获的 URL
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'
控制一个灯组
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)
如何贡献
查看我们的 贡献页面。
鸣谢
本项目受到并基于 https://github.com/jeroenmoors/php-ring-api 的启发和基础。感谢 @jeroenmoors。
Prism19 的 MadBagger 对其初始研究做出了贡献(《http://www.prism19.com/doorbot/second-pass-and-comm-reversing/》)
mitmproxy 的创作者(https://mitmproxy.org/)——出色的 http 和 https 流量检查器
@mfussenegger 为其关于 mitmproxy 和 virtualbox 的帖子(https://zignar.net/2015/12/31/sniffing-vbox-traffic-mitmproxy/)
感谢项目 http://www.android-x86.org/ 允许我在 KVM 上安装 Android。
感谢 Carles Pina I Estany <carles@pina.cat> 为创建 python-ring-doorbell Debian 软件包(https://tracker.debian.org/pkg/python-ring-doorbell)。
项目详情
下载文件
下载适用于您平台的应用程序。如果您不确定该选择哪个,请了解更多关于 安装包 的信息。