Cleanup August activity processing and add tests (#31774)
* Update py-august to 0.12.0 * Upstream update also resolves issue #28960
This commit is contained in:
parent
834acd85d3
commit
6879105b14
10 changed files with 378 additions and 52 deletions
|
@ -2,7 +2,7 @@
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from august.activity import ActivityType
|
from august.activity import ACTIVITY_ACTION_STATES, ActivityType
|
||||||
from august.lock import LockDoorStatus
|
from august.lock import LockDoorStatus
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorDevice
|
from homeassistant.components.binary_sensor import BinarySensorDevice
|
||||||
|
@ -138,12 +138,12 @@ class AugustDoorBinarySensor(BinarySensorDevice):
|
||||||
|
|
||||||
self._state = self._state == LockDoorStatus.OPEN
|
self._state = self._state == LockDoorStatus.OPEN
|
||||||
|
|
||||||
activity = self._data.get_latest_device_activity(
|
door_activity = self._data.get_latest_device_activity(
|
||||||
self._door.device_id, ActivityType.DOOR_OPERATION
|
self._door.device_id, ActivityType.DOOR_OPERATION
|
||||||
)
|
)
|
||||||
|
|
||||||
if activity is not None:
|
if door_activity is not None:
|
||||||
self._sync_door_activity(activity)
|
self._sync_door_activity(door_activity)
|
||||||
|
|
||||||
def _update_door_state(self, door_state, update_start_time):
|
def _update_door_state(self, door_state, update_start_time):
|
||||||
new_state = door_state == LockDoorStatus.OPEN
|
new_state = door_state == LockDoorStatus.OPEN
|
||||||
|
@ -153,7 +153,7 @@ class AugustDoorBinarySensor(BinarySensorDevice):
|
||||||
self._door.device_id, door_state, update_start_time
|
self._door.device_id, door_state, update_start_time
|
||||||
)
|
)
|
||||||
|
|
||||||
def _sync_door_activity(self, activity):
|
def _sync_door_activity(self, door_activity):
|
||||||
"""Check the activity for the latest door open/close activity (events).
|
"""Check the activity for the latest door open/close activity (events).
|
||||||
|
|
||||||
We use this to determine the door state in between calls to the lock
|
We use this to determine the door state in between calls to the lock
|
||||||
|
@ -162,25 +162,26 @@ class AugustDoorBinarySensor(BinarySensorDevice):
|
||||||
last_door_state_update_time_utc = self._data.get_last_door_state_update_time_utc(
|
last_door_state_update_time_utc = self._data.get_last_door_state_update_time_utc(
|
||||||
self._door.device_id
|
self._door.device_id
|
||||||
)
|
)
|
||||||
activity_end_time_utc = dt.as_utc(activity.activity_end_time)
|
activity_end_time_utc = dt.as_utc(door_activity.activity_end_time)
|
||||||
|
|
||||||
if activity_end_time_utc > last_door_state_update_time_utc:
|
if activity_end_time_utc > last_door_state_update_time_utc:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"The activity log has new events for %s: [action=%s] [activity_end_time_utc=%s] > [last_door_state_update_time_utc=%s]",
|
"The activity log has new events for %s: [action=%s] [activity_end_time_utc=%s] > [last_door_state_update_time_utc=%s]",
|
||||||
self.name,
|
self.name,
|
||||||
activity.action,
|
door_activity.action,
|
||||||
activity_end_time_utc,
|
activity_end_time_utc,
|
||||||
last_door_state_update_time_utc,
|
last_door_state_update_time_utc,
|
||||||
)
|
)
|
||||||
activity_start_time_utc = dt.as_utc(activity.activity_start_time)
|
activity_start_time_utc = dt.as_utc(door_activity.activity_start_time)
|
||||||
if activity.action == "doorclosed":
|
if door_activity.action in ACTIVITY_ACTION_STATES:
|
||||||
self._update_door_state(LockDoorStatus.CLOSED, activity_start_time_utc)
|
self._update_door_state(
|
||||||
elif activity.action == "dooropen":
|
ACTIVITY_ACTION_STATES[door_activity.action],
|
||||||
self._update_door_state(LockDoorStatus.OPEN, activity_start_time_utc)
|
activity_start_time_utc,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Unhandled door activity action %s for %s",
|
"Unhandled door activity action %s for %s",
|
||||||
activity.action,
|
door_activity.action,
|
||||||
self.name,
|
self.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
|
|
||||||
|
|
||||||
class AugustCamera(Camera):
|
class AugustCamera(Camera):
|
||||||
"""An implementation of a Canary security camera."""
|
"""An implementation of a August security camera."""
|
||||||
|
|
||||||
def __init__(self, data, doorbell, timeout):
|
def __init__(self, data, doorbell, timeout):
|
||||||
"""Initialize a Canary security camera."""
|
"""Initialize a August security camera."""
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self._data = data
|
self._data = data
|
||||||
self._doorbell = doorbell
|
self._doorbell = doorbell
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from august.activity import ActivityType
|
from august.activity import ACTIVITY_ACTION_STATES, ActivityType
|
||||||
from august.lock import LockStatus
|
from august.lock import LockStatus
|
||||||
|
|
||||||
from homeassistant.components.lock import LockDevice
|
from homeassistant.components.lock import LockDevice
|
||||||
|
@ -67,15 +67,15 @@ class AugustLock(LockDevice):
|
||||||
|
|
||||||
self._lock_detail = self._data.get_lock_detail(self._lock.device_id)
|
self._lock_detail = self._data.get_lock_detail(self._lock.device_id)
|
||||||
|
|
||||||
activity = self._data.get_latest_device_activity(
|
lock_activity = self._data.get_latest_device_activity(
|
||||||
self._lock.device_id, ActivityType.LOCK_OPERATION
|
self._lock.device_id, ActivityType.LOCK_OPERATION
|
||||||
)
|
)
|
||||||
|
|
||||||
if activity is not None:
|
if lock_activity is not None:
|
||||||
self._changed_by = activity.operated_by
|
self._changed_by = lock_activity.operated_by
|
||||||
self._sync_lock_activity(activity)
|
self._sync_lock_activity(lock_activity)
|
||||||
|
|
||||||
def _sync_lock_activity(self, activity):
|
def _sync_lock_activity(self, lock_activity):
|
||||||
"""Check the activity for the latest lock/unlock activity (events).
|
"""Check the activity for the latest lock/unlock activity (events).
|
||||||
|
|
||||||
We use this to determine the lock state in between calls to the lock
|
We use this to determine the lock state in between calls to the lock
|
||||||
|
@ -84,25 +84,26 @@ class AugustLock(LockDevice):
|
||||||
last_lock_status_update_time_utc = self._data.get_last_lock_status_update_time_utc(
|
last_lock_status_update_time_utc = self._data.get_last_lock_status_update_time_utc(
|
||||||
self._lock.device_id
|
self._lock.device_id
|
||||||
)
|
)
|
||||||
activity_end_time_utc = dt.as_utc(activity.activity_end_time)
|
activity_end_time_utc = dt.as_utc(lock_activity.activity_end_time)
|
||||||
|
|
||||||
if activity_end_time_utc > last_lock_status_update_time_utc:
|
if activity_end_time_utc > last_lock_status_update_time_utc:
|
||||||
_LOGGER.debug(
|
_LOGGER.debug(
|
||||||
"The activity log has new events for %s: [action=%s] [activity_end_time_utc=%s] > [last_lock_status_update_time_utc=%s]",
|
"The activity log has new events for %s: [action=%s] [activity_end_time_utc=%s] > [last_lock_status_update_time_utc=%s]",
|
||||||
self.name,
|
self.name,
|
||||||
activity.action,
|
lock_activity.action,
|
||||||
activity_end_time_utc,
|
activity_end_time_utc,
|
||||||
last_lock_status_update_time_utc,
|
last_lock_status_update_time_utc,
|
||||||
)
|
)
|
||||||
activity_start_time_utc = dt.as_utc(activity.activity_start_time)
|
activity_start_time_utc = dt.as_utc(lock_activity.activity_start_time)
|
||||||
if activity.action == "lock" or activity.action == "onetouchlock":
|
if lock_activity.action in ACTIVITY_ACTION_STATES:
|
||||||
self._update_lock_status(LockStatus.LOCKED, activity_start_time_utc)
|
self._update_lock_status(
|
||||||
elif activity.action == "unlock":
|
ACTIVITY_ACTION_STATES[lock_activity.action],
|
||||||
self._update_lock_status(LockStatus.UNLOCKED, activity_start_time_utc)
|
activity_start_time_utc,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
_LOGGER.info(
|
_LOGGER.info(
|
||||||
"Unhandled lock activity action %s for %s",
|
"Unhandled lock activity action %s for %s",
|
||||||
activity.action,
|
lock_activity.action,
|
||||||
self.name,
|
self.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"domain": "august",
|
"domain": "august",
|
||||||
"name": "August",
|
"name": "August",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/august",
|
"documentation": "https://www.home-assistant.io/integrations/august",
|
||||||
"requirements": ["py-august==0.11.0"],
|
"requirements": ["py-august==0.12.0"],
|
||||||
"dependencies": ["configurator"],
|
"dependencies": ["configurator"],
|
||||||
"codeowners": ["@bdraco"]
|
"codeowners": ["@bdraco"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1074,7 +1074,7 @@ pushover_complete==1.1.1
|
||||||
pwmled==1.4.1
|
pwmled==1.4.1
|
||||||
|
|
||||||
# homeassistant.components.august
|
# homeassistant.components.august
|
||||||
py-august==0.11.0
|
py-august==0.12.0
|
||||||
|
|
||||||
# homeassistant.components.canary
|
# homeassistant.components.canary
|
||||||
py-canary==0.5.0
|
py-canary==0.5.0
|
||||||
|
|
|
@ -390,7 +390,7 @@ pure-python-adb==0.2.2.dev0
|
||||||
pushbullet.py==0.11.0
|
pushbullet.py==0.11.0
|
||||||
|
|
||||||
# homeassistant.components.august
|
# homeassistant.components.august
|
||||||
py-august==0.11.0
|
py-august==0.12.0
|
||||||
|
|
||||||
# homeassistant.components.canary
|
# homeassistant.components.canary
|
||||||
py-canary==0.5.0
|
py-canary==0.5.0
|
||||||
|
|
95
tests/components/august/mocks.py
Normal file
95
tests/components/august/mocks.py
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
"""Mocks for the august component."""
|
||||||
|
import datetime
|
||||||
|
from unittest.mock import MagicMock, PropertyMock
|
||||||
|
|
||||||
|
from august.activity import Activity
|
||||||
|
|
||||||
|
from homeassistant.components.august import AugustData
|
||||||
|
from homeassistant.util import dt
|
||||||
|
|
||||||
|
|
||||||
|
class MockActivity(Activity):
|
||||||
|
"""A mock for py-august Activity class."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, action=None, activity_start_timestamp=None, activity_end_timestamp=None
|
||||||
|
):
|
||||||
|
"""Init the py-august Activity class mock."""
|
||||||
|
self._action = action
|
||||||
|
self._activity_start_timestamp = activity_start_timestamp
|
||||||
|
self._activity_end_timestamp = activity_end_timestamp
|
||||||
|
|
||||||
|
@property
|
||||||
|
def activity_start_time(self):
|
||||||
|
"""Mock the time activity started."""
|
||||||
|
return datetime.datetime.fromtimestamp(self._activity_start_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def activity_end_time(self):
|
||||||
|
"""Mock the time activity ended."""
|
||||||
|
return datetime.datetime.fromtimestamp(self._activity_end_timestamp)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def action(self):
|
||||||
|
"""Mock the action."""
|
||||||
|
return self._action
|
||||||
|
|
||||||
|
|
||||||
|
class MockAugustData(AugustData):
|
||||||
|
"""A wrapper to mock AugustData."""
|
||||||
|
|
||||||
|
# AugustData support multiple locks, however for the purposes of
|
||||||
|
# mocking we currently only mock one lockid
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self, last_lock_status_update_timestamp=1, last_door_state_update_timestamp=1
|
||||||
|
):
|
||||||
|
"""Mock AugustData."""
|
||||||
|
self._last_lock_status_update_time_utc = dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(last_lock_status_update_timestamp)
|
||||||
|
)
|
||||||
|
self._last_door_state_update_time_utc = dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(last_lock_status_update_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_last_lock_status_update_time_utc(self, device_id):
|
||||||
|
"""Mock to get last lock status update time."""
|
||||||
|
return self._last_lock_status_update_time_utc
|
||||||
|
|
||||||
|
def set_last_lock_status_update_time_utc(self, device_id, update_time):
|
||||||
|
"""Mock to set last lock status update time."""
|
||||||
|
self._last_lock_status_update_time_utc = update_time
|
||||||
|
|
||||||
|
def get_last_door_state_update_time_utc(self, device_id):
|
||||||
|
"""Mock to get last door state update time."""
|
||||||
|
return self._last_door_state_update_time_utc
|
||||||
|
|
||||||
|
def set_last_door_state_update_time_utc(self, device_id, update_time):
|
||||||
|
"""Mock to set last door state update time."""
|
||||||
|
self._last_door_state_update_time_utc = update_time
|
||||||
|
|
||||||
|
|
||||||
|
def _mock_august_lock():
|
||||||
|
lock = MagicMock(name="august.lock")
|
||||||
|
type(lock).device_id = PropertyMock(return_value="lock_device_id_1")
|
||||||
|
return lock
|
||||||
|
|
||||||
|
|
||||||
|
def _mock_august_authenticator():
|
||||||
|
authenticator = MagicMock(name="august.authenticator")
|
||||||
|
authenticator.should_refresh = MagicMock(
|
||||||
|
name="august.authenticator.should_refresh", return_value=0
|
||||||
|
)
|
||||||
|
authenticator.refresh_access_token = MagicMock(
|
||||||
|
name="august.authenticator.refresh_access_token"
|
||||||
|
)
|
||||||
|
return authenticator
|
||||||
|
|
||||||
|
|
||||||
|
def _mock_august_authentication(token_text, token_timestamp):
|
||||||
|
authentication = MagicMock(name="august.authentication")
|
||||||
|
type(authentication).access_token = PropertyMock(return_value=token_text)
|
||||||
|
type(authentication).access_token_expires = PropertyMock(
|
||||||
|
return_value=token_timestamp
|
||||||
|
)
|
||||||
|
return authentication
|
113
tests/components/august/test_binary_sensor.py
Normal file
113
tests/components/august/test_binary_sensor.py
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
"""The lock tests for the august platform."""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from august.activity import ACTION_DOOR_CLOSED, ACTION_DOOR_OPEN
|
||||||
|
from august.lock import LockDoorStatus
|
||||||
|
|
||||||
|
from homeassistant.components.august.binary_sensor import AugustDoorBinarySensor
|
||||||
|
from homeassistant.util import dt
|
||||||
|
|
||||||
|
from tests.components.august.mocks import (
|
||||||
|
MockActivity,
|
||||||
|
MockAugustData,
|
||||||
|
_mock_august_lock,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MockAugustDoorBinarySensor(AugustDoorBinarySensor):
|
||||||
|
"""A mock for august component AugustLock class."""
|
||||||
|
|
||||||
|
def __init__(self, august_data=None):
|
||||||
|
"""Init the mock for august component AugustLock class."""
|
||||||
|
self._data = august_data
|
||||||
|
self._door = _mock_august_lock()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
"""Mock name."""
|
||||||
|
return "mockedname1"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""Mock device_id."""
|
||||||
|
return "mockdeviceid1"
|
||||||
|
|
||||||
|
def _update_door_state(self, door_state, activity_start_time_utc):
|
||||||
|
"""Mock updating the lock status."""
|
||||||
|
self._data.set_last_door_state_update_time_utc(
|
||||||
|
self._door.device_id, activity_start_time_utc
|
||||||
|
)
|
||||||
|
self.last_update_door_state = {}
|
||||||
|
self.last_update_door_state["door_state"] = door_state
|
||||||
|
self.last_update_door_state["activity_start_time_utc"] = activity_start_time_utc
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_door_activity_doored_via_dooropen():
|
||||||
|
"""Test _sync_door_activity dooropen."""
|
||||||
|
data = MockAugustData(last_door_state_update_timestamp=1)
|
||||||
|
door = MockAugustDoorBinarySensor(august_data=data)
|
||||||
|
door_activity_start_timestamp = 1234
|
||||||
|
door_activity = MockActivity(
|
||||||
|
action=ACTION_DOOR_OPEN,
|
||||||
|
activity_start_timestamp=door_activity_start_timestamp,
|
||||||
|
activity_end_timestamp=5678,
|
||||||
|
)
|
||||||
|
door._sync_door_activity(door_activity)
|
||||||
|
assert door.last_update_door_state["door_state"] == LockDoorStatus.OPEN
|
||||||
|
assert door.last_update_door_state["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(door_activity_start_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_door_activity_doorclosed():
|
||||||
|
"""Test _sync_door_activity doorclosed."""
|
||||||
|
data = MockAugustData(last_door_state_update_timestamp=1)
|
||||||
|
door = MockAugustDoorBinarySensor(august_data=data)
|
||||||
|
door_activity_timestamp = 1234
|
||||||
|
door_activity = MockActivity(
|
||||||
|
action=ACTION_DOOR_CLOSED,
|
||||||
|
activity_start_timestamp=door_activity_timestamp,
|
||||||
|
activity_end_timestamp=door_activity_timestamp,
|
||||||
|
)
|
||||||
|
door._sync_door_activity(door_activity)
|
||||||
|
assert door.last_update_door_state["door_state"] == LockDoorStatus.CLOSED
|
||||||
|
assert door.last_update_door_state["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(door_activity_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_door_activity_ignores_old_data():
|
||||||
|
"""Test _sync_door_activity dooropen then expired doorclosed."""
|
||||||
|
data = MockAugustData(last_door_state_update_timestamp=1)
|
||||||
|
door = MockAugustDoorBinarySensor(august_data=data)
|
||||||
|
first_door_activity_timestamp = 1234
|
||||||
|
door_activity = MockActivity(
|
||||||
|
action=ACTION_DOOR_OPEN,
|
||||||
|
activity_start_timestamp=first_door_activity_timestamp,
|
||||||
|
activity_end_timestamp=first_door_activity_timestamp,
|
||||||
|
)
|
||||||
|
door._sync_door_activity(door_activity)
|
||||||
|
assert door.last_update_door_state["door_state"] == LockDoorStatus.OPEN
|
||||||
|
assert door.last_update_door_state["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(first_door_activity_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now we do the update with an older start time to
|
||||||
|
# make sure it ignored
|
||||||
|
data.set_last_door_state_update_time_utc(
|
||||||
|
door.device_id, dt.as_utc(datetime.datetime.fromtimestamp(1000))
|
||||||
|
)
|
||||||
|
door_activity_timestamp = 2
|
||||||
|
door_activity = MockActivity(
|
||||||
|
action=ACTION_DOOR_CLOSED,
|
||||||
|
activity_start_timestamp=door_activity_timestamp,
|
||||||
|
activity_end_timestamp=door_activity_timestamp,
|
||||||
|
)
|
||||||
|
door._sync_door_activity(door_activity)
|
||||||
|
assert door.last_update_door_state["door_state"] == LockDoorStatus.OPEN
|
||||||
|
assert door.last_update_door_state["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(first_door_activity_timestamp)
|
||||||
|
)
|
|
@ -1,27 +1,12 @@
|
||||||
"""The tests for the august platform."""
|
"""The tests for the august platform."""
|
||||||
from unittest.mock import MagicMock, PropertyMock
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
from homeassistant.components import august
|
from homeassistant.components import august
|
||||||
|
|
||||||
|
from tests.components.august.mocks import (
|
||||||
def _mock_august_authenticator():
|
_mock_august_authentication,
|
||||||
authenticator = MagicMock(name="august.authenticator")
|
_mock_august_authenticator,
|
||||||
authenticator.should_refresh = MagicMock(
|
)
|
||||||
name="august.authenticator.should_refresh", return_value=0
|
|
||||||
)
|
|
||||||
authenticator.refresh_access_token = MagicMock(
|
|
||||||
name="august.authenticator.refresh_access_token"
|
|
||||||
)
|
|
||||||
return authenticator
|
|
||||||
|
|
||||||
|
|
||||||
def _mock_august_authentication(token_text, token_timestamp):
|
|
||||||
authentication = MagicMock(name="august.authentication")
|
|
||||||
type(authentication).access_token = PropertyMock(return_value=token_text)
|
|
||||||
type(authentication).access_token_expires = PropertyMock(
|
|
||||||
return_value=token_timestamp
|
|
||||||
)
|
|
||||||
return authentication
|
|
||||||
|
|
||||||
|
|
||||||
def test__refresh_access_token():
|
def test__refresh_access_token():
|
||||||
|
|
131
tests/components/august/test_lock.py
Normal file
131
tests/components/august/test_lock.py
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
"""The lock tests for the august platform."""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from august.activity import (
|
||||||
|
ACTION_LOCK_LOCK,
|
||||||
|
ACTION_LOCK_ONETOUCHLOCK,
|
||||||
|
ACTION_LOCK_UNLOCK,
|
||||||
|
)
|
||||||
|
from august.lock import LockStatus
|
||||||
|
|
||||||
|
from homeassistant.components.august.lock import AugustLock
|
||||||
|
from homeassistant.util import dt
|
||||||
|
|
||||||
|
from tests.components.august.mocks import (
|
||||||
|
MockActivity,
|
||||||
|
MockAugustData,
|
||||||
|
_mock_august_lock,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class MockAugustLock(AugustLock):
|
||||||
|
"""A mock for august component AugustLock class."""
|
||||||
|
|
||||||
|
def __init__(self, august_data=None):
|
||||||
|
"""Init the mock for august component AugustLock class."""
|
||||||
|
self._data = august_data
|
||||||
|
self._lock = _mock_august_lock()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_id(self):
|
||||||
|
"""Mock device_id."""
|
||||||
|
return "mockdeviceid1"
|
||||||
|
|
||||||
|
def _update_lock_status(self, lock_status, activity_start_time_utc):
|
||||||
|
"""Mock updating the lock status."""
|
||||||
|
self._data.set_last_lock_status_update_time_utc(
|
||||||
|
self._lock.device_id, activity_start_time_utc
|
||||||
|
)
|
||||||
|
self.last_update_lock_status = {}
|
||||||
|
self.last_update_lock_status["lock_status"] = lock_status
|
||||||
|
self.last_update_lock_status[
|
||||||
|
"activity_start_time_utc"
|
||||||
|
] = activity_start_time_utc
|
||||||
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_lock_activity_locked_via_onetouchlock():
|
||||||
|
"""Test _sync_lock_activity locking."""
|
||||||
|
data = MockAugustData(last_lock_status_update_timestamp=1)
|
||||||
|
lock = MockAugustLock(august_data=data)
|
||||||
|
lock_activity_start_timestamp = 1234
|
||||||
|
lock_activity = MockActivity(
|
||||||
|
action=ACTION_LOCK_ONETOUCHLOCK,
|
||||||
|
activity_start_timestamp=lock_activity_start_timestamp,
|
||||||
|
activity_end_timestamp=5678,
|
||||||
|
)
|
||||||
|
lock._sync_lock_activity(lock_activity)
|
||||||
|
assert lock.last_update_lock_status["lock_status"] == LockStatus.LOCKED
|
||||||
|
assert lock.last_update_lock_status["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(lock_activity_start_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_lock_activity_locked_via_lock():
|
||||||
|
"""Test _sync_lock_activity locking."""
|
||||||
|
data = MockAugustData(last_lock_status_update_timestamp=1)
|
||||||
|
lock = MockAugustLock(august_data=data)
|
||||||
|
lock_activity_start_timestamp = 1234
|
||||||
|
lock_activity = MockActivity(
|
||||||
|
action=ACTION_LOCK_LOCK,
|
||||||
|
activity_start_timestamp=lock_activity_start_timestamp,
|
||||||
|
activity_end_timestamp=5678,
|
||||||
|
)
|
||||||
|
lock._sync_lock_activity(lock_activity)
|
||||||
|
assert lock.last_update_lock_status["lock_status"] == LockStatus.LOCKED
|
||||||
|
assert lock.last_update_lock_status["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(lock_activity_start_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_lock_activity_unlocked():
|
||||||
|
"""Test _sync_lock_activity unlocking."""
|
||||||
|
data = MockAugustData(last_lock_status_update_timestamp=1)
|
||||||
|
lock = MockAugustLock(august_data=data)
|
||||||
|
lock_activity_timestamp = 1234
|
||||||
|
lock_activity = MockActivity(
|
||||||
|
action=ACTION_LOCK_UNLOCK,
|
||||||
|
activity_start_timestamp=lock_activity_timestamp,
|
||||||
|
activity_end_timestamp=lock_activity_timestamp,
|
||||||
|
)
|
||||||
|
lock._sync_lock_activity(lock_activity)
|
||||||
|
assert lock.last_update_lock_status["lock_status"] == LockStatus.UNLOCKED
|
||||||
|
assert lock.last_update_lock_status["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(lock_activity_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test__sync_lock_activity_ignores_old_data():
|
||||||
|
"""Test _sync_lock_activity unlocking."""
|
||||||
|
data = MockAugustData(last_lock_status_update_timestamp=1)
|
||||||
|
lock = MockAugustLock(august_data=data)
|
||||||
|
first_lock_activity_timestamp = 1234
|
||||||
|
lock_activity = MockActivity(
|
||||||
|
action=ACTION_LOCK_UNLOCK,
|
||||||
|
activity_start_timestamp=first_lock_activity_timestamp,
|
||||||
|
activity_end_timestamp=first_lock_activity_timestamp,
|
||||||
|
)
|
||||||
|
lock._sync_lock_activity(lock_activity)
|
||||||
|
assert lock.last_update_lock_status["lock_status"] == LockStatus.UNLOCKED
|
||||||
|
assert lock.last_update_lock_status["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(first_lock_activity_timestamp)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Now we do the update with an older start time to
|
||||||
|
# make sure it ignored
|
||||||
|
data.set_last_lock_status_update_time_utc(
|
||||||
|
lock.device_id, dt.as_utc(datetime.datetime.fromtimestamp(1000))
|
||||||
|
)
|
||||||
|
lock_activity_timestamp = 2
|
||||||
|
lock_activity = MockActivity(
|
||||||
|
action=ACTION_LOCK_LOCK,
|
||||||
|
activity_start_timestamp=lock_activity_timestamp,
|
||||||
|
activity_end_timestamp=lock_activity_timestamp,
|
||||||
|
)
|
||||||
|
lock._sync_lock_activity(lock_activity)
|
||||||
|
assert lock.last_update_lock_status["lock_status"] == LockStatus.UNLOCKED
|
||||||
|
assert lock.last_update_lock_status["activity_start_time_utc"] == dt.as_utc(
|
||||||
|
datetime.datetime.fromtimestamp(first_lock_activity_timestamp)
|
||||||
|
)
|
Loading…
Add table
Add a link
Reference in a new issue