Skip to content

Add support for downloading snapshot from doorbell - #108

Merged
tchellomello merged 3 commits into
python-ring-doorbell:masterfrom
MorganBulkeley:MorganBulkeley-download-snapshot
Feb 11, 2019
Merged

Add support for downloading snapshot from doorbell#108
tchellomello merged 3 commits into
python-ring-doorbell:masterfrom
MorganBulkeley:MorganBulkeley-download-snapshot

Conversation

@MorganBulkeley

Copy link
Copy Markdown
Contributor

Adds support for downloading snapshots from the doorbell

https://support.ring.com/hc/en-us/articles/360000685566-Camera-Previews-FAQ

Comment thread ring_doorbell/doorbot.py Outdated
time.sleep(delay)
response = self._ring.query(url, method="POST", json=payload, raw=1).json()
if response["timestamps"][0]["timestamp"] / 100 > request_time:
return self._ring.query(API_URI + SNAPSHOT_ENDPOINT.format(self._attrs.get('id')), raw=True).content

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (116 > 79 characters)

Comment thread ring_doorbell/doorbot.py Outdated
request_time = time.time()
for _ in range(3):
time.sleep(delay)
response = self._ring.query(url, method="POST", json=payload, raw=1).json()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (87 > 79 characters)

Comment thread ring_doorbell/doorbot.py Outdated
DOORBELL_EXISTING_TYPE, DINGS_ENDPOINT, FILE_EXISTS,
LIVE_STREAMING_ENDPOINT, MSG_BOOLEAN_REQUIRED, MSG_EXISTING_TYPE,
MSG_VOL_OUTBOUND, URL_DOORBELL_HISTORY, URL_RECORDING)
MSG_VOL_OUTBOUND, SNAPSHOT_ENDPOINT, SNAPSHOT_TIMESTAMP_ENDPOINT, URL_DOORBELL_HISTORY, URL_RECORDING)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (106 > 79 characters)

Comment thread ring_doorbell/__init__.py
req = self.session.put((url), params=urlencode(params))
elif method == 'POST':
req = self.session.post((url), params=urlencode(params))
req = self.session.post((url), params=urlencode(params), json=json)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (87 > 79 characters)

@coveralls

coveralls commented Nov 29, 2018

Copy link
Copy Markdown

Coverage Status

Coverage decreased (-0.9%) to 64.286% when pulling 2ecd6e3 on MorganBulkeley:MorganBulkeley-download-snapshot into 50c940b on tchellomello:master.

@coveralls

Copy link
Copy Markdown

Coverage Status

Coverage decreased (-1.2%) to 63.972% when pulling b641268 on MorganBulkeley:MorganBulkeley-download-snapshot into 50c940b on tchellomello:master.

@tchellomello tchellomello self-assigned this Dec 6, 2018

@tchellomello tchellomello left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @MorganBulkeley,
Thanks for your contribution.
Could you please review the code style to make sure the tests pass?

Thank you!

Comment thread ring_doorbell/doorbot.py
for _ in range(retries):
time.sleep(delay)
response = self._ring.query(url, method="POST", json=payload,
raw=1).json()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

continuation line over-indented for visual indent

@10der

10der commented Dec 9, 2018

Copy link
Copy Markdown

look like it doesn't work.

if myring.is_connected:
   dev = myring.doorbells[0]
   print(dev.last_recording_id)
   snapshot = dev.get_snapshot()
   print(snapshot)

console

python.exe ring.py
2332445056122158153
False

I have removed loop and just return content as is without
check response["timestamps"][0]["timestamp"] / 1000 > request_time
now all ok.

strange.
fvvj9nvtvk

@10der

10der commented Dec 9, 2018

Copy link
Copy Markdown

UPD: about timestamps and request_time

            print(response["timestamps"][0]["timestamp"] / 1000)
            print(request_time)
1544388452
1544388505.49

False

@MorganBulkeley

Copy link
Copy Markdown
Contributor Author

Thanks for taking a look at this, I've been really busy these past few weeks and haven't had time to troubleshoot.

@odenisenko-zz

Copy link
Copy Markdown

JFYI: sometimes this function (not @MorganBulkeley) I am saying about ring api. working is not properly,
for example, my middle dau now went to walk. ring app said about motion but api said

