diff --git a/homeassistant/components/august.py b/homeassistant/components/august.py index 5f268a95f5d..850d972c373 100644 --- a/homeassistant/components/august.py +++ b/homeassistant/components/august.py @@ -4,7 +4,6 @@ Support for August devices. For more details about this component, please refer to the documentation at https://home-assistant.io/components/august/ """ - import logging from datetime import timedelta @@ -124,6 +123,7 @@ def setup_august(hass, config, api, authenticator): return True if state == AuthenticationState.BAD_PASSWORD: + _LOGGER.error("Invalid password provided") return False if state == AuthenticationState.REQUIRES_VALIDATION: request_configuration(hass, config, api, authenticator) @@ -165,6 +165,7 @@ class AugustData: self._doorbell_detail_by_id = {} self._lock_status_by_id = {} self._lock_detail_by_id = {} + self._door_state_by_id = {} self._activities_by_id = {} @property @@ -184,6 +185,7 @@ class AugustData: def get_device_activities(self, device_id, *activity_types): """Return a list of activities.""" + _LOGGER.debug("Getting device activities") self._update_device_activities() activities = self._activities_by_id.get(device_id, []) @@ -199,6 +201,7 @@ class AugustData: @Throttle(MIN_TIME_BETWEEN_UPDATES) def _update_device_activities(self, limit=ACTIVITY_FETCH_LIMIT): """Update data object with latest from August API.""" + _LOGGER.debug("Updating device activities") for house_id in self.house_ids: activities = self._api.get_house_activities(self._access_token, house_id, @@ -218,14 +221,21 @@ class AugustData: def _update_doorbells(self): detail_by_id = {} + _LOGGER.debug("Start retrieving doorbell details") for doorbell in self._doorbells: + _LOGGER.debug("Updating status for %s", + doorbell.device_name) detail_by_id[doorbell.device_id] = self._api.get_doorbell_detail( self._access_token, doorbell.device_id) + _LOGGER.debug("Completed retrieving doorbell details") self._doorbell_detail_by_id = detail_by_id def get_lock_status(self, lock_id): - """Return lock status.""" + """Return status if the door is locked or unlocked. + + This is status for the lock itself. + """ self._update_locks() return self._lock_status_by_id.get(lock_id) @@ -234,17 +244,43 @@ class AugustData: self._update_locks() return self._lock_detail_by_id.get(lock_id) + def get_door_state(self, lock_id): + """Return status if the door is open or closed. + + This is the status from the door sensor. + """ + self._update_doors() + return self._door_state_by_id.get(lock_id) + + @Throttle(MIN_TIME_BETWEEN_UPDATES) + def _update_doors(self): + state_by_id = {} + + _LOGGER.debug("Start retrieving door status") + for lock in self._locks: + _LOGGER.debug("Updating status for %s", + lock.device_name) + state_by_id[lock.device_id] = self._api.get_lock_door_status( + self._access_token, lock.device_id) + + _LOGGER.debug("Completed retrieving door status") + self._door_state_by_id = state_by_id + @Throttle(MIN_TIME_BETWEEN_UPDATES) def _update_locks(self): status_by_id = {} detail_by_id = {} + _LOGGER.debug("Start retrieving locks status") for lock in self._locks: + _LOGGER.debug("Updating status for %s", + lock.device_name) status_by_id[lock.device_id] = self._api.get_lock_status( self._access_token, lock.device_id) detail_by_id[lock.device_id] = self._api.get_lock_detail( self._access_token, lock.device_id) + _LOGGER.debug("Completed retrieving locks status") self._lock_status_by_id = status_by_id self._lock_detail_by_id = detail_by_id diff --git a/homeassistant/components/binary_sensor/august.py b/homeassistant/components/binary_sensor/august.py index 7f5da390906..55b31a6da5f 100644 --- a/homeassistant/components/binary_sensor/august.py +++ b/homeassistant/components/binary_sensor/august.py @@ -4,16 +4,26 @@ Support for August binary sensors. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.august/ """ +import logging from datetime import timedelta, datetime from homeassistant.components.august import DATA_AUGUST from homeassistant.components.binary_sensor import (BinarySensorDevice) +_LOGGER = logging.getLogger(__name__) + DEPENDENCIES = ['august'] SCAN_INTERVAL = timedelta(seconds=5) +def _retrieve_door_state(data, lock): + """Get the latest state of the DoorSense sensor.""" + from august.lock import LockDoorStatus + doorstate = data.get_door_state(lock.device_id) + return doorstate == LockDoorStatus.OPEN + + def _retrieve_online_state(data, doorbell): """Get the latest state of the sensor.""" detail = data.get_doorbell_detail(doorbell.device_id) @@ -46,7 +56,11 @@ def _activity_time_based_state(data, doorbell, activity_types): # Sensor types: Name, device_class, state_provider -SENSOR_TYPES = { +SENSOR_TYPES_DOOR = { + 'door_open': ['Open', 'door', _retrieve_door_state], +} + +SENSOR_TYPES_DOORBELL = { 'doorbell_ding': ['Ding', 'occupancy', _retrieve_ding_state], 'doorbell_motion': ['Motion', 'motion', _retrieve_motion_state], 'doorbell_online': ['Online', 'connectivity', _retrieve_online_state], @@ -58,14 +72,78 @@ def setup_platform(hass, config, add_entities, discovery_info=None): data = hass.data[DATA_AUGUST] devices = [] + from august.lock import LockDoorStatus + for door in data.locks: + for sensor_type in SENSOR_TYPES_DOOR: + state_provider = SENSOR_TYPES_DOOR[sensor_type][2] + if state_provider(data, door) is LockDoorStatus.UNKNOWN: + _LOGGER.debug( + "Not adding sensor class %s for lock %s ", + SENSOR_TYPES_DOOR[sensor_type][1], door.device_name + ) + continue + + _LOGGER.debug( + "Adding sensor class %s for %s", + SENSOR_TYPES_DOOR[sensor_type][1], door.device_name + ) + devices.append(AugustDoorBinarySensor(data, sensor_type, door)) + for doorbell in data.doorbells: - for sensor_type in SENSOR_TYPES: - devices.append(AugustBinarySensor(data, sensor_type, doorbell)) + for sensor_type in SENSOR_TYPES_DOORBELL: + _LOGGER.debug("Adding doorbell sensor class %s for %s", + SENSOR_TYPES_DOORBELL[sensor_type][1], + doorbell.device_name) + devices.append( + AugustDoorbellBinarySensor(data, sensor_type, + doorbell) + ) add_entities(devices, True) -class AugustBinarySensor(BinarySensorDevice): +class AugustDoorBinarySensor(BinarySensorDevice): + """Representation of an August Door binary sensor.""" + + def __init__(self, data, sensor_type, door): + """Initialize the sensor.""" + self._data = data + self._sensor_type = sensor_type + self._door = door + self._state = None + self._available = False + + @property + def available(self): + """Return the availability of this sensor.""" + return self._available + + @property + def is_on(self): + """Return true if the binary sensor is on.""" + return self._state + + @property + def device_class(self): + """Return the class of this device, from component DEVICE_CLASSES.""" + return SENSOR_TYPES_DOOR[self._sensor_type][1] + + @property + def name(self): + """Return the name of the binary sensor.""" + return "{} {}".format(self._door.device_name, + SENSOR_TYPES_DOOR[self._sensor_type][0]) + + def update(self): + """Get the latest state of the sensor.""" + state_provider = SENSOR_TYPES_DOOR[self._sensor_type][2] + self._state = state_provider(self._data, self._door) + + from august.lock import LockDoorStatus + self._available = self._state != LockDoorStatus.UNKNOWN + + +class AugustDoorbellBinarySensor(BinarySensorDevice): """Representation of an August binary sensor.""" def __init__(self, data, sensor_type, doorbell): @@ -83,15 +161,15 @@ class AugustBinarySensor(BinarySensorDevice): @property def device_class(self): """Return the class of this device, from component DEVICE_CLASSES.""" - return SENSOR_TYPES[self._sensor_type][1] + return SENSOR_TYPES_DOORBELL[self._sensor_type][1] @property def name(self): """Return the name of the binary sensor.""" return "{} {}".format(self._doorbell.device_name, - SENSOR_TYPES[self._sensor_type][0]) + SENSOR_TYPES_DOORBELL[self._sensor_type][0]) def update(self): """Get the latest state of the sensor.""" - state_provider = SENSOR_TYPES[self._sensor_type][2] + state_provider = SENSOR_TYPES_DOORBELL[self._sensor_type][2] self._state = state_provider(self._data, self._doorbell) diff --git a/homeassistant/components/lock/august.py b/homeassistant/components/lock/august.py index 7aec3c78690..e8949255ee9 100644 --- a/homeassistant/components/lock/august.py +++ b/homeassistant/components/lock/august.py @@ -4,12 +4,15 @@ Support for August lock. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/lock.august/ """ +import logging from datetime import timedelta from homeassistant.components.august import DATA_AUGUST from homeassistant.components.lock import LockDevice from homeassistant.const import ATTR_BATTERY_LEVEL +_LOGGER = logging.getLogger(__name__) + DEPENDENCIES = ['august'] SCAN_INTERVAL = timedelta(seconds=5) @@ -21,6 +24,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): devices = [] for lock in data.locks: + _LOGGER.debug("Adding lock for %s", lock.device_name) devices.append(AugustLock(data, lock)) add_entities(devices, True) @@ -77,6 +81,9 @@ class AugustLock(LockDevice): @property def device_state_attributes(self): """Return the device specific state attributes.""" + if self._lock_detail is None: + return None + return { ATTR_BATTERY_LEVEL: self._lock_detail.battery_level, }