===================== Python Ring 门铃
.. image:: https://badge.fury.io/py/ring-doorbell.svg :alt: PyPI 版本 :target: https://badge.fury.io/py/ring-doorbell
.. image:: https://github.com/tchellomello/python-ring-doorbell/actions/workflows/ci.yml/badge.svg?branch=master :alt: 构建状态 :target: https://github.com/tchellomello/python-ring-doorbell/actions/workflows/ci.yml?branch=master
.. image:: https://coveralls.io/repos/github/tchellomello/python-ring-doorbell/badge.svg?branch=master :alt: 覆盖率 :target: https://coveralls.io/github/tchellomello/python-ring-doorbell?branch=master
.. image:: https://readthedocs.org/projects/python-ring-doorbell/badge/?version=latest :alt: 文档状态 :target: https://python-ring-doorbell.readthedocs.io/?badge=latest
.. image:: https://img.shields.io/pypi/pyversions/ring-doorbell.svg :alt: Python 版本 :target: https://pypi.python.org/pypi/ring-doorbell
Python Ring 门铃是一个为 Python 3.8+ 编写的库,它将 Ring.com 设备作为 Python 对象暴露出来。
还有一个正在开发中的命令行界面。欢迎贡献者 <https://python-ring-doorbell.readthedocs.io/contributing.html>
_。
目前 Ring.com 并未提供官方 API。本项目的结果仅来自逆向工程。
文档:http://python-ring-doorbell.readthedocs.io/ <http://python-ring-doorbell.readthedocs.io/>
_
安装
.. code-block:: bash
# 从 PyPi 安装
$ pip install ring_doorbell
# 安装最新开发版
$ pip install \
git+https://github.com/tchellomello/python-ring-doorbell@master
事件监听器 ++++++++++++++
如果你希望 ring api 监听来自 ring.com 的按铃和动作推送事件,你需要安装带有 listen
额外选项的版本::
$ pip install ring_doorbell[listen]
在你首次调用 update_dings()
或 update_data()
后,API 将开始监听推送事件,但前提是有一个正在运行的 asyncio <https://docs.python.org/3/library/asyncio.html>
_ 事件循环(使用 CLI 时会自动有一个)
使用 CLI
CLI 仍在开发中,目前有以下命令:
-
显示你的设备::
$ ring-doorbell
或::
$ ring-doorbell show
#. 列出你的设备名称(带设备类型)::
$ ring-doorbell list
#. 计数或下载你的视频,或两者都做::
$ ring-doorbell videos --count --download-all
#. 启用禁用动作检测::
$ ring-doorbell motion-detection --device-name "设备名称" --on
$ ring-doorbell motion-detection --device-name "设备名称" --off
#. 监听推送通知,类似于发送到你手机的通知::
$ ring-doorbell listen
#. 列出你的 ring 群组::
$ ring-doorbell groups
#. 显示你的按铃历史::
$ ring-doorbell history --device-name "前门"
#. 显示你当前活跃的按铃::
$ ring-doorbell dings
#. 直接查询 ring api 网址::
$ ring-doorbell raw-query --url /clients_api/dings/active
#. 运行 ring-doorbell --help
或 ring-doorbell videos --help
获取完整选项
初始化你的 Ring 对象
.. code-block:: python
import getpass
import json
from pathlib import Path
from ring_doorbell import Auth, AuthenticationError, Requires2FAError, Ring
user_agent = "你的项目名称-1.0" # 修改这里
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 验证码: ")
return auth_code
def do_auth():
username = input("用户名: ")
password = getpass.getpass("密码: ")
auth = Auth(user_agent, None, token_updated)
try:
auth.fetch_token(username, password)
except Requires2FAError:
auth.fetch_token(username, password, otp_callback())
return auth
def main():
if cache_file.is_file(): # 认证令牌已缓存
auth = Auth(user_agent, json.loads(cache_file.read_text()), token_updated)
ring = Ring(auth)
try:
ring.create_session() # 认证令牌仍然有效
except AuthenticationError: # 认证令牌已过期
auth = do_auth()
else:
auth = do_auth() # 获取新的认证令牌
ring = Ring(auth)
ring.update_data()
devices = ring.devices()
print(devices)
if __name__ == "__main__":
main()
列出链接到你账户的设备
.. code-block:: python
所有设备
devices = ring.devices() {'chimes': [<RingChime: Downstairs>], 'doorbots': [<RingDoorBell: Front Door>]}
所有门铃
doorbells = devices['doorbots'] [<RingDoorBell: Front Door>]
所有门铃音箱
chimes = devices['chimes'] [<RingChime: Downstairs>]
所有便携式摄像头
stickup_cams = devices['stickup_cams'] [<RingStickUpCam: Driveway>]
使用属性和函数
.. code-block:: python
devices = ring.devices()
for dev in list(devices['stickup_cams'] + devices['chimes'] + devices['doorbots']):
dev.update_health_data()
print('地址: %s' % dev.address)
print('类型: %s' % dev.family)
print('ID: %s' % dev.id)
print('名称: %s' % dev.name)
print('时区: %s' % dev.timezone)
print('Wi-Fi名称: %s' % dev.wifi_name)
print('Wi-Fi信号强度: %s' % dev.wifi_signal_strength)
# 设置设备音量
print('音量: %s' % dev.volume)
dev.volume = 5
print('音量: %s' % dev.volume)
# 播放设备测试声音
if dev.family == 'chimes':
dev.test_sound(kind = 'ding')
dev.test_sound(kind = 'motion')
# 打开泛光灯摄像头的灯
if dev.family == 'stickup_cams' and dev.lights:
dev.lights = 'on'
显示门铃事件
.. code-block:: python
devices = ring.devices()
for doorbell in devices['doorbots']:
# 列出最近15个任意类型的事件
for event in doorbell.history(limit=15):
print('ID: %s' % event['id'])
print('类型: %s' % event['kind'])
print('是否应答: %s' % event['answered'])
print('时间: %s' % event['created_at'])
print('--' * 50)
# 获取仅由动作触发的事件列表
events = doorbell.history(kind='motion')
下载最近一个由按铃或动作事件触发的视频
.. code-block:: python
devices = ring.devices()
doorbell = devices['doorbots'][0]
doorbell.recording_download(
doorbell.history(limit=100, kind='ding')[0]['id'],
filename='last_ding.mp4',
override=True)
显示最后一个视频捕获的URL
.. code-block:: python
print(doorbell.recording_url(doorbell.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'
控制灯光组
.. code-block:: python
groups = ring.groups()
group = groups['你想要的组']
print(group.lights)
# 如果灯亮着打印True,如果关着打印False
# 无限期开灯
group.lights = True
# 关灯
group.lights = False
# 开灯30秒
group.lights = (True, 30)
如何贡献
请查看我们的贡献页面 <https://python-ring-doorbell.readthedocs.io/contributing.html>
_。
鸣谢
- 本项目受到 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)。