Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sensor and camera support to SimpliSafe #40129

Closed
wants to merge 4 commits into from
Closed

Add sensor and camera support to SimpliSafe #40129

wants to merge 4 commits into from

Conversation

nzapponi
Copy link
Contributor

Proposed change

This PR adds support to SimpliSafe sensors, cameras and doorbells. Cameras appear not to work with HomeKit bridge, whereas everything else looks good!

Type of change

  • Dependency upgrade
  • Bugfix (non-breaking change which fixes an issue)
  • New integration (thank you!)
  • New feature (which adds functionality to an existing integration)
  • Breaking change (fix/feature causing existing functionality to break)
  • Code quality improvements to existing code or addition of tests

Additional information

  • This PR fixes or closes issue: fixes #
  • This PR is related to issue:
  • Link to documentation pull request:

I also need some support in writing out some tests. I noticed that the SimpliSafe component generally does not have many tests except for config_flow, so there are quite a few that need to be written out.

Checklist

  • The code change is tested and works locally.
  • Local tests pass. Your PR cannot be merged unless tests pass
  • There is no commented out code in this PR.
  • I have followed the development checklist
  • The code has been formatted using Black (black --fast homeassistant tests)
  • Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

If the code communicates with devices, web services, or third-party tools:

  • The manifest file has all fields filled out correctly.
    Updated and included derived files by running: python3 -m script.hassfest.
  • New or updated dependencies have been added to requirements_all.txt.
    Updated by running python3 -m script.gen_requirements_all.
  • Untested files have been added to .coveragerc.

The integration reached or maintains the following Integration Quality Scale:

  • No score or internal
  • 🥈 Silver
  • 🥇 Gold
  • 🏆 Platinum

To help with the load of incoming pull requests:

@nzapponi
Copy link
Contributor Author

@bachya could you please take a look at the above?
Also, I also need some support in writing out some tests. I noticed that the SimpliSafe component generally does not have many tests except for config_flow, so there are quite a few that need to be written out... Could we work together on these?

@probot-home-assistant
Copy link

Hey there @bachya, mind taking a look at this pull request as its been labeled with an integration (simplisafe) you are listed as a codeowner for? Thanks!
(message by CodeOwnersMention)

Copy link
Contributor

@bachya bachya left a comment

Choose a reason for hiding this comment

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

Hi @nzapponi – thank you for your contribution.

I've left you some specific code review comments, but in general, this PR won't work in its current form. Multiple things going on:

First, because of the popularity of the request, a previous attempt to integrate SimpliSafe sensors was made in #30926. The primary comment to notice:

After running this for a bit, I’m not happy with the results. The extra hop introduced here - in which HASS talks to the SimpliSafe cloud, which talks to the base station - can be very laggy, especially during HASS startup. I don’t think that’s a particular good user experience, so I’m going to close this. Should SimpliSafe ever update their architecture to be more responsive to what we’d like to do, I will re-open.

Your PR uses the same polling mechanisms attempted there; since nothing has fundamentally changed, I'm not comfortable with the approach.

Second, this PR is much too large - you're attempting to add multiple platforms (sensors, cameras, etc.), all while modifying code that is already there. In general, PRs should focus on a single piece of functionality/change.

Lastly, you mention tests – in general, Home Assistant allows for ignoring device/service-specific code from test coverage (via .coveragerc); in the case of this integration, I focus my non-HASS testing efforts in simplisafe-python.

