Skip to content

Commit

Permalink
Provide a util to update LockDetail from activity
Browse files Browse the repository at this point in the history
Home Assistant checks the activity log far more frequently than other
apis in order to reduce the number of api calls.

The new update_lock_from_activity util provides a way to update a
LockDetail class with one of the following activities:

  LockOperationActivity
  DoorOperationActivity
  • Loading branch information
bdraco committed Feb 18, 2020
1 parent 6beafb0 commit 24b08ee
Show file tree
Hide file tree
Showing 10 changed files with 350 additions and 1 deletion.
1 change: 1 addition & 0 deletions MANIFEST
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ august/exceptions.py
august/keypad.py
august/lock.py
august/pin.py
august/util.py
35 changes: 35 additions & 0 deletions august/util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import datetime

from august.activity import (
ACTIVITY_ACTION_STATES,
DoorOperationActivity,
LockOperationActivity,
)


def update_lock_detail_from_activity(lock_detail, activity):
"""Update the LockDetail from an activity."""
activity_end_time_utc = as_utc_from_local(activity.activity_end_time)
if activity.house_id != lock_detail.house_id:
raise ValueError
if activity.device_id != lock_detail.device_id:
raise ValueError
if isinstance(activity, LockOperationActivity):
if lock_detail.lock_status_datetime >= activity_end_time_utc:
return False
lock_detail.lock_status = ACTIVITY_ACTION_STATES[activity.action]
lock_detail.lock_status_datetime = activity_end_time_utc
elif isinstance(activity, DoorOperationActivity):
if lock_detail.door_state_datetime >= activity_end_time_utc:
return False
lock_detail.door_state = ACTIVITY_ACTION_STATES[activity.action]
lock_detail.door_state_datetime = activity_end_time_utc
else:
raise ValueError

return True


def as_utc_from_local(dtime):
"""Converts the datetime returned from an activity to UTC."""
return dtime.astimezone(tz=datetime.timezone.utc)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='py-august',
version='0.15.0',
version='0.16.0',
packages=['august'],
url='https://github.com/snjoetw/py-august',
license='MIT',
Expand Down
35 changes: 35 additions & 0 deletions tests/fixtures/door_closed_activity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"action" : "doorclosed",
"callingUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
},
"dateTime" : 1582007217000,
"deviceID" : "ABC",
"deviceName" : "MockHouse Tech Room Door",
"deviceType" : "lock",
"entities" : {
"activity" : "activityId",
"callingUser" : "deleted",
"device" : "ABC",
"house" : "123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time"
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}
35 changes: 35 additions & 0 deletions tests/fixtures/door_closed_activity_wrong_deviceid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"action" : "doorclosed",
"callingUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
},
"dateTime" : 1582007217000,
"deviceID" : "notABC",
"deviceName" : "MockHouse Tech Room Door",
"deviceType" : "lock",
"entities" : {
"activity" : "activityId",
"callingUser" : "deleted",
"device" : "ABC",
"house" : "123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time"
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}
35 changes: 35 additions & 0 deletions tests/fixtures/door_closed_activity_wrong_houseid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"action" : "doorclosed",
"callingUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
},
"dateTime" : 1582007217000,
"deviceID" : "ABC",
"deviceName" : "MockHouse Tech Room Door",
"deviceType" : "lock",
"entities" : {
"activity" : "activityId",
"callingUser" : "deleted",
"device" : "ABC",
"house" : "not123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "not123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time"
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}
35 changes: 35 additions & 0 deletions tests/fixtures/door_open_activity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"action" : "dooropen",
"callingUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
},
"dateTime" : 1582007219000,
"deviceID" : "ABC",
"deviceName" : "MockHouse Tech Room Door",
"deviceType" : "lock",
"entities" : {
"activity" : "ActivityId",
"callingUser" : "deleted",
"device" : "ABC",
"house" : "123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time"
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}
35 changes: 35 additions & 0 deletions tests/fixtures/lock_activity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"action" : "lock",
"callingUser" : {
"FirstName" : "MockHouse",
"LastName" : "House",
"UserID" : "mockUserId2"
},
"dateTime" : 1582007218000,
"deviceID" : "ABC",
"deviceName" : "MockHouseTDoor",
"deviceType" : "lock",
"entities" : {
"activity" : "mockActivity2",
"callingUser" : "mockUserId2",
"device" : "ABC",
"house" : "123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time",
"remote" : true
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}

