diff --git a/homeassistant/components/august/binary_sensor.py b/homeassistant/components/august/binary_sensor.py index 2ec53b06bdb..b748c0994a1 100644 --- a/homeassistant/components/august/binary_sensor.py +++ b/homeassistant/components/august/binary_sensor.py @@ -58,6 +58,17 @@ def _retrieve_motion_state(data: AugustData, detail: DoorbellDetail) -> bool: return _activity_time_based_state(latest) +def _retrieve_image_capture_state(data: AugustData, detail: DoorbellDetail) -> bool: + latest = data.activity_stream.get_latest_device_activity( + detail.device_id, {ActivityType.DOORBELL_IMAGE_CAPTURE} + ) + + if latest is None: + return False + + return _activity_time_based_state(latest) + + def _retrieve_ding_state(data: AugustData, detail: DoorbellDetail) -> bool: latest = data.activity_stream.get_latest_device_activity( detail.device_id, {ActivityType.DOORBELL_DING} @@ -123,6 +134,13 @@ SENSOR_TYPES_DOORBELL: tuple[AugustBinarySensorEntityDescription, ...] = ( value_fn=_retrieve_motion_state, is_time_based=True, ), + AugustBinarySensorEntityDescription( + key="doorbell_image_capture", + name="Image Capture", + icon="mdi:file-image", + value_fn=_retrieve_image_capture_state, + is_time_based=True, + ), AugustBinarySensorEntityDescription( key="doorbell_online", name="Online", diff --git a/homeassistant/components/august/camera.py b/homeassistant/components/august/camera.py index 6f9ecf1b182..6c1f31c4b9c 100644 --- a/homeassistant/components/august/camera.py +++ b/homeassistant/components/august/camera.py @@ -63,7 +63,8 @@ class AugustCamera(AugustEntityMixin, Camera): def _update_from_data(self): """Get the latest state of the sensor.""" doorbell_activity = self._data.activity_stream.get_latest_device_activity( - self._device_id, {ActivityType.DOORBELL_MOTION} + self._device_id, + {ActivityType.DOORBELL_MOTION, ActivityType.DOORBELL_IMAGE_CAPTURE}, ) if doorbell_activity is not None: diff --git a/homeassistant/components/august/manifest.json b/homeassistant/components/august/manifest.json index fc365102926..f89be2915fb 100644 --- a/homeassistant/components/august/manifest.json +++ b/homeassistant/components/august/manifest.json @@ -2,7 +2,7 @@ "domain": "august", "name": "August", "documentation": "https://www.home-assistant.io/integrations/august", - "requirements": ["yalexs==1.1.13"], + "requirements": ["yalexs==1.1.15"], "codeowners": ["@bdraco"], "dhcp": [ { diff --git a/requirements_all.txt b/requirements_all.txt index fbd49ab7d0e..f9d97f36b5b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2480,7 +2480,7 @@ xs1-api-client==3.0.0 yalesmartalarmclient==0.3.4 # homeassistant.components.august -yalexs==1.1.13 +yalexs==1.1.15 # homeassistant.components.yeelight yeelight==0.7.8 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index fa55a57bf77..2008007ac04 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1479,7 +1479,7 @@ xmltodict==0.12.0 yalesmartalarmclient==0.3.4 # homeassistant.components.august -yalexs==1.1.13 +yalexs==1.1.15 # homeassistant.components.yeelight yeelight==0.7.8 diff --git a/tests/components/august/test_binary_sensor.py b/tests/components/august/test_binary_sensor.py index 26c824e5842..e2ff4a6771a 100644 --- a/tests/components/august/test_binary_sensor.py +++ b/tests/components/august/test_binary_sensor.py @@ -1,5 +1,6 @@ """The binary_sensor tests for the august platform.""" import datetime +import time from unittest.mock import Mock, patch from yalexs.pubnub_async import AugustPubNub @@ -26,6 +27,10 @@ from tests.components.august.mocks import ( ) +def _timetoken(): + return str(time.time_ns())[:-2] + + async def test_doorsense(hass): """Test creation of a lock with doorsense and bridge.""" lock_one = await _mock_lock_from_fixture( @@ -85,6 +90,10 @@ async def test_create_doorbell(hass): "binary_sensor.k98gidt45gul_name_motion" ) assert binary_sensor_k98gidt45gul_name_motion.state == STATE_OFF + binary_sensor_k98gidt45gul_name_image_capture = hass.states.get( + "binary_sensor.k98gidt45gul_name_image_capture" + ) + assert binary_sensor_k98gidt45gul_name_image_capture.state == STATE_OFF binary_sensor_k98gidt45gul_name_online = hass.states.get( "binary_sensor.k98gidt45gul_name_online" ) @@ -97,6 +106,10 @@ async def test_create_doorbell(hass): "binary_sensor.k98gidt45gul_name_motion" ) assert binary_sensor_k98gidt45gul_name_motion.state == STATE_OFF + binary_sensor_k98gidt45gul_name_image_capture = hass.states.get( + "binary_sensor.k98gidt45gul_name_image_capture" + ) + assert binary_sensor_k98gidt45gul_name_image_capture.state == STATE_OFF async def test_create_doorbell_offline(hass): @@ -171,7 +184,7 @@ async def test_doorbell_update_via_pubnub(hass): pubnub, Mock( channel=doorbell_one.pubsub_channel, - timetoken=dt_util.utcnow().timestamp() * 10000000, + timetoken=_timetoken(), message={ "status": "imagecapture", "data": { @@ -186,10 +199,46 @@ async def test_doorbell_update_via_pubnub(hass): await hass.async_block_till_done() + binary_sensor_k98gidt45gul_name_image_capture = hass.states.get( + "binary_sensor.k98gidt45gul_name_image_capture" + ) + assert binary_sensor_k98gidt45gul_name_image_capture.state == STATE_ON + + pubnub.message( + pubnub, + Mock( + channel=doorbell_one.pubsub_channel, + timetoken=_timetoken(), + message={ + "status": "doorbell_motion_detected", + "data": { + "event": "doorbell_motion_detected", + "image": { + "height": 640, + "width": 480, + "format": "jpg", + "created_at": "2021-03-16T02:36:26.886Z", + "bytes": 14061, + "secure_url": "https://dyu7azbnaoi74.cloudfront.net/images/1f8.jpeg", + "url": "https://dyu7azbnaoi74.cloudfront.net/images/1f8.jpeg", + "etag": "09e839331c4ea59eef28081f2caa0e90", + }, + "doorbellName": "Front Door", + "callID": None, + "origin": "mars-api", + "mutableContent": True, + }, + }, + ), + ) + + await hass.async_block_till_done() + binary_sensor_k98gidt45gul_name_motion = hass.states.get( "binary_sensor.k98gidt45gul_name_motion" ) assert binary_sensor_k98gidt45gul_name_motion.state == STATE_ON + binary_sensor_k98gidt45gul_name_ding = hass.states.get( "binary_sensor.k98gidt45gul_name_ding" ) @@ -204,16 +253,16 @@ async def test_doorbell_update_via_pubnub(hass): async_fire_time_changed(hass, new_time) await hass.async_block_till_done() - binary_sensor_k98gidt45gul_name_motion = hass.states.get( - "binary_sensor.k98gidt45gul_name_motion" + binary_sensor_k98gidt45gul_name_image_capture = hass.states.get( + "binary_sensor.k98gidt45gul_name_image_capture" ) - assert binary_sensor_k98gidt45gul_name_motion.state == STATE_OFF + assert binary_sensor_k98gidt45gul_name_image_capture.state == STATE_OFF pubnub.message( pubnub, Mock( channel=doorbell_one.pubsub_channel, - timetoken=dt_util.utcnow().timestamp() * 10000000, + timetoken=_timetoken(), message={ "status": "buttonpush", }, @@ -274,7 +323,7 @@ async def test_door_sense_update_via_pubnub(hass): pubnub, Mock( channel=lock_one.pubsub_channel, - timetoken=dt_util.utcnow().timestamp() * 10000000, + timetoken=_timetoken(), message={"status": "kAugLockState_Unlocking", "doorState": "closed"}, ), ) @@ -289,11 +338,10 @@ async def test_door_sense_update_via_pubnub(hass): pubnub, Mock( channel=lock_one.pubsub_channel, - timetoken=dt_util.utcnow().timestamp() * 10000000, + timetoken=_timetoken(), message={"status": "kAugLockState_Locking", "doorState": "open"}, ), ) - await hass.async_block_till_done() binary_sensor_online_with_doorsense_name = hass.states.get( "binary_sensor.online_with_doorsense_name_open" @@ -327,7 +375,7 @@ async def test_door_sense_update_via_pubnub(hass): pubnub, Mock( channel=lock_one.pubsub_channel, - timetoken=dt_util.utcnow().timestamp() * 10000000, + timetoken=_timetoken(), message={"status": "kAugLockState_Unlocking", "doorState": "open"}, ), )