From cbc13dc71b189f6f742ac481c6fae3a65dce18a0 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Fri, 9 Dec 2022 11:39:59 -0700 Subject: [PATCH 1/4] Update vivintpy to 2022.12.0 --- custom_components/vivint/manifest.json | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/custom_components/vivint/manifest.json b/custom_components/vivint/manifest.json index c157331..5e53e07 100644 --- a/custom_components/vivint/manifest.json +++ b/custom_components/vivint/manifest.json @@ -1,17 +1,12 @@ { "domain": "vivint", "name": "Vivint", - "version": "2022.6.2", + "version": "2022.12.0", "config_flow": true, "documentation": "https://github.com/natekspencer/hacs-vivint", "issue_tracker": "https://github.com/natekspencer/hacs-vivint/issues", - "requirements": [ - "vivintpy==2022.6.0" - ], - "dependencies": [ - "ffmpeg" - ], - "codeowners": [ - "@natekspencer" - ] -} \ No newline at end of file + "requirements": ["vivintpy==2022.12.0"], + "dependencies": ["ffmpeg"], + "codeowners": ["@natekspencer"], + "zeroconf": ["_vivint-ODC300._tcp.local.", "_vivint-DBC350._tcp.local."] +} From e4c9451699dbe682f01acc6f03315c590f7ecc78 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Fri, 9 Dec 2022 11:45:00 -0700 Subject: [PATCH 2/4] Display better auth error messages during config --- custom_components/vivint/config_flow.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/custom_components/vivint/config_flow.py b/custom_components/vivint/config_flow.py index b22e8fc..0fad03e 100644 --- a/custom_components/vivint/config_flow.py +++ b/custom_components/vivint/config_flow.py @@ -123,12 +123,19 @@ async def async_step_mfa( self, user_input: dict[str, Any] | None = None ) -> FlowResult: """Handle a multi-factor authentication (MFA) flow.""" - super().async_step_user() + await super().async_step_user() if user_input is None: return self.async_show_form(step_id="mfa", data_schema=STEP_MFA_DATA_SCHEMA) try: await self._hub.verify_mfa(user_input[CONF_MFA]) + except VivintSkyApiAuthenticationError as err: # pylint: disable=broad-except + _LOGGER.error(err) + return self.async_show_form( + step_id="mfa", + data_schema=STEP_MFA_DATA_SCHEMA, + errors={"base": str(err)}, + ) except Exception as ex: # pylint: disable=broad-except _LOGGER.error(ex) return self.async_show_form( From 7fd8b98f27ba6af7b0b8e8fbf5b0b1b1aeb3c763 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Fri, 9 Dec 2022 11:45:46 -0700 Subject: [PATCH 3/4] Fix via_device for devices connected through panel --- custom_components/vivint/hub.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/vivint/hub.py b/custom_components/vivint/hub.py index 681eea8..1455fd7 100644 --- a/custom_components/vivint/hub.py +++ b/custom_components/vivint/hub.py @@ -176,5 +176,5 @@ def device_info(self) -> DeviceInfo: sw_version=device.software_version, via_device=None if isinstance(device, AlarmPanel) - else (DOMAIN, device.alarm_panel.id), + else get_device_id(device.alarm_panel), ) From ef7311c7f182c486732bdf7d9a14fc03662e9d51 Mon Sep 17 00:00:00 2001 From: Nathan Spencer Date: Fri, 9 Dec 2022 11:46:33 -0700 Subject: [PATCH 4/4] Add online binary sensor entity for supported devices --- custom_components/vivint/binary_sensor.py | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/custom_components/vivint/binary_sensor.py b/custom_components/vivint/binary_sensor.py index 9e8e9ad..7b6ad15 100644 --- a/custom_components/vivint/binary_sensor.py +++ b/custom_components/vivint/binary_sensor.py @@ -1,4 +1,6 @@ """Support for Vivint binary sensors.""" +from __future__ import annotations + from datetime import datetime, timedelta from vivintpy.devices import VivintDevice @@ -15,6 +17,7 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect +from homeassistant.helpers.entity import EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.event import async_call_later from homeassistant.util.dt import utcnow @@ -51,6 +54,18 @@ async def async_setup_entry( entity_description=ENTITY_DESCRIPTION_MOTION, ) ) + elif hasattr(device, "node_online"): + entities.append( + VivintOnlineBinarySensorEntity( + device=device, hub=hub, key="node_online" + ) + ) + elif hasattr(device, "is_online"): + entities.append( + VivintOnlineBinarySensorEntity( + device=device, hub=hub, key="is_online" + ) + ) if not entities: return @@ -199,3 +214,27 @@ def async_cancel_motion_stopped_callback(self) -> None: if self._motion_stopped_callback is not None: self._motion_stopped_callback() self._motion_stopped_callback = None + + +class VivintOnlineBinarySensorEntity(VivintEntity, BinarySensorEntity): + """Vivint online binary sensor entity.""" + + _attr_device_class = BinarySensorDeviceClass.CONNECTIVITY + _attr_entity_category = EntityCategory.DIAGNOSTIC + _attr_has_entity_name = True + _attr_name = "Online" + + def __init__(self, device: VivintDevice, hub: VivintHub, key: str) -> None: + """Initialize a Vivint online binary sensor entity.""" + super().__init__(device=device, hub=hub) + self._key = key + + @property + def unique_id(self) -> str: + """Return a unique ID.""" + return f"{self.device.alarm_panel.id}-{self.device.id}-online" + + @property + def is_on(self) -> bool: + """Return true if the binary sensor is on.""" + return getattr(self.device, self._key)