Skip to content

Commit

Permalink
Updates
Browse files Browse the repository at this point in the history
  • Loading branch information
aneisch committed Feb 24, 2023
1 parent fa57f75 commit f78e9c7
Show file tree
Hide file tree
Showing 24 changed files with 319 additions and 240 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[![Build Status](https://github.com/aneisch/home-assistant-config/actions/workflows/check-ha-release-compatibility.yml/badge.svg)](https://github.com/aneisch/home-assistant-config/actions)
[![GitHub last commit](https://img.shields.io/github/last-commit/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/commits/master)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/y/aneisch/home-assistant-config)](https://github.com/aneisch/home-assistant-config/graphs/commit-activity)
[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant-2023.2.3%20(Latest)-brightgreen)](https://github.com/home-assistant/home-assistant/releases/latest)
[![HA Version](https://img.shields.io/badge/Running%20Home%20Assistant-2023.2.5%20(Latest)-brightgreen)](https://github.com/home-assistant/home-assistant/releases/latest)
<br><a href="https://www.buymeacoffee.com/aneisch" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-black.png" width="150px" height="35px" alt="Buy Me A Coffee" style="height: 35px !important;width: 150px !important;" ></a>


Expand Down Expand Up @@ -58,7 +58,7 @@ Also using Grafana/Influx for graphing, both running in Docker containers on NUC
Description | value
-- | --
Lines of ESPHome YAML | 2342
Lines of Home Assistant YAML | 6867
Lines of Home Assistant YAML | 6872
[Integrations](https://www.home-assistant.io/integrations/) in use | 44
Zigbee devices in [`zha`](https://www.home-assistant.io/integrations/zha/) | 26
Z-Wave devices in [`zwave_js`](https://www.home-assistant.io/integrations/zwave_js/) | 37
Expand All @@ -74,7 +74,7 @@ Entities in the [`camera`](https://www.home-assistant.io/components/camera) doma
Entities in the [`climate`](https://www.home-assistant.io/components/climate) domain | 1
Entities in the [`counter`](https://www.home-assistant.io/components/counter) domain | 1
Entities in the [`cover`](https://www.home-assistant.io/components/cover) domain | 5
Entities in the [`device_tracker`](https://www.home-assistant.io/components/device_tracker) domain | 20
Entities in the [`device_tracker`](https://www.home-assistant.io/components/device_tracker) domain | 21
Entities in the [`fan`](https://www.home-assistant.io/components/fan) domain | 3
Entities in the [`group`](https://www.home-assistant.io/components/group) domain | 13
Entities in the [`input_boolean`](https://www.home-assistant.io/components/input_boolean) domain | 23
Expand All @@ -92,7 +92,7 @@ Entities in the [`remote`](https://www.home-assistant.io/components/remote) doma
Entities in the [`scene`](https://www.home-assistant.io/components/scene) domain | 2
Entities in the [`script`](https://www.home-assistant.io/components/script) domain | 46
Entities in the [`select`](https://www.home-assistant.io/components/select) domain | 22
Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 354
Entities in the [`sensor`](https://www.home-assistant.io/components/sensor) domain | 355
Entities in the [`setter`](https://www.home-assistant.io/components/setter) domain | 1
Entities in the [`siren`](https://www.home-assistant.io/components/siren) domain | 1
Entities in the [`sun`](https://www.home-assistant.io/components/sun) domain | 1
Expand All @@ -102,7 +102,7 @@ Entities in the [`update`](https://www.home-assistant.io/components/update) doma
Entities in the [`vacuum`](https://www.home-assistant.io/components/vacuum) domain | 1
Entities in the [`weather`](https://www.home-assistant.io/components/weather) domain | 2
Entities in the [`zone`](https://www.home-assistant.io/components/zone) domain | 6
**Total state objects** | **1137**
**Total state objects** | **1139**
## The HACS integrations/plugins that I use:
**Appdaemon**:<br>
[aneisch/follow_me_appdaemon](https://github.com/aneisch/follow_me_appdaemon)<br>
Expand Down
3 changes: 0 additions & 3 deletions automations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,6 @@
- condition: time
weekday:
- sun
- mon
- wed
- fri
- "{{ states('person.andrew') == 'home'}}"
action:
# Watchtower runs once at container start then turns back off
Expand Down
12 changes: 11 additions & 1 deletion custom_components/aarlo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@

from .pyaarlo.constant import DEFAULT_AUTH_HOST, DEFAULT_HOST, SIREN_STATE_KEY

__version__ = "0.7.4b4"
__version__ = "0.7.4b8"

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -70,6 +70,8 @@
CONF_TFA_HOST = "tfa_host"
CONF_TFA_USERNAME = "tfa_username"
CONF_TFA_PASSWORD = "tfa_password"
CONF_TFA_TIMEOUT = "tfa_timeout"
CONF_TFA_TOTAL_TIMEOUT = "tfa_total_timeout"
CONF_LIBRARY_DAYS = "library_days"
CONF_AUTH_HOST = "auth_host"
CONF_SERIAL_IDS = "serial_ids"
Expand Down Expand Up @@ -113,6 +115,8 @@
DEFAULT_TFA_HOST = "unknown.imap.com"
DEFAULT_TFA_USERNAME = "[email protected]"
DEFAULT_TFA_PASSWORD = "unknown"
DEFAULT_TFA_TIMEOUT = timedelta(seconds=3)
DEFAULT_TFA_TOTAL_TIMEOUT = timedelta(seconds=60)
DEFAULT_LIBRARY_DAYS = 30
SERIAL_IDS = False
STREAM_SNAPSHOT = False
Expand Down Expand Up @@ -187,6 +191,8 @@
vol.Optional(
CONF_TFA_PASSWORD, default=DEFAULT_TFA_PASSWORD
): cv.string,
vol.Optional(CONF_TFA_TIMEOUT, default=DEFAULT_TFA_TIMEOUT): cv.time_period,
vol.Optional(CONF_TFA_TOTAL_TIMEOUT, default=DEFAULT_TFA_TOTAL_TIMEOUT): cv.time_period,
vol.Optional(
CONF_LIBRARY_DAYS, default=DEFAULT_LIBRARY_DAYS
): cv.positive_int,
Expand Down Expand Up @@ -375,6 +381,8 @@ def login(hass, conf):
tfa_host = conf.get(CONF_TFA_HOST)
tfa_username = conf.get(CONF_TFA_USERNAME)
tfa_password = conf.get(CONF_TFA_PASSWORD)
tfa_timeout = int(conf.get(CONF_TFA_TIMEOUT).total_seconds())
tfa_total_timeout = int(conf.get(CONF_TFA_TOTAL_TIMEOUT).total_seconds())
library_days = conf.get(CONF_LIBRARY_DAYS)
serial_ids = conf.get(CONF_SERIAL_IDS)
stream_snapshot = conf.get(CONF_STREAM_SNAPSHOT)
Expand Down Expand Up @@ -433,6 +441,8 @@ def login(hass, conf):
tfa_host=tfa_host,
tfa_username=tfa_username,
tfa_password=tfa_password,
tfa_timeout=tfa_timeout,
tfa_total_timeout=tfa_total_timeout,
library_days=library_days,
serial_ids=serial_ids,
stream_snapshot=stream_snapshot,
Expand Down
4 changes: 2 additions & 2 deletions custom_components/aarlo/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ async def async_setup_platform(hass, config, async_add_entities, _discovery_info

async_add_entities(base_stations)

_LOGGER.error("Adding Locations")
_LOGGER.debug("Adding Locations")
locations = []
for location in arlo.locations:
_LOGGER.error("Locations Iterator")
_LOGGER.debug("Locations Iterator")
locations.append(ArloLocation(location, config))

async_add_entities(locations)
Expand Down
2 changes: 1 addition & 1 deletion custom_components/aarlo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"dependencies": ["ffmpeg"],
"codeowners": ["@twrecked"],
"requirements": ["unidecode","cloudscraper>=1.2.64", "paho-mqtt"],
"version": "0.7.4b4",
"version": "0.7.4b8",
"iot_class": "cloud_push"
}
77 changes: 30 additions & 47 deletions custom_components/aarlo/pyaarlo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

_LOGGER = logging.getLogger("pyaarlo")

__version__ = "0.7.4b4"
__version__ = "0.7.4b8"


class PyArlo(object):
Expand Down Expand Up @@ -305,32 +305,30 @@ def _v3_modes(self):
return self.cfg.mode_api.lower() == "v3"

def _refresh_devices(self):
"""Read in the devices list.
This returns all devices known to the Arlo system. The newer devices
include state information - battery levels etc - while the old devices
don't. We update what we can.
"""
url = DEVICES_PATH + "?t={}".format(time_to_arlotime())
self._devices = self._be.get(url)
if not self._devices:
self.warning("No devices returned from " + url)
self._devices = []
self.vdebug("devices={}".format(pprint.pformat(self._devices)))
self.vdebug(f"devices={pprint.pformat(self._devices)}")

# Newer devices include information in this response. Be sure to update it.
for device in self._devices:
device_id = device.get("deviceId", None)
props = device.get("properties", None)
if device_id is None or props is None:
continue
self.debug(f"updating {device_id} from device refresh")
base = self.lookup_base_station_by_id(device_id)
if base is not None:
base.update_resources(props)
camera = self.lookup_camera_by_id(device_id)
if camera is not None:
camera.update_resources(props)
doorbell = self.lookup_doorbell_by_id(device_id)
if doorbell is not None:
doorbell.update_resources(props)
light = self.lookup_light_by_id(device_id)
if light is not None:
light.update_resources(props)
self.vdebug(f"device-id={device_id}")
if device_id is not None and props is not None:
device = self.lookup_device_by_id(device_id)
if device is not None:
self.vdebug(f"updating {device_id} from device refresh")
device.update_resources(props)
else:
self.vdebug(f"not updating {device_id} from device refresh")

def _refresh_locations(self):
"""Retrieve location list from the backend
Expand Down Expand Up @@ -384,36 +382,7 @@ def _ping_bases(self):
def _refresh_bases(self, initial):
for base in self._bases:
base.update_modes(initial)
if base.has_capability(RESOURCE_CAPABILITY):
self._be.notify(
base=base,
body={
"action": "get",
"resource": "cameras",
"publishResponse": False,
},
wait_for="response",
)
self._be.notify(
base=base,
body={
"action": "get",
"resource": "doorbells",
"publishResponse": False,
},
wait_for="response",
)
self._be.notify(
base=base,
body={
"action": "get",
"resource": "lights",
"publishResponse": False,
},
wait_for="response",
)
else:
self.vdebug(f"NO resource for {base.device_id}")
base.update_states()

def _refresh_modes(self):
self.vdebug("refresh modes")
Expand Down Expand Up @@ -584,6 +553,10 @@ def locations(self):
"""
return self._locations

@property
def all_devices(self):
return self.cameras + self.doorbells + self.lights + self.base_stations + self.locations

@property
def sensors(self):
return self._sensors
Expand Down Expand Up @@ -695,6 +668,16 @@ def lookup_base_station_by_name(self, name):
return base_station[0]
return None

def lookup_device_by_id(self, device_id):
device = self.lookup_base_station_by_id(device_id)
if device is None:
device = self.lookup_camera_by_id(device_id)
if device is None:
device = self.lookup_doorbell_by_id(device_id)
if device is None:
device = self.lookup_light_by_id(device_id)
return device

def inject_response(self, response):
"""Inject a test packet into the event stream.
Expand Down
7 changes: 7 additions & 0 deletions custom_components/aarlo/pyaarlo/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,13 @@ def _event_dispatcher(self, response):
device_id = resource.split("/")[1]
responses.append((device_id, resource, response))

# Device status...
elif resource == 'devices':
for device_id in response.get('devices', {}):
self._arlo.debug(f"DEVICES={device_id}")
props = response['devices'][device_id]
responses.append((device_id, resource, props))

# These are base station responses. Which can be about the base station
# or devices on it... Check if property is list.
# Packet number #3/#2
Expand Down
14 changes: 14 additions & 0 deletions custom_components/aarlo/pyaarlo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,20 @@ def update_modes(self, initial=False):
if curr_location:
curr_location.update_mode()

def update_states(self):
# Only do work on 'old' style base stations
if self.device_type == 'basestation' or self.device_type == 'arlobridge':
self.debug("updating state")
self._arlo.be.notify(
base=self,
body={
"action": "get",
"resource": "devices",
"publishResponse": False,
},
wait_for="response",
)

@property
def schedule(self):
"""Returns current schedule name or `None` if no schedule active."""
Expand Down
6 changes: 4 additions & 2 deletions custom_components/aarlo/pyaarlo/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
EVENT_STREAM_TIMEOUT = (FAST_REFRESH_INTERVAL * 2) + 5
MODE_UPDATE_INTERVAL = 2

# Device capabilities
PING_CAPABILITY = "pingCapability"
RESOURCE_CAPABILITY = "resourceCapability"

# update keys
ACTIVITY_STATE_KEY = "activityState"
AIR_QUALITY_KEY = "airQuality"
Expand All @@ -86,8 +90,6 @@
MOTION_STATE_KEY = "motionState"
MOTION_ENABLED_KEY = "motionSetupModeEnabled"
MOTION_SENS_KEY = "motionSetupModeSensitivity"
PING_CAPABILITY = "pingCapability"
RESOURCE_CAPABILITY = "resourceCapability"
POWER_SAVE_KEY = "powerSaveMode"
PRIVACY_KEY = "privacyActive"
LIGHT_BRIGHTNESS_KEY = "lightBrightness"
Expand Down
3 changes: 2 additions & 1 deletion custom_components/aarlo/pyaarlo/tfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def start(self):
return False

self._new_ids = self._old_ids
self._arlo.debug("old-ids={}".format(self._old_ids))
self._arlo.debug("2fa-imap: old-ids={}".format(self._old_ids))
if res.lower() == "ok":
return True

Expand All @@ -92,6 +92,7 @@ def get(self):

# give tfa_total_timeout seconds for email to arrive
start = time.time()
self._arlo.debug(f"2fa-imap: retry-every={self._arlo.cfg.tfa_timeout},up-to={self._arlo.cfg.tfa_total_timeout}")
while True:

# wait a short while, stop after a total timeout
Expand Down
Loading

0 comments on commit f78e9c7

Please sign in to comment.