doorbells = []
for system in simplisafe.systems.values():
if (
"cameras" in system._location_info["system"]
Copy link
Contributor

@bachya bachya Sep 16, 2020

Choose a reason for hiding this comment

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

We should not be accessing a protected attribute here – this should be abstracted out in simplisafe-python.

@callback
def async_update_from_rest_api(self):
"""Update the entity with the provided REST API data."""
self._is_on = self._sensor.triggered
Copy link
Contributor

Choose a reason for hiding this comment

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

This is only going to show as triggered every 30 seconds (i.e., each time the REST API polls).

def async_update_from_websocket_event(self, event):
"""Update the entity with the provided websocket event data."""
if (
event.event_type == EVENT_MOTION_DETECTED
Copy link
Contributor

Choose a reason for hiding this comment

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

I understand that other integrations surface events like this as entities, but we already have a way to detect (and run automation on) these events: https://www.home-assistant.io/integrations/simplisafe/#events – what does your implementation provide beyond the event architecture?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is to surface this as a visible binary sensor in the UI, like other motion sensors. I've taken the implementation from similar sensors already implemented in HA.

Copy link
Contributor

Choose a reason for hiding this comment

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

But why is that UI needed (especially since we're manually flipping the sensor 10 seconds later)? The events provide the same mechanism, but in a more flexible way (which can create notifications, etc.).

@property
def _video_url(self):
"""Provide the video URL."""
return '{} -i "https://media.simplisafe.com/v1/{}/flv?x=1280&audioEncoding=AAC"'.format(
Copy link
Contributor

@bachya bachya Sep 16, 2020

Choose a reason for hiding this comment

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

This shouldn't be so explicit and should be abstracted away in simplisafe-python. In addition, please see this ongoing simplisafe-python issue re: camera support; the URL you use here isn't long-lived and has several other issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The URL is long lived, the auth token isn't. It works for the odd check of the camera. Yes, if you want to continuously stream for hours, then this is not a good implementation, but for the odd check for a few minutes it's absolutely fine.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's good to know. Nevertheless, HASS shouldn't be aware of these implementation details; they belong in simplisafe-python.

@@ -38,6 +38,11 @@ def __init__(self, simplisafe, system, lock):
for event_type in (EVENT_LOCK_LOCKED, EVENT_LOCK_UNLOCKED):
self.websocket_events_to_listen_for.append(event_type)

@property
Copy link
Contributor

Choose a reason for hiding this comment

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

Why? The SimpliSafeEntity class from which the SimpliSafeLock class inherits already has a unique ID defined.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair enough

@@ -517,7 +529,7 @@ async def async_update(self):

async def update_system(system):
"""Update a system."""
await system.update()
await system.update(cached=False)
Copy link
Contributor

Choose a reason for hiding this comment

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

We can't do this – their API isn't structured to properly support that. See this attempt for more details: #30926

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Why not? See my comment below - it runs fine on SimpliSafe 3.

Copy link
Contributor

Choose a reason for hiding this comment

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

I appreciate the thinking, but again, I don't see the value for door/window sensors that poll for state every 30 seconds; if someone opens/closes a door within that timeframe, HASS will never hear about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The use case isn't just triggering something when a door/window sensor opens, but it is also to check the current state of the sensor, e.g. check if there are any open windows before leaving the house. There's still value in this use case, and it doesn't require real time sensor data.
Also, we can poll every 15 seconds without any issues.

Copy link
Contributor

Choose a reason for hiding this comment

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

I hear you and can see the validity. Overall, I'm concerned that if tens/hundreds/more of HASS users start pinging SimpliSafe's cloud every 15 seconds in an un-cached way, we're going to get blocked off for good. That's definitely my own fear and not substantiated in any way. 😆

I'm definitely open to continuing the conversation, but at a minimum, I think the simplisafe-python work mentioned throughout needs to be looked at before this PR can proceed. Feel free to start looking around and let me know of any questions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Alright, let me rework some of these changes into simplisafe-python. I'm aware they're meant to be in there but I wanted to start by getting something functional up and running first.

I'll close this PR and will re-open a few smaller ones once simplisafe-python is updated.

):
for cam in system._location_info["system"]["cameras"]:
cameras.append(cam)
if cam["model"] == "SS002":
Copy link
Contributor

Choose a reason for hiding this comment

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

What is this? Seems brittle to have it hardcoded here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is how doorbells are differentiated vs standard cameras.

Copy link
Contributor

Choose a reason for hiding this comment

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

HASS shouldn't be aware of such details. This is better suited for simplisafe-python.

@nzapponi
Copy link
Contributor Author

Hi @bachya ,
I have created this same integration for Homebridge (https://github.com/nzapponi/homebridge-simplisafe3) and, aside from the odd hiccup once a month or so, it actually works really well. I've been running it for over a year with very little issues.
Yes, there is a slight delay in getting updates from sensors, but nothing different than other cloud polling integrations...

As a SimpliSafe customer, I'd rather get something in Home Assistant, even if not perfect, than nothing at all and be forced to put two sensors on each door.

We can caveat all this in user documentation, but honestly I don't see why we shouldn't be providing some basic functionality here.

I agree with you re cameras - we should be moving some of that logic into simplisafe-python.

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

Successfully merging this pull request may close these issues.

3 participants