Skip to content

Per camera snooze#1135

Open
austinc3030 wants to merge 24 commits intofronzbot:devfrom
dynacylabs:per_camera_snooze
Open

Per camera snooze#1135
austinc3030 wants to merge 24 commits intofronzbot:devfrom
dynacylabs:per_camera_snooze

Conversation

@austinc3030
Copy link

Description:

Related Issue: #955

This PR adds support for snoozing cameras.

Been running this for over a year with no issues snoozing cameras. While not "scientifically" tested, my script using this PR continues to arm/disarm, as well as take snapshots.

Could use some help with tox tests.

Related issue (if applicable): fixes #

Checklist:

  • Local tests with tox run successfully PR cannot be meged unless tests pass
  • Changes tested locally to ensure platform still works as intended
  • Tests added to verify new code works

@austinc3030
Copy link
Author

Sorry but I am working on another feature and needed to move my Camera Snooze commits to a new branch.

@fronzbot
Copy link
Owner

@austinc3030 sounds good. I didn't review the other PR because you had it marked as WIP so I assumed you were still working on it. I'll review this when I have some time (hopefully this week).

Comment on lines 182 to 184
if res is None:
return None
return res.get("camera", [{}])[0].get("snooze_till")
Copy link
Owner

Choose a reason for hiding this comment

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

There's no indication to the user if this fails. I think a better approach would be to either let it raise an exception OR catch the exception and log an error/warning. I tend to favor the latter, but could be convinced either way.

Suggested change
if res is None:
return None
return res.get("camera", [{}])[0].get("snooze_till")
try:
return res["camera"][0]["snooze_till"]
except TypeError:
return None
except (IndexError, KeyError) as e:
_LOGGER.warning("Exception %s: Encountered a likely malformed response from the snooze API endpoint. Response: %s", e, res)

Copy link
Author

Choose a reason for hiding this comment

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

Addressed in 050dca6

import logging
import string
import datetime
from json import dumps
Copy link
Owner

Choose a reason for hiding this comment

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

Remove this. sync_module.py already has access to this through the json_dumps method in blinkpy.helpers.util

Suggested change
from json import dumps

Copy link
Author

Choose a reason for hiding this comment

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

Addressed in 8009230


async def async_snooze(self, snooze_time=240):
"""Set sync snooze status."""
data = dumps({"snooze_time": snooze_time})
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
data = dumps({"snooze_time": snooze_time})
data = json_dumps({"snooze_time": snooze_time})

Copy link
Author

Choose a reason for hiding this comment

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

Addressed in 8009230

return_value=mock_resp,
):
result = await self.camera.snooze_till
self.assertEqual(result, {"camera": [{"snooze_till": 1234567890}]})
Copy link
Owner

Choose a reason for hiding this comment

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

The self.camera.snooze_till method returns the snooze_till value, not the full dictionary (based on your implementation. I don't know what your intent was, but this makes sense to me).

So this should be the following, assuming it was your code intent:

Suggested change
self.assertEqual(result, {"camera": [{"snooze_till": 1234567890}]})
self.assertEqual(result, 1234567890)

Copy link
Author

Choose a reason for hiding this comment

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

This test was removed. Will be adding new tests.

with mock.patch("blinkpy.api.request_camera_snooze", return_value=mock_resp):
response = await self.camera.async_snooze()
self.assertEqual(response, {})
mock_resp = mresp.MockResponse({}, 200)
Copy link
Owner

Choose a reason for hiding this comment

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

This is failing and I think it's related to my confusion earlier. I believe the BlinkCamera.async_snooze method is supposed to grab the json data (like you do in the Doorbell class). If that's true and works to fix this, then you don't need to overload the async_snooze method in the Doorbell class since both functions will be identical.

Copy link
Author

Choose a reason for hiding this comment

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

This test was removed and new tests will be added.

"""Tests camera and system functions."""

import datetime
from json import dumps
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
from json import dumps
from blinkpy.helpers.util import json_dumps

Copy link
Author

Choose a reason for hiding this comment

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

Removed

mock_resp_local.return_value.status = 200
mock_resp_local.return_value.json.return_value = {"status": 200}
snooze_time = 240
expected_data = dumps({"snooze_time": snooze_time})
Copy link
Owner

Choose a reason for hiding this comment

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

Suggested change
expected_data = dumps({"snooze_time": snooze_time})
expected_data = json_dumps({"snooze_time": snooze_time})

Copy link
Author

Choose a reason for hiding this comment

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

Removed

return None
return res.get("camera", [{}])[0].get("snooze_till")

async def async_snooze(self, snooze_time=240):
Copy link
Owner

Choose a reason for hiding this comment

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

what are the units of snooze_time? Please annotate this in the docstring. It looks like these are in seconds?

Copy link
Author

Choose a reason for hiding this comment

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

Addressed in a7aa35d

Snooze time is in minutes.

Copy link
Author

Choose a reason for hiding this comment

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

Actually, snooze time used to be minutes (hence the 240 value, 4 hours). However, it now looks like snooze time is in seconds (240 = 4 minutes). This appears to be a change to how blink's API is handling the value.

@fronzbot
Copy link
Owner

fronzbot commented Jan 4, 2026

@austinc3030 are you still working on this PR? I reviewed it a few months back with no response.

Repository owner deleted a comment from jmgarcia1230-commits Jan 6, 2026
@austinc3030
Copy link
Author

Hey, @fronzbot.

You know how it goes: life got busy around the holidays and I completely forgot to circle back to this.

I will try to pick this up this week. Thanks for the ping.

@austinc3030
Copy link
Author

I don't recall the current state of this but last I remember, camera snooze worked for all cameras except I am hitting an issue with my new Blink Arc cameras. They don't snooze with the current implementation. I was working on a fix for this along side this PR. I will review and update.

@austinc3030 austinc3030 marked this pull request as draft February 9, 2026 20:08
@austinc3030
Copy link
Author

Converted to draft while I work on this. Should be ready this week. Will add a new comment when ready. Thank you for your patience.

@austinc3030 austinc3030 marked this pull request as ready for review February 10, 2026 18:32
@austinc3030 austinc3030 requested a review from fronzbot February 10, 2026 18:33
@austinc3030
Copy link
Author

@fronzbot I believe we are in a good state now and ready for re-review. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants