Rflink: added support for lights with toggle type (#6521)
* added support for lights with toggle type
* fixed style errors
* introduced tests for the toggle type
it's not passing yet because of an assertionerror at line 407
* updated to reflect tristate of "state"
* Format code according to pep8
Added line break for import that was too long.
* fixed lint, replaced if statement with 'var = bool(test)'
* changed implementation of state check according to bug on 6bceb04ca1 (r106758784)
pull/6686/head
parent
4e91c65d6e
commit
678f273002
|
@ -14,8 +14,8 @@ from homeassistant.components.rflink import (
|
|||
CONF_IGNORE_DEVICES, CONF_SIGNAL_REPETITIONS, DATA_DEVICE_REGISTER,
|
||||
DATA_ENTITY_LOOKUP, DEVICE_DEFAULTS_SCHEMA, DOMAIN,
|
||||
EVENT_KEY_COMMAND, EVENT_KEY_ID, SwitchableRflinkDevice, cv, vol)
|
||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM, CONF_TYPE
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_NAME, CONF_PLATFORM, CONF_TYPE, STATE_UNKNOWN)
|
||||
DEPENDENCIES = ['rflink']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -23,6 +23,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||
TYPE_DIMMABLE = 'dimmable'
|
||||
TYPE_SWITCHABLE = 'switchable'
|
||||
TYPE_HYBRID = 'hybrid'
|
||||
TYPE_TOGGLE = 'toggle'
|
||||
|
||||
PLATFORM_SCHEMA = vol.Schema({
|
||||
vol.Required(CONF_PLATFORM): DOMAIN,
|
||||
|
@ -33,7 +34,8 @@ PLATFORM_SCHEMA = vol.Schema({
|
|||
cv.string: {
|
||||
vol.Optional(CONF_NAME): cv.string,
|
||||
vol.Optional(CONF_TYPE):
|
||||
vol.Any(TYPE_DIMMABLE, TYPE_SWITCHABLE, TYPE_HYBRID),
|
||||
vol.Any(TYPE_DIMMABLE, TYPE_SWITCHABLE,
|
||||
TYPE_HYBRID, TYPE_TOGGLE),
|
||||
vol.Optional(CONF_ALIASSES, default=[]):
|
||||
vol.All(cv.ensure_list, [cv.string]),
|
||||
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
||||
|
@ -71,6 +73,9 @@ def entity_class_for_type(entity_type):
|
|||
# sends 'dim' and 'on' command to support both dimmers and on/off
|
||||
# switches. Not compatible with signal repetition.
|
||||
TYPE_HYBRID: HybridRflinkLight,
|
||||
# sends only 'on' commands for switches which turn on and off
|
||||
# using the same 'on' command for both.
|
||||
TYPE_TOGGLE: ToggleRflinkLight,
|
||||
}
|
||||
|
||||
return entity_device_mapping.get(entity_type, RflinkLight)
|
||||
|
@ -213,3 +218,38 @@ class HybridRflinkLight(SwitchableRflinkDevice, Light):
|
|||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_BRIGHTNESS
|
||||
|
||||
|
||||
class ToggleRflinkLight(SwitchableRflinkDevice, Light):
|
||||
"""Rflink light device which sends out only 'on' commands.
|
||||
|
||||
Some switches like for example Livolo light switches use the
|
||||
same 'on' command to switch on and switch off the lights.
|
||||
If the light is on and 'on' gets sent, the light will turn off
|
||||
and if the light is off and 'on' gets sent, the light will turn on.
|
||||
"""
|
||||
|
||||
@property
|
||||
def entity_id(self):
|
||||
"""Return entity id."""
|
||||
return "light.{}".format(self.name)
|
||||
|
||||
def _handle_event(self, event):
|
||||
"""Adjust state if Rflink picks up a remote command for this device."""
|
||||
self.cancel_queued_send_commands()
|
||||
|
||||
command = event['command']
|
||||
if command == 'on':
|
||||
# if the state is unknown or false, it gets set as true
|
||||
# if the state is true, it gets set as false
|
||||
self._state = self._state in [STATE_UNKNOWN, False]
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
yield from self._async_handle_command('toggle')
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_turn_off(self, **kwargs):
|
||||
"""Turn the device off."""
|
||||
yield from self._async_handle_command('toggle')
|
||||
|
|
|
@ -316,6 +316,12 @@ class RflinkCommand(RflinkDevice):
|
|||
cmd = str(int(args[0] / 17))
|
||||
self._state = True
|
||||
|
||||
elif command == 'toggle':
|
||||
cmd = 'on'
|
||||
# if the state is unknown or false, it gets set as true
|
||||
# if the state is true, it gets set as false
|
||||
self._state = self._state in [STATE_UNKNOWN, False]
|
||||
|
||||
# Send initial command and queue repetitions.
|
||||
# This allows the entity state to be updated quickly and not having to
|
||||
# wait for all repetitions to be sent
|
||||
|
|
|
@ -342,3 +342,46 @@ def test_signal_repetitions_cancelling(hass, monkeypatch):
|
|||
assert protocol.send_command_ack.call_args_list[1][0][1] == 'on'
|
||||
assert protocol.send_command_ack.call_args_list[2][0][1] == 'on'
|
||||
assert protocol.send_command_ack.call_args_list[3][0][1] == 'on'
|
||||
|
||||
|
||||
@asyncio.coroutine
|
||||
def test_type_toggle(hass, monkeypatch):
|
||||
"""Test toggle type lights (on/on)."""
|
||||
config = {
|
||||
'rflink': {
|
||||
'port': '/dev/ttyABC0',
|
||||
},
|
||||
DOMAIN: {
|
||||
'platform': 'rflink',
|
||||
'devices': {
|
||||
'toggle_0_0': {
|
||||
'name': 'toggle_test',
|
||||
'type': 'toggle',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
# setup mocking rflink module
|
||||
event_callback, _, _, _ = yield from mock_rflink(
|
||||
hass, config, DOMAIN, monkeypatch)
|
||||
|
||||
assert hass.states.get('light.toggle_test').state == 'off'
|
||||
|
||||
# test sending on command to toggle alias
|
||||
event_callback({
|
||||
'id': 'toggle_0_0',
|
||||
'command': 'on',
|
||||
})
|
||||
yield from hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get('light.toggle_test').state == 'on'
|
||||
|
||||
# test sending group command to group alias
|
||||
event_callback({
|
||||
'id': 'toggle_0_0',
|
||||
'command': 'on',
|
||||
})
|
||||
yield from hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get('light.toggle_test').state == 'off'
|
||||
|
|
Loading…
Reference in New Issue