Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
bbd9489
Early draft
Kane610 Sep 2, 2019
d71d90b
Getting there
Kane610 Sep 3, 2019
3145c9f
Working fully with Hue dimmer remote
Kane610 Sep 3, 2019
d86f999
Fix Balloobs comments
Kane610 Sep 4, 2019
32668b7
No side effects in constructor
Kane610 Sep 4, 2019
ba36889
Improve hue dimmer
Kane610 Sep 4, 2019
6f51be7
Add Ikea remote control
Kane610 Sep 4, 2019
e201f5e
Add xiaomi button support
Kane610 Sep 6, 2019
e00d8c9
Refactor getting deconz event
Kane610 Sep 6, 2019
3f92b6f
Added xiaomi devices and tradfri wireless dimmer
Kane610 Sep 6, 2019
12c6ddc
Resolve unique id from device id
Kane610 Sep 6, 2019
bbc1945
Add Hue Tap and Tradfri on off switch
Kane610 Sep 7, 2019
7bbc627
More triggers for ikea on off switch and Aqara double wall switch
Kane610 Sep 7, 2019
8934c19
Add support for Tradfri open close remote
Kane610 Sep 7, 2019
f6e840d
Fix changes after rebase
Kane610 Sep 8, 2019
4a83848
Initial test
Kane610 Sep 8, 2019
df6a2b2
Change id to event_id
Kane610 Sep 8, 2019
c1196f0
Fix translations and add subtypes
Kane610 Sep 8, 2019
fc6204c
Try if tests pass without the new tests
Kane610 Sep 9, 2019
b03ca28
Revert disabling tests
Kane610 Sep 9, 2019
2f7d74d
Ignore places calling remotes
Kane610 Sep 9, 2019
94d45b4
Enable all gateway tests
Kane610 Sep 10, 2019
157b51b
Found the issue, now to identify which test creates it
Kane610 Sep 10, 2019
8242c06
Remove block till done
Kane610 Sep 10, 2019
12d789d
See if device automation test passes in azure
Kane610 Sep 10, 2019
ee17f73
Register event to device registry
Kane610 Sep 10, 2019
bb87686
Enable test sensors
Kane610 Sep 10, 2019
d9f4b87
Skip deconz event tests currently failing
Kane610 Sep 10, 2019
5092201
Added reason why skipping tests
Kane610 Sep 10, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import voluptuous as vol

from homeassistant.components.device_automation.exceptions import (
InvalidDeviceAutomationConfig,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_NAME,
Expand Down Expand Up @@ -467,7 +470,10 @@ async def _async_process_trigger(hass, config, trigger_configs, name, action):
for conf in trigger_configs:
platform = importlib.import_module(".{}".format(conf[CONF_PLATFORM]), __name__)

remove = await platform.async_trigger(hass, conf, action, info)
try:
remove = await platform.async_trigger(hass, conf, action, info)
except InvalidDeviceAutomationConfig:
remove = False

if not remove:
_LOGGER.error("Error setting up trigger %s", name)
Expand Down
29 changes: 29 additions & 0 deletions homeassistant/components/deconz/.translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,34 @@
"description": "Configure visibility of deCONZ device types"
}
}
},
"device_automation": {
"trigger_type": {
"remote_button_short_press": "\"{subtype}\" button pressed",
"remote_button_short_release": "\"{subtype}\" button released",
"remote_button_long_press": "\"{subtype}\" button continuously pressed",
"remote_button_long_release": "\"{subtype}\" button released after long press",
"remote_button_double_press": "\"{subtype}\" button double clicked",
"remote_button_triple_press": "\"{subtype}\" button triple clicked",
"remote_button_quadruple_press": "\"{subtype}\" button quadruple clicked",
"remote_button_quintuple_press": "\"{subtype}\" button quintuple clicked",
"remote_button_rotated": "Button rotated \"{subtype}\"",
"remote_gyro_activated": "Device shaken"
},
"trigger_subtype": {
"turn_on": "Turn on",
"turn_off": "Turn off",
"dim_up": "Dim up",
"dim_down": "Dim down",
"left": "Left",
"right": "Right",
"open": "Open",
"close": "Close",
"both_buttons": "Both buttons",
"button_1": "First button",
"button_2": "Second button",
"button_3": "Third button",
"button_4": "Fourth button"
}
}
}
79 changes: 48 additions & 31 deletions homeassistant/components/deconz/deconz_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,56 @@
from .const import DOMAIN as DECONZ_DOMAIN


class DeconzDevice(Entity):
"""Representation of a deCONZ device."""
class DeconzBase:
"""Common base for deconz entities and events."""

def __init__(self, device, gateway):
"""Set up device and add update callback to get data from websocket."""
self._device = device
self.gateway = gateway
self.listeners = []

@property
def unique_id(self):
"""Return a unique identifier for this device."""
return self._device.uniqueid

@property
def serial(self):
"""Return a serial number for this device."""
if self.unique_id is None or self.unique_id.count(":") != 7:
return None

return self.unique_id.split("-", 1)[0]

@property
def device_info(self):
"""Return a device description for device registry."""
if self.serial is None:
return None

bridgeid = self.gateway.api.config.bridgeid

return {
"connections": {(CONNECTION_ZIGBEE, self.serial)},
"identifiers": {(DECONZ_DOMAIN, self.serial)},
"manufacturer": self._device.manufacturer,
"model": self._device.modelid,
"name": self._device.name,
"sw_version": self._device.swversion,
"via_device": (DECONZ_DOMAIN, bridgeid),
}


class DeconzDevice(DeconzBase, Entity):
"""Representation of a deCONZ device."""

def __init__(self, device, gateway):
"""Set up device and add update callback to get data from websocket."""
super().__init__(device, gateway)

self.unsub_dispatcher = None

@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""
Expand Down Expand Up @@ -54,41 +95,17 @@ def async_update_callback(self, force_update=False):
"""Update the device's state."""
self.async_schedule_update_ha_state()

@property
def name(self):
"""Return the name of the device."""
return self._device.name

@property
def unique_id(self):
"""Return a unique identifier for this device."""
return self._device.uniqueid

@property
def available(self):
"""Return True if device is available."""
return self.gateway.available and self._device.reachable

@property
def name(self):
"""Return the name of the device."""
return self._device.name

@property
def should_poll(self):
"""No polling needed."""
return False

@property
def device_info(self):
"""Return a device description for device registry."""
if self._device.uniqueid is None or self._device.uniqueid.count(":") != 7:
return None

serial = self._device.uniqueid.split("-", 1)[0]
bridgeid = self.gateway.api.config.bridgeid

return {
"connections": {(CONNECTION_ZIGBEE, serial)},
"identifiers": {(DECONZ_DOMAIN, serial)},
"manufacturer": self._device.manufacturer,
"model": self._device.modelid,
"name": self._device.name,
"sw_version": self._device.swversion,
"via_device": (DECONZ_DOMAIN, bridgeid),
}
56 changes: 56 additions & 0 deletions homeassistant/components/deconz/deconz_event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""Representation of a deCONZ remote."""
from homeassistant.const import CONF_EVENT, CONF_ID
from homeassistant.core import callback
from homeassistant.util import slugify

from .const import _LOGGER
from .deconz_device import DeconzBase

CONF_DECONZ_EVENT = "deconz_event"
CONF_UNIQUE_ID = "unique_id"


class DeconzEvent(DeconzBase):
"""When you want signals instead of entities.

Stateless sensors such as remotes are expected to generate an event
instead of a sensor entity in hass.
"""

def __init__(self, device, gateway):
"""Register callback that will be used for signals."""
super().__init__(device, gateway)

self._device.register_async_callback(self.async_update_callback)

self.device_id = None
self.event_id = slugify(self._device.name)
_LOGGER.debug("deCONZ event created: %s", self.event_id)

@callback
def async_will_remove_from_hass(self) -> None:
"""Disconnect event object when removed."""
self._device.remove_callback(self.async_update_callback)
self._device = None

@callback
def async_update_callback(self, force_update=False):
"""Fire the event if reason is that state is updated."""
if "state" in self._device.changed_keys:
data = {
CONF_ID: self.event_id,
CONF_UNIQUE_ID: self.serial,
CONF_EVENT: self._device.state,
}
self.gateway.hass.bus.async_fire(CONF_DECONZ_EVENT, data)

async def async_update_device_registry(self):
"""Update device registry."""
device_registry = (
await self.gateway.hass.helpers.device_registry.async_get_registry()
)

entry = device_registry.async_get_or_create(
config_entry_id=self.gateway.config_entry.entry_id, **self.device_info
)
self.device_id = entry.id
Loading