if myring.is_connected:
   dev = myring.doorbells[0]
   ts = int(dev.get_last_snapshot_time())
   print(datetime.utcfromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S'))

python. ring.py
2018-12-15 08:55:21

be sensible of the fact that now 11:00 (AM)

@MorganBulkeley

Copy link
Copy Markdown
Contributor Author

@odenisenko Is your ring device battery powered? It may not update the frame to save power.

@problemss

Copy link
Copy Markdown

@MorganBulkeley is this working yet? I ran into the same error @odenisenko did. So I will also try to remove the check response["timestamps"][0]["timestamp"] / 1000 > request_time section as well.

@odenisenko-zz

Copy link
Copy Markdown

@MorganBulkeley is this working yet? I ran into the same error @odenisenko did. So I will also try to remove the check response["timestamps"][0]["timestamp"] / 1000 > request_time section as well.

last month my code is:

    def get_snapshot(self, retries=3, delay=1):
        """Take a snapshot and download it"""
        url = API_URI + SNAPSHOT_TIMESTAMP_ENDPOINT
        payload = {"doorbot_ids": [self._attrs.get('id')]}
        self._ring.query(url, json=payload)
        request_time = time.time()
        for _ in range(retries):
            time.sleep(delay)
            response = self._ring.query(url, method="POST", json=payload,
                                                            raw=1).json()
            # print(request_time - response["timestamps"][0]["timestamp"] / 1000)
            if request_time - response["timestamps"][0]["timestamp"] / 1000 < 200:
                return self._ring.query(API_URI + SNAPSHOT_ENDPOINT.format(
                                  self._attrs.get('id')), raw=True).content
        return False

yes, it's ugly but it works like a charm.

@problemss

Copy link
Copy Markdown

@odenisenko Thank you! Looks like it is working. Just have to save the contents of the snapshot now!

@problemss

Copy link
Copy Markdown

@odenisenko @MorganBulkeley Thank you both. This is working perfectly!!!

@TNNSLAB

TNNSLAB commented Jan 13, 2019

Copy link
Copy Markdown

Hey guys, when I do :

if myring.is_connected:
dev = myring.doorbells[0]
print(dev.last_recording_id)
snapshot = dev.get_snapshot()
print(snapshot)

I'm getting the id of the last recording, but no luck with the snapshot :( any thoughts ?

6645686099222589186

Traceback (most recent call last):
File "/Users/home/Desktop/ring.py", line 25, in
snapshot = dev.get_snapshot()
TypeError: 'bytes' object is not callable

@problemss

Copy link
Copy Markdown

This is not checked into the main branch.

@TNNSLAB

TNNSLAB commented Feb 3, 2019

Copy link
Copy Markdown

@problemss what do u mean ? sorry :(

@odenisenko-zz

Copy link
Copy Markdown

@problemss what do u mean ? sorry :(

this feature still not merged into the main branch,.

@tchellomello
tchellomello merged commit a3854e9 into python-ring-doorbell:master Feb 11, 2019
@tchellomello tchellomello mentioned this pull request Mar 5, 2019
@odenisenko-zz

Copy link
Copy Markdown

snapshot endpoint now return 401

@problemss

Copy link
Copy Markdown

Good to know I am not the only one receiving this error.

@tybritten

Copy link
Copy Markdown

I'm running 0.2.3 with a ring pro and the snapshot functionality works fine in the app, but when I try to call it I'm getting this:

6672079068379901730
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
  File "/usr/local/lib/python3.7/site-packages/ring_doorbell/doorbot.py", line 378, in get_snapshot
    self._ring.query(url, json=payload)
  File "/usr/local/lib/python3.7/site-packages/ring_doorbell/__init__.py", line 207, in query
    self._authenticate()
  File "/usr/local/lib/python3.7/site-packages/ring_doorbell/__init__.py", line 155, in _authenticate
    req.raise_for_status()
  File "/usr/local/lib/python3.7/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://api.ring.com/clients_api/session

All the other commands work fine, it's only get_snapshot that's getting an unauthorized message.

@haimiko

haimiko commented Nov 1, 2019

Copy link
Copy Markdown

Same 401 Auth error. It's because the _get_oauth_token is failing when getting the snapshot response 400

b'{"error":"invalid_request","error_description":"The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed."}\n'

But postman returns just fine for the very same oath data/endpoint. So i suspect something in the session. I tried preventing session reuse without luck.

@github-actions github-actions Bot locked and limited conversation to collaborators Apr 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants