Skip to content

Commit

Permalink
fix(alarm_control_panel): add supported_features
Browse files Browse the repository at this point in the history
  • Loading branch information
alandtse committed Dec 10, 2019
1 parent db20537 commit ceedd8b
Showing 1 changed file with 103 additions and 93 deletions.
196 changes: 103 additions & 93 deletions custom_components/alexa_media/alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
from typing import Dict, List, Text # noqa pylint: disable=unused-import

from homeassistant import util
from homeassistant.components.alarm_control_panel import AlarmControlPanel
from homeassistant.components.alarm_control_panel import (
SUPPORT_ALARM_ARM_AWAY,
AlarmControlPanel,
)
from homeassistant.const import STATE_ALARM_ARMED_AWAY, STATE_ALARM_DISARMED
from homeassistant.helpers.event import async_call_later

from . import (CONF_EMAIL, CONF_EXCLUDE_DEVICES, CONF_INCLUDE_DEVICES,
DATA_ALEXAMEDIA)
from . import CONF_EMAIL, CONF_EXCLUDE_DEVICES, CONF_INCLUDE_DEVICES, DATA_ALEXAMEDIA
from . import DOMAIN as ALEXA_DOMAIN
from . import MIN_TIME_BETWEEN_FORCED_SCANS, MIN_TIME_BETWEEN_SCANS, hide_email
from .helpers import _catch_login_errors, add_devices, retry_async
Expand All @@ -27,61 +29,65 @@


@retry_async(limit=5, delay=2, catch_exceptions=True)
async def async_setup_platform(hass,
config,
add_devices_callback,
discovery_info=None) -> bool:
async def async_setup_platform(
hass, config, add_devices_callback, discovery_info=None
) -> bool:
"""Set up the Alexa alarm control panel platform."""
devices = [] # type: List[AlexaAlarmControlPanel]
account = config[CONF_EMAIL]
include_filter = config.get(CONF_INCLUDE_DEVICES, [])
exclude_filter = config.get(CONF_EXCLUDE_DEVICES, [])
account_dict = hass.data[DATA_ALEXAMEDIA]['accounts'][account]
if 'alarm_control_panel' not in (account_dict
['entities']):
(hass.data[DATA_ALEXAMEDIA]
['accounts']
[account]
['entities']['alarm_control_panel']) = {}
account_dict = hass.data[DATA_ALEXAMEDIA]["accounts"][account]
if "alarm_control_panel" not in (account_dict["entities"]):
(
hass.data[DATA_ALEXAMEDIA]["accounts"][account]["entities"][
"alarm_control_panel"
]
) = {}
alexa_client: AlexaAlarmControlPanel = AlexaAlarmControlPanel(
account_dict['login_obj'])
account_dict["login_obj"]
)
await alexa_client.init()
if not (alexa_client and alexa_client.unique_id):
_LOGGER.debug("%s: Skipping creation of uninitialized device: %s",
hide_email(account),
alexa_client)
elif alexa_client.unique_id not in (account_dict
['entities']
['alarm_control_panel']):
_LOGGER.debug(
"%s: Skipping creation of uninitialized device: %s",
hide_email(account),
alexa_client,
)
elif alexa_client.unique_id not in (
account_dict["entities"]["alarm_control_panel"]
):
devices.append(alexa_client)
(hass.data[DATA_ALEXAMEDIA]
['accounts']
[account]
['entities']
['alarm_control_panel'][alexa_client.unique_id]) = alexa_client
(
hass.data[DATA_ALEXAMEDIA]["accounts"][account]["entities"][
"alarm_control_panel"
][alexa_client.unique_id]
) = alexa_client
else:
_LOGGER.debug("%s: Skipping already added device: %s",
hide_email(account),
alexa_client)
return await add_devices(hide_email(account),
devices, add_devices_callback,
include_filter, exclude_filter)
_LOGGER.debug(
"%s: Skipping already added device: %s", hide_email(account), alexa_client
)
return await add_devices(
hide_email(account),
devices,
add_devices_callback,
include_filter,
exclude_filter,
)


async def async_setup_entry(hass, config_entry, async_add_devices):
"""Set up the Alexa alarm control panel platform by config_entry."""
return await async_setup_platform(
hass,
config_entry.data,
async_add_devices,
discovery_info=None)
hass, config_entry.data, async_add_devices, discovery_info=None
)


async def async_unload_entry(hass, entry) -> bool:
"""Unload a config entry."""
account = entry.data[CONF_EMAIL]
account_dict = hass.data[DATA_ALEXAMEDIA]['accounts'][account]
for device in account_dict['entities']['alarm_control_panel'].values():
account_dict = hass.data[DATA_ALEXAMEDIA]["accounts"][account]
for device in account_dict["entities"]["alarm_control_panel"].values():
await device.async_remove()
return True

Expand All @@ -93,6 +99,7 @@ def __init__(self, login) -> None:
# pylint: disable=unexpected-keyword-arg
"""Initialize the Alexa device."""
from alexapy import AlexaAPI

# Class info
self._login = login
self.alexa_api = AlexaAPI(self, login)
Expand All @@ -111,24 +118,29 @@ async def init(self):
"""Initialize."""
try:
from simplejson import JSONDecodeError

data = await self.alexa_api.get_guard_details(self._login)
guard_dict = (data['locationDetails']
['locationDetails']['Default_Location']
['amazonBridgeDetails']['amazonBridgeDetails']
['LambdaBridge_AAA/OnGuardSmartHomeBridgeService']
['applianceDetails']['applianceDetails'])
guard_dict = data["locationDetails"]["locationDetails"]["Default_Location"][
"amazonBridgeDetails"
]["amazonBridgeDetails"]["LambdaBridge_AAA/OnGuardSmartHomeBridgeService"][
"applianceDetails"
][
"applianceDetails"
]
except (KeyError, TypeError, JSONDecodeError):
guard_dict = {}
for _, value in guard_dict.items():
if value['modelName'] == "REDROCK_GUARD_PANEL":
self._appliance_id = value['applianceId']
self._guard_entity_id = value['entityId']
if value["modelName"] == "REDROCK_GUARD_PANEL":
self._appliance_id = value["applianceId"]
self._guard_entity_id = value["entityId"]
self._friendly_name += " " + self._appliance_id[-5:]
_LOGGER.debug("%s: Discovered %s: %s %s",
self.account,
self._friendly_name,
self._appliance_id,
self._guard_entity_id)
_LOGGER.debug(
"%s: Discovered %s: %s %s",
self.account,
self._friendly_name,
self._appliance_id,
self._guard_entity_id,
)
if not self._appliance_id:
_LOGGER.debug("%s: No Alexa Guard entity found", self.account)

Expand All @@ -141,8 +153,8 @@ async def async_added_to_hass(self):
pass
# Register event handler on bus
self._listener = self.hass.bus.async_listen(
f'{ALEXA_DOMAIN}_{hide_email(self._login.email)}'[0:32],
self._handle_event)
f"{ALEXA_DOMAIN}_{hide_email(self._login.email)}"[0:32], self._handle_event
)

async def async_will_remove_from_hass(self):
"""Prepare to remove entity."""
Expand All @@ -159,10 +171,14 @@ def _handle_event(self, event):
return
except AttributeError:
pass
if 'push_activity' in event.data:
async_call_later(self.hass, 2, lambda _:
self.hass.async_create_task(
self.async_update(no_throttle=True)))
if "push_activity" in event.data:
async_call_later(
self.hass,
2,
lambda _: self.hass.async_create_task(
self.async_update(no_throttle=True)
),
)

@util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS)
@_catch_login_errors
Expand All @@ -174,27 +190,29 @@ async def async_update(self):
except AttributeError:
pass
import json

_LOGGER.debug("%s: Refreshing %s", self.account, self.name)
state = None
state_json = await self.alexa_api.get_guard_state(self._login,
self._appliance_id)
state_json = await self.alexa_api.get_guard_state(
self._login, self._appliance_id
)
# _LOGGER.debug("%s: state_json %s", self.account, state_json)
if (state_json and 'deviceStates' in state_json
and state_json['deviceStates']):
cap = state_json['deviceStates'][0]['capabilityStates']
if state_json and "deviceStates" in state_json and state_json["deviceStates"]:
cap = state_json["deviceStates"][0]["capabilityStates"]
# _LOGGER.debug("%s: cap %s", self.account, cap)
for item_json in cap:
item = json.loads(item_json)
# _LOGGER.debug("%s: item %s", self.account, item)
if item['name'] == 'armState':
state = item['value']
if item["name"] == "armState":
state = item["value"]
# _LOGGER.debug("%s: state %s", self.account, state)
elif state_json['errors']:
_LOGGER.debug("%s: Error refreshing alarm_control_panel %s: %s",
self.account,
self.name,
json.dumps(state_json['errors']) if state_json
else None)
elif state_json["errors"]:
_LOGGER.debug(
"%s: Error refreshing alarm_control_panel %s: %s",
self.account,
self.name,
json.dumps(state_json["errors"]) if state_json else None,
)
if state is None:
return
if state == "ARMED_AWAY":
Expand All @@ -209,28 +227,15 @@ async def async_update(self):
@_catch_login_errors
async def async_alarm_disarm(self, code=None) -> None:
# pylint: disable=unexpected-keyword-arg
"""Send disarm command.
We use the arm_home state as Alexa does not have disarm state.
"""
try:
if not self.enabled:
return
except AttributeError:
pass
await self.async_alarm_arm_home()

@_catch_login_errors
async def async_alarm_arm_home(self, code=None) -> None:
"""Send arm home command."""
"""Send disarm command."""
try:
if not self.enabled:
return
except AttributeError:
pass
await self.alexa_api.set_guard_state(self._login,
self._guard_entity_id,
"ARMED_STAY")
await self.alexa_api.set_guard_state(
self._login, self._guard_entity_id, "ARMED_STAY"
)
await self.async_update(no_throttle=True)
self.async_schedule_update_ha_state()

Expand All @@ -243,9 +248,9 @@ async def async_alarm_arm_away(self, code=None) -> None:
return
except AttributeError:
pass
await self.alexa_api.set_guard_state(self._login,
self._guard_entity_id,
"ARMED_AWAY")
await self.alexa_api.set_guard_state(
self._login, self._guard_entity_id, "ARMED_AWAY"
)
await self.async_update(no_throttle=True)
self.async_schedule_update_ha_state()

Expand All @@ -272,6 +277,11 @@ def device_state_attributes(self):
@property
def should_poll(self):
"""Return the polling state."""
return self._should_poll or not (self.hass.data[DATA_ALEXAMEDIA]
['accounts'][self._login.email]
['websocket'])
return self._should_poll or not (
self.hass.data[DATA_ALEXAMEDIA]["accounts"][self._login.email]["websocket"]
)

@property
def supported_features(self) -> int:
"""Return the list of supported features."""
return SUPPORT_ALARM_ARM_AWAY

0 comments on commit ceedd8b

Please sign in to comment.