Abode services, events, lights, cameras, automations, quick actions. (#9310)

* Updated to latest AbodePy version. Added services and events. Added new device types. Added exclude, light, and polling config options.

* Disable the event service if polling is enabled.

* Addressed all CR's

* Removed duplicated super call.

* Name config option now used. Removed deprecated DEFAULT_NAME.

* Modified partial to move event to first param.
This commit is contained in:
Mister Wil 2017-09-18 08:39:41 -07:00 committed by Pascal Vizeli
parent 5851944f80
commit c44397e257
10 changed files with 588 additions and 96 deletions

View file

@ -6,57 +6,138 @@ https://home-assistant.io/components/abode/
""" """
import asyncio import asyncio
import logging import logging
from functools import partial
from os import path
import voluptuous as vol import voluptuous as vol
from requests.exceptions import HTTPError, ConnectTimeout from requests.exceptions import HTTPError, ConnectTimeout
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity import Entity
from homeassistant.const import (ATTR_ATTRIBUTION, from homeassistant.config import load_yaml_config_file
CONF_USERNAME, CONF_PASSWORD, from homeassistant.const import (ATTR_ATTRIBUTION, ATTR_DATE, ATTR_TIME,
CONF_NAME, EVENT_HOMEASSISTANT_STOP, ATTR_ENTITY_ID, CONF_USERNAME, CONF_PASSWORD,
CONF_EXCLUDE, CONF_NAME,
EVENT_HOMEASSISTANT_STOP,
EVENT_HOMEASSISTANT_START) EVENT_HOMEASSISTANT_START)
REQUIREMENTS = ['abodepy==0.9.0'] REQUIREMENTS = ['abodepy==0.11.5']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CONF_ATTRIBUTION = "Data provided by goabode.com" CONF_ATTRIBUTION = "Data provided by goabode.com"
CONF_LIGHTS = "lights"
CONF_POLLING = "polling"
DOMAIN = 'abode' DOMAIN = 'abode'
DEFAULT_NAME = 'Abode'
DATA_ABODE = 'abode'
NOTIFICATION_ID = 'abode_notification' NOTIFICATION_ID = 'abode_notification'
NOTIFICATION_TITLE = 'Abode Security Setup' NOTIFICATION_TITLE = 'Abode Security Setup'
EVENT_ABODE_ALARM = 'abode_alarm'
EVENT_ABODE_ALARM_END = 'abode_alarm_end'
EVENT_ABODE_AUTOMATION = 'abode_automation'
EVENT_ABODE_FAULT = 'abode_panel_fault'
EVENT_ABODE_RESTORE = 'abode_panel_restore'
SERVICE_SETTINGS = 'change_setting'
SERVICE_CAPTURE_IMAGE = 'capture_image'
SERVICE_TRIGGER = 'trigger_quick_action'
ATTR_DEVICE_ID = 'device_id'
ATTR_DEVICE_NAME = 'device_name'
ATTR_DEVICE_TYPE = 'device_type'
ATTR_EVENT_CODE = 'event_code'
ATTR_EVENT_NAME = 'event_name'
ATTR_EVENT_TYPE = 'event_type'
ATTR_EVENT_UTC = 'event_utc'
ATTR_SETTING = 'setting'
ATTR_USER_NAME = 'user_name'
ATTR_VALUE = 'value'
ABODE_DEVICE_ID_LIST_SCHEMA = vol.Schema([str])
CONFIG_SCHEMA = vol.Schema({ CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({ DOMAIN: vol.Schema({
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME): cv.string,
vol.Optional(CONF_POLLING, default=False): cv.boolean,
vol.Optional(CONF_EXCLUDE, default=[]): ABODE_DEVICE_ID_LIST_SCHEMA,
vol.Optional(CONF_LIGHTS, default=[]): ABODE_DEVICE_ID_LIST_SCHEMA
}), }),
}, extra=vol.ALLOW_EXTRA) }, extra=vol.ALLOW_EXTRA)
CHANGE_SETTING_SCHEMA = vol.Schema({
vol.Required(ATTR_SETTING): cv.string,
vol.Required(ATTR_VALUE): cv.string
})
CAPTURE_IMAGE_SCHEMA = vol.Schema({
ATTR_ENTITY_ID: cv.entity_ids,
})
TRIGGER_SCHEMA = vol.Schema({
ATTR_ENTITY_ID: cv.entity_ids,
})
ABODE_PLATFORMS = [ ABODE_PLATFORMS = [
'alarm_control_panel', 'binary_sensor', 'lock', 'switch', 'cover' 'alarm_control_panel', 'binary_sensor', 'lock', 'switch', 'cover',
'camera', 'light'
] ]
class AbodeSystem(object):
"""Abode System class."""
def __init__(self, username, password, name, polling, exclude, lights):
"""Initialize the system."""
import abodepy
self.abode = abodepy.Abode(username, password,
auto_login=True,
get_devices=True,
get_automations=True)
self.name = name
self.polling = polling
self.exclude = exclude
self.lights = lights
self.devices = []
def is_excluded(self, device):
"""Check if a device is configured to be excluded."""
return device.device_id in self.exclude
def is_automation_excluded(self, automation):
"""Check if an automation is configured to be excluded."""
return automation.automation_id in self.exclude
def is_light(self, device):
"""Check if a switch device is configured as a light."""
import abodepy.helpers.constants as CONST
return (device.generic_type == CONST.TYPE_LIGHT or
(device.generic_type == CONST.TYPE_SWITCH and
device.device_id in self.lights))
def setup(hass, config): def setup(hass, config):
"""Set up Abode component.""" """Set up Abode component."""
import abodepy from abodepy.exceptions import AbodeException
conf = config[DOMAIN] conf = config[DOMAIN]
username = conf.get(CONF_USERNAME) username = conf.get(CONF_USERNAME)
password = conf.get(CONF_PASSWORD) password = conf.get(CONF_PASSWORD)
name = conf.get(CONF_NAME)
polling = conf.get(CONF_POLLING)
exclude = conf.get(CONF_EXCLUDE)
lights = conf.get(CONF_LIGHTS)
try: try:
hass.data[DATA_ABODE] = abode = abodepy.Abode( hass.data[DOMAIN] = AbodeSystem(
username, password, auto_login=True, get_devices=True) username, password, name, polling, exclude, lights)
except (AbodeException, ConnectTimeout, HTTPError) as ex:
except (ConnectTimeout, HTTPError) as ex:
_LOGGER.error("Unable to connect to Abode: %s", str(ex)) _LOGGER.error("Unable to connect to Abode: %s", str(ex))
hass.components.persistent_notification.create( hass.components.persistent_notification.create(
'Error: {}<br />' 'Error: {}<br />'
'You will need to restart hass after fixing.' 'You will need to restart hass after fixing.'
@ -65,46 +146,144 @@ def setup(hass, config):
notification_id=NOTIFICATION_ID) notification_id=NOTIFICATION_ID)
return False return False
setup_hass_services(hass)
setup_hass_events(hass)
setup_abode_events(hass)
for platform in ABODE_PLATFORMS: for platform in ABODE_PLATFORMS:
discovery.load_platform(hass, platform, DOMAIN, {}, config) discovery.load_platform(hass, platform, DOMAIN, {}, config)
return True
def setup_hass_services(hass):
"""Home assistant services."""
from abodepy.exceptions import AbodeException
def change_setting(call):
"""Change an Abode system setting."""
setting = call.data.get(ATTR_SETTING)
value = call.data.get(ATTR_VALUE)
try:
hass.data[DOMAIN].abode.set_setting(setting, value)
except AbodeException as ex:
_LOGGER.warning(ex)
def capture_image(call):
"""Capture a new image."""
entity_ids = call.data.get(ATTR_ENTITY_ID)
target_devices = [device for device in hass.data[DOMAIN].devices
if device.entity_id in entity_ids]
for device in target_devices:
device.capture()
def trigger_quick_action(call):
"""Trigger a quick action."""
entity_ids = call.data.get(ATTR_ENTITY_ID, None)
target_devices = [device for device in hass.data[DOMAIN].devices
if device.entity_id in entity_ids]
for device in target_devices:
device.trigger()
descriptions = load_yaml_config_file(
path.join(path.dirname(__file__), 'services.yaml'))[DOMAIN]
hass.services.register(
DOMAIN, SERVICE_SETTINGS, change_setting,
descriptions.get(SERVICE_SETTINGS),
schema=CHANGE_SETTING_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_CAPTURE_IMAGE, capture_image,
descriptions.get(SERVICE_CAPTURE_IMAGE),
schema=CAPTURE_IMAGE_SCHEMA)
hass.services.register(
DOMAIN, SERVICE_TRIGGER, trigger_quick_action,
descriptions.get(SERVICE_TRIGGER),
schema=TRIGGER_SCHEMA)
def setup_hass_events(hass):
"""Home assistant start and stop callbacks."""
def startup(event):
"""Listen for push events."""
hass.data[DOMAIN].abode.events.start()
def logout(event): def logout(event):
"""Logout of Abode.""" """Logout of Abode."""
abode.stop_listener() if not hass.data[DOMAIN].polling:
abode.logout() hass.data[DOMAIN].abode.events.stop()
hass.data[DOMAIN].abode.logout()
_LOGGER.info("Logged out of Abode") _LOGGER.info("Logged out of Abode")
if not hass.data[DOMAIN].polling:
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, startup)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, logout) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, logout)
def startup(event):
"""Listen for push events."""
abode.start_listener()
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, startup) def setup_abode_events(hass):
"""Event callbacks."""
import abodepy.helpers.timeline as TIMELINE
return True def event_callback(event, event_json):
"""Handle an event callback from Abode."""
data = {
ATTR_DEVICE_ID: event_json.get(ATTR_DEVICE_ID, ''),
ATTR_DEVICE_NAME: event_json.get(ATTR_DEVICE_NAME, ''),
ATTR_DEVICE_TYPE: event_json.get(ATTR_DEVICE_TYPE, ''),
ATTR_EVENT_CODE: event_json.get(ATTR_EVENT_CODE, ''),
ATTR_EVENT_NAME: event_json.get(ATTR_EVENT_NAME, ''),
ATTR_EVENT_TYPE: event_json.get(ATTR_EVENT_TYPE, ''),
ATTR_EVENT_UTC: event_json.get(ATTR_EVENT_UTC, ''),
ATTR_USER_NAME: event_json.get(ATTR_USER_NAME, ''),
ATTR_DATE: event_json.get(ATTR_DATE, ''),
ATTR_TIME: event_json.get(ATTR_TIME, ''),
}
hass.bus.fire(event, data)
events = [TIMELINE.ALARM_GROUP, TIMELINE.ALARM_END_GROUP,
TIMELINE.PANEL_FAULT_GROUP, TIMELINE.PANEL_RESTORE_GROUP,
TIMELINE.AUTOMATION_GROUP]
for event in events:
hass.data[DOMAIN].abode.events.add_event_callback(
event,
partial(event_callback, event))
class AbodeDevice(Entity): class AbodeDevice(Entity):
"""Representation of an Abode device.""" """Representation of an Abode device."""
def __init__(self, controller, device): def __init__(self, data, device):
"""Initialize a sensor for Abode device.""" """Initialize a sensor for Abode device."""
self._controller = controller self._data = data
self._device = device self._device = device
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self): def async_added_to_hass(self):
"""Subscribe Abode events.""" """Subscribe Abode events."""
self.hass.async_add_job( self.hass.async_add_job(
self._controller.register, self._device, self._data.abode.events.add_device_callback,
self._update_callback self._device.device_id, self._update_callback
) )
@property @property
def should_poll(self): def should_poll(self):
"""Return the polling state.""" """Return the polling state."""
return False return self._data.polling
def update(self):
"""Update automation state."""
self._device.refresh()
@property @property
def name(self): def name(self):
@ -124,3 +303,51 @@ class AbodeDevice(Entity):
def _update_callback(self, device): def _update_callback(self, device):
"""Update the device state.""" """Update the device state."""
self.schedule_update_ha_state() self.schedule_update_ha_state()
class AbodeAutomation(Entity):
"""Representation of an Abode automation."""
def __init__(self, data, automation, event=None):
"""Initialize for Abode automation."""
self._data = data
self._automation = automation
self._event = event
@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe Abode events."""
if self._event:
self.hass.async_add_job(
self._data.abode.events.add_event_callback,
self._event, self._update_callback
)
@property
def should_poll(self):
"""Return the polling state."""
return self._data.polling
def update(self):
"""Update automation state."""
self._automation.refresh()
@property
def name(self):
"""Return the name of the sensor."""
return self._automation.name
@property
def device_state_attributes(self):
"""Return the state attributes."""
return {
ATTR_ATTRIBUTION: CONF_ATTRIBUTION,
'automation_id': self._automation.automation_id,
'type': self._automation.type,
'sub_type': self._automation.sub_type
}
def _update_callback(self, device):
"""Update the device state."""
self._automation.refresh()
self.schedule_update_ha_state()

View file

@ -7,7 +7,7 @@ https://home-assistant.io/components/alarm_control_panel.abode/
import logging import logging
from homeassistant.components.abode import ( from homeassistant.components.abode import (
AbodeDevice, DATA_ABODE, DEFAULT_NAME, CONF_ATTRIBUTION) AbodeDevice, DOMAIN as ABODE_DOMAIN, CONF_ATTRIBUTION)
from homeassistant.components.alarm_control_panel import (AlarmControlPanel) from homeassistant.components.alarm_control_panel import (AlarmControlPanel)
from homeassistant.const import (ATTR_ATTRIBUTION, STATE_ALARM_ARMED_AWAY, from homeassistant.const import (ATTR_ATTRIBUTION, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED) STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED)
@ -22,18 +22,22 @@ ICON = 'mdi:security'
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up a sensor for an Abode device.""" """Set up a sensor for an Abode device."""
abode = hass.data[DATA_ABODE] data = hass.data[ABODE_DOMAIN]
add_devices([AbodeAlarm(abode, abode.get_alarm())]) alarm_devices = [AbodeAlarm(data, data.abode.get_alarm(), data.name)]
data.devices.extend(alarm_devices)
add_devices(alarm_devices)
class AbodeAlarm(AbodeDevice, AlarmControlPanel): class AbodeAlarm(AbodeDevice, AlarmControlPanel):
"""An alarm_control_panel implementation for Abode.""" """An alarm_control_panel implementation for Abode."""
def __init__(self, controller, device): def __init__(self, data, device, name):
"""Initialize the alarm control panel.""" """Initialize the alarm control panel."""
AbodeDevice.__init__(self, controller, device) super().__init__(data, device)
self._name = "{0}".format(DEFAULT_NAME) self._name = name
@property @property
def icon(self): def icon(self):
@ -65,6 +69,11 @@ class AbodeAlarm(AbodeDevice, AlarmControlPanel):
"""Send arm away command.""" """Send arm away command."""
self._device.set_away() self._device.set_away()
@property
def name(self):
"""Return the name of the alarm."""
return self._name or super().name
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""Return the state attributes.""" """Return the state attributes."""

View file

@ -6,7 +6,8 @@ https://home-assistant.io/components/binary_sensor.abode/
""" """
import logging import logging
from homeassistant.components.abode import AbodeDevice, DATA_ABODE from homeassistant.components.abode import (AbodeDevice, AbodeAutomation,
DOMAIN as ABODE_DOMAIN)
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
@ -17,39 +18,38 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up a sensor for an Abode device.""" """Set up a sensor for an Abode device."""
abode = hass.data[DATA_ABODE]
device_types = map_abode_device_class().keys()
sensors = []
for sensor in abode.get_devices(type_filter=device_types):
sensors.append(AbodeBinarySensor(abode, sensor))
add_devices(sensors)
def map_abode_device_class():
"""Map Abode device types to Home Assistant binary sensor class."""
import abodepy.helpers.constants as CONST import abodepy.helpers.constants as CONST
import abodepy.helpers.timeline as TIMELINE
return { data = hass.data[ABODE_DOMAIN]
CONST.DEVICE_GLASS_BREAK: 'connectivity',
CONST.DEVICE_KEYPAD: 'connectivity', device_types = [CONST.TYPE_CONNECTIVITY, CONST.TYPE_MOISTURE,
CONST.DEVICE_DOOR_CONTACT: 'opening', CONST.TYPE_MOTION, CONST.TYPE_OCCUPANCY,
CONST.DEVICE_STATUS_DISPLAY: 'connectivity', CONST.TYPE_OPENING]
CONST.DEVICE_MOTION_CAMERA: 'connectivity',
CONST.DEVICE_WATER_SENSOR: 'moisture' devices = []
} for device in data.abode.get_devices(generic_type=device_types):
if data.is_excluded(device):
continue
devices.append(AbodeBinarySensor(data, device))
for automation in data.abode.get_automations(
generic_type=CONST.TYPE_QUICK_ACTION):
if data.is_automation_excluded(automation):
continue
devices.append(AbodeQuickActionBinarySensor(
data, automation, TIMELINE.AUTOMATION_EDIT_GROUP))
data.devices.extend(devices)
add_devices(devices)
class AbodeBinarySensor(AbodeDevice, BinarySensorDevice): class AbodeBinarySensor(AbodeDevice, BinarySensorDevice):
"""A binary sensor implementation for Abode device.""" """A binary sensor implementation for Abode device."""
def __init__(self, controller, device):
"""Initialize a sensor for Abode device."""
AbodeDevice.__init__(self, controller, device)
self._device_class = map_abode_device_class().get(self._device.type)
@property @property
def is_on(self): def is_on(self):
"""Return True if the binary sensor is on.""" """Return True if the binary sensor is on."""
@ -58,4 +58,17 @@ class AbodeBinarySensor(AbodeDevice, BinarySensorDevice):
@property @property
def device_class(self): def device_class(self):
"""Return the class of the binary sensor.""" """Return the class of the binary sensor."""
return self._device_class return self._device.generic_type
class AbodeQuickActionBinarySensor(AbodeAutomation, BinarySensorDevice):
"""A binary sensor implementation for Abode quick action automations."""
def trigger(self):
"""Trigger a quick automation."""
self._automation.trigger()
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._automation.is_active

View file

@ -0,0 +1,101 @@
"""
This component provides HA camera support for Abode Security System.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.abode/
"""
import asyncio
import logging
from datetime import timedelta
import requests
from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.camera import Camera
from homeassistant.util import Throttle
DEPENDENCIES = ['abode']
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discoveryy_info=None):
"""Set up Abode camera devices."""
import abodepy.helpers.constants as CONST
import abodepy.helpers.timeline as TIMELINE
data = hass.data[ABODE_DOMAIN]
devices = []
for device in data.abode.get_devices(generic_type=CONST.TYPE_CAMERA):
if data.is_excluded(device):
continue
devices.append(AbodeCamera(data, device, TIMELINE.CAPTURE_IMAGE))
data.devices.extend(devices)
add_devices(devices)
class AbodeCamera(AbodeDevice, Camera):
"""Representation of an Abode camera."""
def __init__(self, data, device, event):
"""Initialize the Abode device."""
AbodeDevice.__init__(self, data, device)
Camera.__init__(self)
self._event = event
self._response = None
@asyncio.coroutine
def async_added_to_hass(self):
"""Subscribe Abode events."""
yield from super().async_added_to_hass()
self.hass.async_add_job(
self._data.abode.events.add_timeline_callback,
self._event, self._capture_callback
)
def capture(self):
"""Request a new image capture."""
return self._device.capture()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
def refresh_image(self):
"""Find a new image on the timeline."""
if self._device.refresh_image():
self.get_image()
def get_image(self):
"""Attempt to download the most recent capture."""
if self._device.image_url:
try:
self._response = requests.get(
self._device.image_url, stream=True)
self._response.raise_for_status()
except requests.HTTPError as err:
_LOGGER.warning("Failed to get camera image: %s", err)
self._response = None
else:
self._response = None
def camera_image(self):
"""Get a camera image."""
self.refresh_image()
if self._response:
return self._response.content
return None
def _capture_callback(self, capture):
"""Update the image with the device then refresh device."""
self._device.update_image_location(capture)
self.get_image()
self.schedule_update_ha_state()

View file

@ -6,7 +6,7 @@ https://home-assistant.io/components/cover.abode/
""" """
import logging import logging
from homeassistant.components.abode import AbodeDevice, DATA_ABODE from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.cover import CoverDevice from homeassistant.components.cover import CoverDevice
@ -19,31 +19,32 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Abode cover devices.""" """Set up Abode cover devices."""
import abodepy.helpers.constants as CONST import abodepy.helpers.constants as CONST
abode = hass.data[DATA_ABODE] data = hass.data[ABODE_DOMAIN]
sensors = [] devices = []
for sensor in abode.get_devices(type_filter=(CONST.DEVICE_SECURE_BARRIER)): for device in data.abode.get_devices(generic_type=CONST.TYPE_COVER):
sensors.append(AbodeCover(abode, sensor)) if data.is_excluded(device):
continue
add_devices(sensors) devices.append(AbodeCover(data, device))
data.devices.extend(devices)
add_devices(devices)
class AbodeCover(AbodeDevice, CoverDevice): class AbodeCover(AbodeDevice, CoverDevice):
"""Representation of an Abode cover.""" """Representation of an Abode cover."""
def __init__(self, controller, device):
"""Initialize the Abode device."""
AbodeDevice.__init__(self, controller, device)
@property @property
def is_closed(self): def is_closed(self):
"""Return true if cover is closed, else False.""" """Return true if cover is closed, else False."""
return self._device.is_open is False return not self._device.is_open
def close_cover(self): def close_cover(self, **kwargs):
"""Issue close command to cover.""" """Issue close command to cover."""
self._device.close_cover() self._device.close_cover()
def open_cover(self): def open_cover(self, **kwargs):
"""Issue open command to cover.""" """Issue open command to cover."""
self._device.open_cover() self._device.open_cover()

View file

@ -0,0 +1,84 @@
"""
This component provides HA light support for Abode Security System.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.abode/
"""
import logging
from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.light import (
ATTR_BRIGHTNESS, ATTR_RGB_COLOR,
SUPPORT_BRIGHTNESS, SUPPORT_RGB_COLOR, Light)
DEPENDENCIES = ['abode']
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Abode light devices."""
import abodepy.helpers.constants as CONST
data = hass.data[ABODE_DOMAIN]
device_types = [CONST.TYPE_LIGHT, CONST.TYPE_SWITCH]
devices = []
# Get all regular lights that are not excluded or switches marked as lights
for device in data.abode.get_devices(generic_type=device_types):
if data.is_excluded(device) or not data.is_light(device):
continue
devices.append(AbodeLight(data, device))
data.devices.extend(devices)
add_devices(devices)
class AbodeLight(AbodeDevice, Light):
"""Representation of an Abode light."""
def turn_on(self, **kwargs):
"""Turn on the light."""
if (ATTR_RGB_COLOR in kwargs and
self._device.is_dimmable and self._device.has_color):
self._device.set_color(kwargs[ATTR_RGB_COLOR])
elif ATTR_BRIGHTNESS in kwargs and self._device.is_dimmable:
self._device.set_level(kwargs[ATTR_BRIGHTNESS])
else:
self._device.switch_on()
def turn_off(self, **kwargs):
"""Turn off the light."""
self._device.switch_off()
@property
def is_on(self):
"""Return true if device is on."""
return self._device.is_on
@property
def brightness(self):
"""Return the brightness of the light."""
if self._device.is_dimmable and self._device.has_brightness:
return self._device.brightness
@property
def rgb_color(self):
"""Return the color of the light."""
if self._device.is_dimmable and self._device.has_color:
return self._device.color
@property
def supported_features(self):
"""Flag supported features."""
if self._device.is_dimmable and self._device.has_color:
return SUPPORT_BRIGHTNESS | SUPPORT_RGB_COLOR
elif self._device.is_dimmable:
return SUPPORT_BRIGHTNESS
return 0

View file

@ -6,7 +6,7 @@ https://home-assistant.io/components/lock.abode/
""" """
import logging import logging
from homeassistant.components.abode import AbodeDevice, DATA_ABODE from homeassistant.components.abode import AbodeDevice, DOMAIN as ABODE_DOMAIN
from homeassistant.components.lock import LockDevice from homeassistant.components.lock import LockDevice
@ -19,22 +19,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Abode lock devices.""" """Set up Abode lock devices."""
import abodepy.helpers.constants as CONST import abodepy.helpers.constants as CONST
abode = hass.data[DATA_ABODE] data = hass.data[ABODE_DOMAIN]
sensors = [] devices = []
for sensor in abode.get_devices(type_filter=(CONST.DEVICE_DOOR_LOCK)): for device in data.abode.get_devices(generic_type=CONST.TYPE_LOCK):
sensors.append(AbodeLock(abode, sensor)) if data.is_excluded(device):
continue
add_devices(sensors) devices.append(AbodeLock(data, device))
data.devices.extend(devices)
add_devices(devices)
class AbodeLock(AbodeDevice, LockDevice): class AbodeLock(AbodeDevice, LockDevice):
"""Representation of an Abode lock.""" """Representation of an Abode lock."""
def __init__(self, controller, device):
"""Initialize the Abode device."""
AbodeDevice.__init__(self, controller, device)
def lock(self, **kwargs): def lock(self, **kwargs):
"""Lock the device.""" """Lock the device."""
self._device.lock() self._device.lock()

View file

@ -571,3 +571,32 @@ counter:
entity_id: entity_id:
description: Entity id of the counter to reset. description: Entity id of the counter to reset.
example: 'counter.count0' example: 'counter.count0'
abode:
change_setting:
description: Change an Abode system setting.
fields:
setting:
description: Setting to change.
example: 'beeper_mute'
value:
description: Value of the setting.
example: '1'
capture_image:
description: Request a new image capture from a camera device.
fields:
entity_id:
description: Entity id of the camera to request an image.
example: 'camera.downstairs_motion_camera'
trigger_quick_action:
description: Trigger an Abode quick action.
fields:
entity_id:
description: Entity id of the quick action to trigger.
example: 'binary_sensor.home_quick_action'

View file

@ -6,7 +6,8 @@ https://home-assistant.io/components/switch.abode/
""" """
import logging import logging
from homeassistant.components.abode import AbodeDevice, DATA_ABODE from homeassistant.components.abode import (AbodeDevice, AbodeAutomation,
DOMAIN as ABODE_DOMAIN)
from homeassistant.components.switch import SwitchDevice from homeassistant.components.switch import SwitchDevice
@ -18,27 +19,36 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Abode switch devices.""" """Set up Abode switch devices."""
import abodepy.helpers.constants as CONST import abodepy.helpers.constants as CONST
import abodepy.helpers.timeline as TIMELINE
abode = hass.data[DATA_ABODE] data = hass.data[ABODE_DOMAIN]
device_types = [ devices = []
CONST.DEVICE_POWER_SWITCH_SENSOR,
CONST.DEVICE_POWER_SWITCH_METER]
sensors = [] # Get all regular switches that are not excluded or marked as lights
for sensor in abode.get_devices(type_filter=device_types): for device in data.abode.get_devices(generic_type=CONST.TYPE_SWITCH):
sensors.append(AbodeSwitch(abode, sensor)) if data.is_excluded(device) or not data.is_light(device):
continue
add_devices(sensors) devices.append(AbodeSwitch(data, device))
# Get all Abode automations that can be enabled/disabled
for automation in data.abode.get_automations(
generic_type=CONST.TYPE_AUTOMATION):
if data.is_automation_excluded(automation):
continue
devices.append(AbodeAutomationSwitch(
data, automation, TIMELINE.AUTOMATION_EDIT_GROUP))
data.devices.extend(devices)
add_devices(devices)
class AbodeSwitch(AbodeDevice, SwitchDevice): class AbodeSwitch(AbodeDevice, SwitchDevice):
"""Representation of an Abode switch.""" """Representation of an Abode switch."""
def __init__(self, controller, device):
"""Initialize the Abode device."""
AbodeDevice.__init__(self, controller, device)
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
"""Turn on the device.""" """Turn on the device."""
self._device.switch_on() self._device.switch_on()
@ -51,3 +61,20 @@ class AbodeSwitch(AbodeDevice, SwitchDevice):
def is_on(self): def is_on(self):
"""Return true if device is on.""" """Return true if device is on."""
return self._device.is_on return self._device.is_on
class AbodeAutomationSwitch(AbodeAutomation, SwitchDevice):
"""A switch implementation for Abode automations."""
def turn_on(self, **kwargs):
"""Turn on the device."""
self._automation.set_active(True)
def turn_off(self, **kwargs):
"""Turn off the device."""
self._automation.set_active(False)
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._automation.is_active

View file

@ -42,7 +42,7 @@ SoCo==0.12
TwitterAPI==2.4.6 TwitterAPI==2.4.6
# homeassistant.components.abode # homeassistant.components.abode
abodepy==0.9.0 abodepy==0.11.5
# homeassistant.components.device_tracker.automatic # homeassistant.components.device_tracker.automatic
aioautomatic==0.6.3 aioautomatic==0.6.3