Add ring switch platform (#25612)
* Add in a switch platform to ring. * Changes following code review * remove tests for now * remove the request to call update * support the new type of test * update after running black * fix comment * fixes following code review * Remove ring cache file * patch out io code * Move the patches to within a fixture * missing period
This commit is contained in:
parent
7ff7c7b9f5
commit
9e8df936ac
7 changed files with 745 additions and 1 deletions
108
homeassistant/components/ring/switch.py
Normal file
108
homeassistant/components/ring/switch.py
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
"""This component provides HA switch support for Ring Door Bell/Chimes."""
|
||||||
|
import logging
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from homeassistant.components.switch import SwitchDevice
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.core import callback
|
||||||
|
|
||||||
|
from . import DATA_RING_STICKUP_CAMS, SIGNAL_UPDATE_RING
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
SIREN_ICON = "mdi:alarm-bell"
|
||||||
|
|
||||||
|
|
||||||
|
# It takes a few seconds for the API to correctly return an update indicating
|
||||||
|
# that the changes have been made. Once we request a change (i.e. a light
|
||||||
|
# being turned on) we simply wait for this time delta before we allow
|
||||||
|
# updates to take place.
|
||||||
|
|
||||||
|
SKIP_UPDATES_DELAY = timedelta(seconds=5)
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
"""Create the switches for the Ring devices."""
|
||||||
|
cameras = hass.data[DATA_RING_STICKUP_CAMS]
|
||||||
|
switches = []
|
||||||
|
for device in cameras:
|
||||||
|
if device.has_capability("siren"):
|
||||||
|
switches.append(SirenSwitch(device))
|
||||||
|
|
||||||
|
add_entities(switches, True)
|
||||||
|
|
||||||
|
|
||||||
|
class BaseRingSwitch(SwitchDevice):
|
||||||
|
"""Represents a switch for controlling an aspect of a ring device."""
|
||||||
|
|
||||||
|
def __init__(self, device, device_type):
|
||||||
|
"""Initialize the switch."""
|
||||||
|
self._device = device
|
||||||
|
self._device_type = device_type
|
||||||
|
self._unique_id = "{}-{}".format(self._device.id, self._device_type)
|
||||||
|
|
||||||
|
async def async_added_to_hass(self):
|
||||||
|
"""Register callbacks."""
|
||||||
|
async_dispatcher_connect(self.hass, SIGNAL_UPDATE_RING, self._update_callback)
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _update_callback(self):
|
||||||
|
"""Call update method."""
|
||||||
|
_LOGGER.debug("Updating Ring sensor %s (callback)", self.name)
|
||||||
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Name of the device."""
|
||||||
|
return "{} {}".format(self._device.name, self._device_type)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return a unique ID."""
|
||||||
|
return self._unique_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def should_poll(self):
|
||||||
|
"""Update controlled via the hub."""
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class SirenSwitch(BaseRingSwitch):
|
||||||
|
"""Creates a switch to turn the ring cameras siren on and off."""
|
||||||
|
|
||||||
|
def __init__(self, device):
|
||||||
|
"""Initialize the switch for a device with a siren."""
|
||||||
|
super().__init__(device, "siren")
|
||||||
|
self._no_updates_until = datetime.now()
|
||||||
|
self._siren_on = False
|
||||||
|
|
||||||
|
def _set_switch(self, new_state):
|
||||||
|
"""Update switch state, and causes HASS to correctly update."""
|
||||||
|
self._device.siren = new_state
|
||||||
|
self._siren_on = new_state > 0
|
||||||
|
self._no_updates_until = datetime.now() + SKIP_UPDATES_DELAY
|
||||||
|
self.schedule_update_ha_state()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self):
|
||||||
|
"""If the switch is currently on or off."""
|
||||||
|
return self._siren_on
|
||||||
|
|
||||||
|
def turn_on(self, **kwargs):
|
||||||
|
"""Turn the siren on for 30 seconds."""
|
||||||
|
self._set_switch(1)
|
||||||
|
|
||||||
|
def turn_off(self, **kwargs):
|
||||||
|
"""Turn the siren off."""
|
||||||
|
self._set_switch(0)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def icon(self):
|
||||||
|
"""Return the icon."""
|
||||||
|
return SIREN_ICON
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
"""Update state of the siren."""
|
||||||
|
if self._no_updates_until > datetime.now():
|
||||||
|
_LOGGER.debug("Skipping update...")
|
||||||
|
return
|
||||||
|
self._siren_on = self._device.siren > 0
|
14
tests/components/ring/common.py
Normal file
14
tests/components/ring/common.py
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
"""Common methods used across the tests for ring devices."""
|
||||||
|
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, CONF_SCAN_INTERVAL
|
||||||
|
from homeassistant.components.ring import DOMAIN
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
|
||||||
|
async def setup_platform(hass, platform):
|
||||||
|
"""Set up the ring platform and prerequisites."""
|
||||||
|
config = {
|
||||||
|
DOMAIN: {CONF_USERNAME: "foo", CONF_PASSWORD: "bar", CONF_SCAN_INTERVAL: 1000},
|
||||||
|
platform: {"platform": DOMAIN},
|
||||||
|
}
|
||||||
|
assert await async_setup_component(hass, platform, config)
|
||||||
|
await hass.async_block_till_done()
|
54
tests/components/ring/conftest.py
Normal file
54
tests/components/ring/conftest.py
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
"""Configuration for Ring tests."""
|
||||||
|
import requests_mock
|
||||||
|
import pytest
|
||||||
|
from tests.common import load_fixture
|
||||||
|
from asynctest import patch
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="ring_mock")
|
||||||
|
def ring_save_mock():
|
||||||
|
"""Fixture to mock a ring."""
|
||||||
|
with patch("ring_doorbell._exists_cache", return_value=False):
|
||||||
|
with patch("ring_doorbell._save_cache", return_value=True) as save_mock:
|
||||||
|
yield save_mock
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(name="requests_mock")
|
||||||
|
def requests_mock_fixture(ring_mock):
|
||||||
|
"""Fixture to provide a requests mocker."""
|
||||||
|
with requests_mock.mock() as mock:
|
||||||
|
# Note all devices have an id of 987652, but a different device_id.
|
||||||
|
# the device_id is used as our unique_id, but the id is what is sent
|
||||||
|
# to the APIs, which is why every mock uses that id.
|
||||||
|
|
||||||
|
# Mocks the response for authenticating
|
||||||
|
mock.post(
|
||||||
|
"https://oauth.ring.com/oauth/token", text=load_fixture("ring_oauth.json")
|
||||||
|
)
|
||||||
|
# Mocks the response for getting the login session
|
||||||
|
mock.post(
|
||||||
|
"https://api.ring.com/clients_api/session",
|
||||||
|
text=load_fixture("ring_session.json"),
|
||||||
|
)
|
||||||
|
# Mocks the response for getting all the devices
|
||||||
|
mock.get(
|
||||||
|
"https://api.ring.com/clients_api/ring_devices",
|
||||||
|
text=load_fixture("ring_devices.json"),
|
||||||
|
)
|
||||||
|
# Mocks the response for getting the history of a device
|
||||||
|
mock.get(
|
||||||
|
"https://api.ring.com/clients_api/doorbots/987652/history",
|
||||||
|
text=load_fixture("ring_doorbots.json"),
|
||||||
|
)
|
||||||
|
# Mocks the response for getting the health of a device
|
||||||
|
mock.get(
|
||||||
|
"https://api.ring.com/clients_api/doorbots/987652/health",
|
||||||
|
text=load_fixture("ring_doorboot_health_attrs.json"),
|
||||||
|
)
|
||||||
|
# Mocks the response for getting a chimes health
|
||||||
|
mock.get(
|
||||||
|
"https://api.ring.com/clients_api/chimes/999999/health",
|
||||||
|
text=load_fixture("ring_chime_health_attrs.json"),
|
||||||
|
)
|
||||||
|
|
||||||
|
yield mock
|
75
tests/components/ring/test_switch.py
Normal file
75
tests/components/ring/test_switch.py
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
"""The tests for the Ring switch platform."""
|
||||||
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
|
from tests.common import load_fixture
|
||||||
|
from .common import setup_platform
|
||||||
|
|
||||||
|
|
||||||
|
async def test_entity_registry(hass, requests_mock):
|
||||||
|
"""Tests that the devices are registed in the entity registry."""
|
||||||
|
await setup_platform(hass, SWITCH_DOMAIN)
|
||||||
|
entity_registry = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
entry = entity_registry.async_get("switch.front_siren")
|
||||||
|
assert entry.unique_id == "aacdef123-siren"
|
||||||
|
|
||||||
|
entry = entity_registry.async_get("switch.internal_siren")
|
||||||
|
assert entry.unique_id == "aacdef124-siren"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_siren_off_reports_correctly(hass, requests_mock):
|
||||||
|
"""Tests that the initial state of a device that should be off is correct."""
|
||||||
|
await setup_platform(hass, SWITCH_DOMAIN)
|
||||||
|
|
||||||
|
state = hass.states.get("switch.front_siren")
|
||||||
|
assert state.state == "off"
|
||||||
|
assert state.attributes.get("friendly_name") == "Front siren"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_siren_on_reports_correctly(hass, requests_mock):
|
||||||
|
"""Tests that the initial state of a device that should be on is correct."""
|
||||||
|
await setup_platform(hass, SWITCH_DOMAIN)
|
||||||
|
|
||||||
|
state = hass.states.get("switch.internal_siren")
|
||||||
|
assert state.state == "on"
|
||||||
|
assert state.attributes.get("friendly_name") == "Internal siren"
|
||||||
|
assert state.attributes.get("icon") == "mdi:alarm-bell"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_siren_can_be_turned_on(hass, requests_mock):
|
||||||
|
"""Tests the siren turns on correctly."""
|
||||||
|
await setup_platform(hass, SWITCH_DOMAIN)
|
||||||
|
|
||||||
|
# Mocks the response for turning a siren on
|
||||||
|
requests_mock.put(
|
||||||
|
"https://api.ring.com/clients_api/doorbots/987652/siren_on",
|
||||||
|
text=load_fixture("ring_doorbot_siren_on_response.json"),
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("switch.front_siren")
|
||||||
|
assert state.state == "off"
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
"switch", "turn_on", {"entity_id": "switch.front_siren"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("switch.front_siren")
|
||||||
|
assert state.state == "on"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_updates_work(hass, requests_mock):
|
||||||
|
"""Tests the update service works correctly."""
|
||||||
|
await setup_platform(hass, SWITCH_DOMAIN)
|
||||||
|
state = hass.states.get("switch.front_siren")
|
||||||
|
assert state.state == "off"
|
||||||
|
# Changes the return to indicate that the siren is now on.
|
||||||
|
requests_mock.get(
|
||||||
|
"https://api.ring.com/clients_api/ring_devices",
|
||||||
|
text=load_fixture("ring_devices_updated.json"),
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.services.async_call("ring", "update", {}, blocking=True)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
state = hass.states.get("switch.front_siren")
|
||||||
|
assert state.state == "on"
|
139
tests/fixtures/ring_devices.json
vendored
139
tests/fixtures/ring_devices.json
vendored
|
@ -214,5 +214,142 @@
|
||||||
"subscribed": true,
|
"subscribed": true,
|
||||||
"subscribed_motions": true,
|
"subscribed_motions": true,
|
||||||
"time_zone": "America/New_York"
|
"time_zone": "America/New_York"
|
||||||
}]
|
},
|
||||||
|
{
|
||||||
|
"address": "123 Main St",
|
||||||
|
"alerts": {"connection": "online"},
|
||||||
|
"battery_life": 80,
|
||||||
|
"description": "Internal",
|
||||||
|
"device_id": "aacdef124",
|
||||||
|
"external_connection": false,
|
||||||
|
"features": {
|
||||||
|
"advanced_motion_enabled": false,
|
||||||
|
"motion_message_enabled": false,
|
||||||
|
"motions_enabled": true,
|
||||||
|
"night_vision_enabled": false,
|
||||||
|
"people_only_enabled": false,
|
||||||
|
"shadow_correction_enabled": false,
|
||||||
|
"show_recordings": true},
|
||||||
|
"firmware_version": "1.9.3",
|
||||||
|
"id": 987652,
|
||||||
|
"kind": "hp_cam_v1",
|
||||||
|
"latitude": 12.000000,
|
||||||
|
"led_status": "off",
|
||||||
|
"location_id": null,
|
||||||
|
"longitude": -70.12345,
|
||||||
|
"motion_snooze": {"scheduled": true},
|
||||||
|
"night_mode_status": "false",
|
||||||
|
"owned": true,
|
||||||
|
"owner": {
|
||||||
|
"email": "foo@bar.org",
|
||||||
|
"first_name": "Foo",
|
||||||
|
"id": 999999,
|
||||||
|
"last_name": "Bar"},
|
||||||
|
"ring_cam_light_installed": "false",
|
||||||
|
"ring_id": null,
|
||||||
|
"settings": {
|
||||||
|
"chime_settings": {
|
||||||
|
"duration": 10,
|
||||||
|
"enable": true,
|
||||||
|
"type": 0},
|
||||||
|
"doorbell_volume": 11,
|
||||||
|
"enable_vod": true,
|
||||||
|
"floodlight_settings": {
|
||||||
|
"duration": 30,
|
||||||
|
"priority": 0},
|
||||||
|
"light_schedule_settings": {
|
||||||
|
"end_hour": 0,
|
||||||
|
"end_minute": 0,
|
||||||
|
"start_hour": 0,
|
||||||
|
"start_minute": 0},
|
||||||
|
"live_view_preset_profile": "highest",
|
||||||
|
"live_view_presets": [
|
||||||
|
"low",
|
||||||
|
"middle",
|
||||||
|
"high",
|
||||||
|
"highest"],
|
||||||
|
"motion_announcement": false,
|
||||||
|
"motion_snooze_preset_profile": "low",
|
||||||
|
"motion_snooze_presets": [
|
||||||
|
"none",
|
||||||
|
"low",
|
||||||
|
"medium",
|
||||||
|
"high"],
|
||||||
|
"motion_zones": {
|
||||||
|
"active_motion_filter": 1,
|
||||||
|
"advanced_object_settings": {
|
||||||
|
"human_detection_confidence": {
|
||||||
|
"day": 0.7,
|
||||||
|
"night": 0.7},
|
||||||
|
"motion_zone_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.2},
|
||||||
|
"object_size_maximum": {
|
||||||
|
"day": 0.8,
|
||||||
|
"night": 0.8},
|
||||||
|
"object_size_minimum": {
|
||||||
|
"day": 0.03,
|
||||||
|
"night": 0.05},
|
||||||
|
"object_time_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.6}
|
||||||
|
},
|
||||||
|
"enable_audio": false,
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"sensitivity": 5,
|
||||||
|
"zone1": {
|
||||||
|
"name": "Zone 1",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone2": {
|
||||||
|
"name": "Zone 2",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone3": {
|
||||||
|
"name": "Zone 3",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}}},
|
||||||
|
"pir_motion_zones": [0, 1, 1],
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"stream_setting": 0,
|
||||||
|
"video_settings": {
|
||||||
|
"ae_level": 0,
|
||||||
|
"birton": null,
|
||||||
|
"brightness": 0,
|
||||||
|
"contrast": 64,
|
||||||
|
"saturation": 80}},
|
||||||
|
"siren_status": {"seconds_remaining": 30},
|
||||||
|
"stolen": false,
|
||||||
|
"subscribed": true,
|
||||||
|
"subscribed_motions": true,
|
||||||
|
"time_zone": "America/New_York"}]
|
||||||
}
|
}
|
||||||
|
|
355
tests/fixtures/ring_devices_updated.json
vendored
Normal file
355
tests/fixtures/ring_devices_updated.json
vendored
Normal file
|
@ -0,0 +1,355 @@
|
||||||
|
{
|
||||||
|
"authorized_doorbots": [],
|
||||||
|
"chimes": [
|
||||||
|
{
|
||||||
|
"address": "123 Main St",
|
||||||
|
"alerts": {"connection": "online"},
|
||||||
|
"description": "Downstairs",
|
||||||
|
"device_id": "abcdef123",
|
||||||
|
"do_not_disturb": {"seconds_left": 0},
|
||||||
|
"features": {"ringtones_enabled": true},
|
||||||
|
"firmware_version": "1.2.3",
|
||||||
|
"id": 999999,
|
||||||
|
"kind": "chime",
|
||||||
|
"latitude": 12.000000,
|
||||||
|
"longitude": -70.12345,
|
||||||
|
"owned": true,
|
||||||
|
"owner": {
|
||||||
|
"email": "foo@bar.org",
|
||||||
|
"first_name": "Marcelo",
|
||||||
|
"id": 999999,
|
||||||
|
"last_name": "Assistant"},
|
||||||
|
"settings": {
|
||||||
|
"ding_audio_id": null,
|
||||||
|
"ding_audio_user_id": null,
|
||||||
|
"motion_audio_id": null,
|
||||||
|
"motion_audio_user_id": null,
|
||||||
|
"volume": 2},
|
||||||
|
"time_zone": "America/New_York"}],
|
||||||
|
"doorbots": [
|
||||||
|
{
|
||||||
|
"address": "123 Main St",
|
||||||
|
"alerts": {"connection": "online"},
|
||||||
|
"battery_life": 4081,
|
||||||
|
"description": "Front Door",
|
||||||
|
"device_id": "aacdef123",
|
||||||
|
"external_connection": false,
|
||||||
|
"features": {
|
||||||
|
"advanced_motion_enabled": false,
|
||||||
|
"motion_message_enabled": false,
|
||||||
|
"motions_enabled": true,
|
||||||
|
"people_only_enabled": false,
|
||||||
|
"shadow_correction_enabled": false,
|
||||||
|
"show_recordings": true},
|
||||||
|
"firmware_version": "1.4.26",
|
||||||
|
"id": 987652,
|
||||||
|
"kind": "lpd_v1",
|
||||||
|
"latitude": 12.000000,
|
||||||
|
"longitude": -70.12345,
|
||||||
|
"motion_snooze": null,
|
||||||
|
"owned": true,
|
||||||
|
"owner": {
|
||||||
|
"email": "foo@bar.org",
|
||||||
|
"first_name": "Home",
|
||||||
|
"id": 999999,
|
||||||
|
"last_name": "Assistant"},
|
||||||
|
"settings": {
|
||||||
|
"chime_settings": {
|
||||||
|
"duration": 3,
|
||||||
|
"enable": true,
|
||||||
|
"type": 0},
|
||||||
|
"doorbell_volume": 1,
|
||||||
|
"enable_vod": true,
|
||||||
|
"live_view_preset_profile": "highest",
|
||||||
|
"live_view_presets": [
|
||||||
|
"low",
|
||||||
|
"middle",
|
||||||
|
"high",
|
||||||
|
"highest"],
|
||||||
|
"motion_announcement": false,
|
||||||
|
"motion_snooze_preset_profile": "low",
|
||||||
|
"motion_snooze_presets": [
|
||||||
|
"null",
|
||||||
|
"low",
|
||||||
|
"medium",
|
||||||
|
"high"]},
|
||||||
|
"subscribed": true,
|
||||||
|
"subscribed_motions": true,
|
||||||
|
"time_zone": "America/New_York"}],
|
||||||
|
"stickup_cams": [
|
||||||
|
{
|
||||||
|
"address": "123 Main St",
|
||||||
|
"alerts": {"connection": "online"},
|
||||||
|
"battery_life": 80,
|
||||||
|
"description": "Front",
|
||||||
|
"device_id": "aacdef123",
|
||||||
|
"external_connection": false,
|
||||||
|
"features": {
|
||||||
|
"advanced_motion_enabled": false,
|
||||||
|
"motion_message_enabled": false,
|
||||||
|
"motions_enabled": true,
|
||||||
|
"night_vision_enabled": false,
|
||||||
|
"people_only_enabled": false,
|
||||||
|
"shadow_correction_enabled": false,
|
||||||
|
"show_recordings": true},
|
||||||
|
"firmware_version": "1.9.3",
|
||||||
|
"id": 987652,
|
||||||
|
"kind": "hp_cam_v1",
|
||||||
|
"latitude": 12.000000,
|
||||||
|
"led_status": "off",
|
||||||
|
"location_id": null,
|
||||||
|
"longitude": -70.12345,
|
||||||
|
"motion_snooze": {"scheduled": true},
|
||||||
|
"night_mode_status": "false",
|
||||||
|
"owned": true,
|
||||||
|
"owner": {
|
||||||
|
"email": "foo@bar.org",
|
||||||
|
"first_name": "Foo",
|
||||||
|
"id": 999999,
|
||||||
|
"last_name": "Bar"},
|
||||||
|
"ring_cam_light_installed": "false",
|
||||||
|
"ring_id": null,
|
||||||
|
"settings": {
|
||||||
|
"chime_settings": {
|
||||||
|
"duration": 10,
|
||||||
|
"enable": true,
|
||||||
|
"type": 0},
|
||||||
|
"doorbell_volume": 11,
|
||||||
|
"enable_vod": true,
|
||||||
|
"floodlight_settings": {
|
||||||
|
"duration": 30,
|
||||||
|
"priority": 0},
|
||||||
|
"light_schedule_settings": {
|
||||||
|
"end_hour": 0,
|
||||||
|
"end_minute": 0,
|
||||||
|
"start_hour": 0,
|
||||||
|
"start_minute": 0},
|
||||||
|
"live_view_preset_profile": "highest",
|
||||||
|
"live_view_presets": [
|
||||||
|
"low",
|
||||||
|
"middle",
|
||||||
|
"high",
|
||||||
|
"highest"],
|
||||||
|
"motion_announcement": false,
|
||||||
|
"motion_snooze_preset_profile": "low",
|
||||||
|
"motion_snooze_presets": [
|
||||||
|
"none",
|
||||||
|
"low",
|
||||||
|
"medium",
|
||||||
|
"high"],
|
||||||
|
"motion_zones": {
|
||||||
|
"active_motion_filter": 1,
|
||||||
|
"advanced_object_settings": {
|
||||||
|
"human_detection_confidence": {
|
||||||
|
"day": 0.7,
|
||||||
|
"night": 0.7},
|
||||||
|
"motion_zone_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.2},
|
||||||
|
"object_size_maximum": {
|
||||||
|
"day": 0.8,
|
||||||
|
"night": 0.8},
|
||||||
|
"object_size_minimum": {
|
||||||
|
"day": 0.03,
|
||||||
|
"night": 0.05},
|
||||||
|
"object_time_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.6}
|
||||||
|
},
|
||||||
|
"enable_audio": false,
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"sensitivity": 5,
|
||||||
|
"zone1": {
|
||||||
|
"name": "Zone 1",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone2": {
|
||||||
|
"name": "Zone 2",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone3": {
|
||||||
|
"name": "Zone 3",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}}},
|
||||||
|
"pir_motion_zones": [0, 1, 1],
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"stream_setting": 0,
|
||||||
|
"video_settings": {
|
||||||
|
"ae_level": 0,
|
||||||
|
"birton": null,
|
||||||
|
"brightness": 0,
|
||||||
|
"contrast": 64,
|
||||||
|
"saturation": 80}},
|
||||||
|
"siren_status": {"seconds_remaining": 30},
|
||||||
|
"stolen": false,
|
||||||
|
"subscribed": true,
|
||||||
|
"subscribed_motions": true,
|
||||||
|
"time_zone": "America/New_York"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": "123 Main St",
|
||||||
|
"alerts": {"connection": "online"},
|
||||||
|
"battery_life": 80,
|
||||||
|
"description": "Internal",
|
||||||
|
"device_id": "aacdef124",
|
||||||
|
"external_connection": false,
|
||||||
|
"features": {
|
||||||
|
"advanced_motion_enabled": false,
|
||||||
|
"motion_message_enabled": false,
|
||||||
|
"motions_enabled": true,
|
||||||
|
"night_vision_enabled": false,
|
||||||
|
"people_only_enabled": false,
|
||||||
|
"shadow_correction_enabled": false,
|
||||||
|
"show_recordings": true},
|
||||||
|
"firmware_version": "1.9.3",
|
||||||
|
"id": 987652,
|
||||||
|
"kind": "hp_cam_v1",
|
||||||
|
"latitude": 12.000000,
|
||||||
|
"led_status": "off",
|
||||||
|
"location_id": null,
|
||||||
|
"longitude": -70.12345,
|
||||||
|
"motion_snooze": {"scheduled": true},
|
||||||
|
"night_mode_status": "false",
|
||||||
|
"owned": true,
|
||||||
|
"owner": {
|
||||||
|
"email": "foo@bar.org",
|
||||||
|
"first_name": "Foo",
|
||||||
|
"id": 999999,
|
||||||
|
"last_name": "Bar"},
|
||||||
|
"ring_cam_light_installed": "false",
|
||||||
|
"ring_id": null,
|
||||||
|
"settings": {
|
||||||
|
"chime_settings": {
|
||||||
|
"duration": 10,
|
||||||
|
"enable": true,
|
||||||
|
"type": 0},
|
||||||
|
"doorbell_volume": 11,
|
||||||
|
"enable_vod": true,
|
||||||
|
"floodlight_settings": {
|
||||||
|
"duration": 30,
|
||||||
|
"priority": 0},
|
||||||
|
"light_schedule_settings": {
|
||||||
|
"end_hour": 0,
|
||||||
|
"end_minute": 0,
|
||||||
|
"start_hour": 0,
|
||||||
|
"start_minute": 0},
|
||||||
|
"live_view_preset_profile": "highest",
|
||||||
|
"live_view_presets": [
|
||||||
|
"low",
|
||||||
|
"middle",
|
||||||
|
"high",
|
||||||
|
"highest"],
|
||||||
|
"motion_announcement": false,
|
||||||
|
"motion_snooze_preset_profile": "low",
|
||||||
|
"motion_snooze_presets": [
|
||||||
|
"none",
|
||||||
|
"low",
|
||||||
|
"medium",
|
||||||
|
"high"],
|
||||||
|
"motion_zones": {
|
||||||
|
"active_motion_filter": 1,
|
||||||
|
"advanced_object_settings": {
|
||||||
|
"human_detection_confidence": {
|
||||||
|
"day": 0.7,
|
||||||
|
"night": 0.7},
|
||||||
|
"motion_zone_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.2},
|
||||||
|
"object_size_maximum": {
|
||||||
|
"day": 0.8,
|
||||||
|
"night": 0.8},
|
||||||
|
"object_size_minimum": {
|
||||||
|
"day": 0.03,
|
||||||
|
"night": 0.05},
|
||||||
|
"object_time_overlap": {
|
||||||
|
"day": 0.1,
|
||||||
|
"night": 0.6}
|
||||||
|
},
|
||||||
|
"enable_audio": false,
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"sensitivity": 5,
|
||||||
|
"zone1": {
|
||||||
|
"name": "Zone 1",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone2": {
|
||||||
|
"name": "Zone 2",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}},
|
||||||
|
"zone3": {
|
||||||
|
"name": "Zone 3",
|
||||||
|
"state": 2,
|
||||||
|
"vertex1": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex2": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex3": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex4": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex5": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex6": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex7": {"x": 0.0, "y": 0.0},
|
||||||
|
"vertex8": {"x": 0.0, "y": 0.0}}},
|
||||||
|
"pir_motion_zones": [0, 1, 1],
|
||||||
|
"pir_settings": {
|
||||||
|
"sensitivity1": 1,
|
||||||
|
"sensitivity2": 1,
|
||||||
|
"sensitivity3": 1,
|
||||||
|
"zone_mask": 6},
|
||||||
|
"stream_setting": 0,
|
||||||
|
"video_settings": {
|
||||||
|
"ae_level": 0,
|
||||||
|
"birton": null,
|
||||||
|
"brightness": 0,
|
||||||
|
"contrast": 64,
|
||||||
|
"saturation": 80}},
|
||||||
|
"siren_status": {"seconds_remaining": 30},
|
||||||
|
"stolen": false,
|
||||||
|
"subscribed": true,
|
||||||
|
"subscribed_motions": true,
|
||||||
|
"time_zone": "America/New_York"}]
|
||||||
|
}
|
1
tests/fixtures/ring_doorbot_siren_on_response.json
vendored
Normal file
1
tests/fixtures/ring_doorbot_siren_on_response.json
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"started_at":"2019-07-28T16:58:27.593+00:00","duration":30,"ends_at":"2019-07-28T16:58:57.593+00:00","seconds_remaining":30}
|
Loading…
Add table
Reference in a new issue