34 changes: 34 additions & 0 deletions tests/fixtures/unlock_activity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"action" : "unlock",
"callingUser" : {
"FirstName" : "MockHouse",
"LastName" : "House",
"UserID" : "mockUserId2"
},
"dateTime" : 1582007217000,
"deviceID" : "ABC",
"deviceName" : "MockHouseXDoor",
"deviceType" : "lock",
"entities" : {
"activity" : "ActivityId",
"callingUser" : "mockUserId2",
"device" : "ABC",
"house" : "123",
"otherUser" : "deleted"
},
"house" : {
"houseID" : "123",
"houseName" : "MockHouse"
},
"info" : {
"DateLogActionID" : "ABC+Time",
"remote" : true
},
"otherUser" : {
"FirstName" : "Unknown",
"LastName" : "User",
"PhoneNo" : "deleted",
"UserID" : "deleted",
"UserName" : "deleteduser"
}
}
104 changes: 104 additions & 0 deletions tests/test_lock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import json
import os
import unittest

import dateutil.parser
import datetime

from august.activity import DoorOperationActivity, LockOperationActivity
from august.lock import LockDetail, LockDoorStatus, LockStatus
from august.util import update_lock_detail_from_activity, as_utc_from_local


def load_fixture(filename):
"""Load a fixture."""
path = os.path.join(os.path.dirname(__file__), "fixtures", filename)
with open(path) as fptr:
return fptr.read()


class TestLockDetail(unittest.TestCase):
def test_update_lock_with_activity(self):
lock = LockDetail(
json.loads(load_fixture("get_lock.online_with_doorsense.json"))
)
self.assertEqual("ABC", lock.device_id)
self.assertEqual(LockStatus.LOCKED, lock.lock_status)
self.assertEqual(LockDoorStatus.OPEN, lock.door_state)
self.assertEqual(
dateutil.parser.parse("2017-12-10T04:48:30.272Z"), lock.lock_status_datetime
)
self.assertEqual(
dateutil.parser.parse("2017-12-10T04:48:30.272Z"), lock.door_state_datetime
)

lock_operation_activity = LockOperationActivity(
json.loads(load_fixture("lock_activity.json"))
)
unlock_operation_activity = LockOperationActivity(
json.loads(load_fixture("unlock_activity.json"))
)
open_operation_activity = DoorOperationActivity(
json.loads(load_fixture("door_open_activity.json"))
)
closed_operation_activity = DoorOperationActivity(
json.loads(load_fixture("door_closed_activity.json"))
)
closed_operation_wrong_deviceid_activity = DoorOperationActivity(
json.loads(load_fixture("door_closed_activity_wrong_deviceid.json"))
)
closed_operation_wrong_houseid_activity = DoorOperationActivity(
json.loads(load_fixture("door_closed_activity_wrong_houseid.json"))
)

self.assertTrue(
update_lock_detail_from_activity(lock, unlock_operation_activity)
)
self.assertEqual(LockStatus.UNLOCKED, lock.lock_status)
self.assertEqual(
as_utc_from_local(datetime.datetime.fromtimestamp(1582007217000 / 1000)),
lock.lock_status_datetime,
)

self.assertTrue(update_lock_detail_from_activity(lock, lock_operation_activity))
self.assertEqual(LockStatus.LOCKED, lock.lock_status)
self.assertEqual(
as_utc_from_local(datetime.datetime.fromtimestamp(1582007218000 / 1000)),
lock.lock_status_datetime,
)

# returns false we send an older activity
self.assertFalse(
update_lock_detail_from_activity(lock, unlock_operation_activity)
)

self.assertTrue(
update_lock_detail_from_activity(lock, closed_operation_activity)
)
self.assertEqual(LockDoorStatus.CLOSED, lock.door_state)
self.assertEqual(
as_utc_from_local(datetime.datetime.fromtimestamp(1582007217000 / 1000)),
lock.door_state_datetime,
)

self.assertTrue(update_lock_detail_from_activity(lock, open_operation_activity))
self.assertEqual(LockDoorStatus.OPEN, lock.door_state)
self.assertEqual(
as_utc_from_local(datetime.datetime.fromtimestamp(1582007219000 / 1000)),
lock.door_state_datetime,
)

# returns false we send an older activity
self.assertFalse(
update_lock_detail_from_activity(lock, closed_operation_activity)
)

with self.assertRaises(ValueError):
update_lock_detail_from_activity(
lock, closed_operation_wrong_deviceid_activity
)

with self.assertRaises(ValueError):
update_lock_detail_from_activity(
lock, closed_operation_wrong_houseid_activity
)

0 comments on commit 24b08ee

Please sign in to comment.