[switch.pilight] Implement echo config option (#5056)

* Implement echo config option for pilight

Pilight switches can get a receive code configured. If so they act on
received codes. In the current implementation "act on" means not only
to set the internal state, but also to send the code again. If the
receiver is directly parred with the switch, to act even if HA is not
running, this causes it to receive the signal twice because the HA
sends it again.

In my case this causes a dimmer to start dimming until I hit the switch
again.

This implements a "echo" argument for the receive codes that let the
user choose if a received signal should result in any sending or not.
If not, only the status of pilight will be updated.

The echo option defaults to True, as this was the default since now.
Simply set it to halse to disable this behaviour.

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>

* Add documentation to set_state in switch/pilight.

Signed-off-by: Jan Losinski <losinski@wh2.tu-dresden.de>
This commit is contained in:
Jan Losinski 2017-01-27 07:40:14 +01:00 committed by Paulus Schoutsen
parent 837994196e
commit 41218e5a37

View File

@ -23,6 +23,7 @@ CONF_ON_CODE_RECIEVE = 'on_code_receive'
CONF_SYSTEMCODE = 'systemcode'
CONF_UNIT = 'unit'
CONF_UNITCODE = 'unitcode'
CONF_ECHO = 'echo'
DEPENDENCIES = ['pilight']
@ -37,6 +38,10 @@ COMMAND_SCHEMA = vol.Schema({
vol.Optional(CONF_SYSTEMCODE): cv.positive_int,
}, extra=vol.ALLOW_EXTRA)
RECEIVE_SCHEMA = COMMAND_SCHEMA.extend({
vol.Optional(CONF_ECHO): cv.boolean
})
SWITCHES_SCHEMA = vol.Schema({
vol.Required(CONF_ON_CODE): COMMAND_SCHEMA,
vol.Required(CONF_OFF_CODE): COMMAND_SCHEMA,
@ -73,6 +78,24 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
add_devices(devices)
class _ReceiveHandle(object):
def __init__(self, config, echo):
"""Initialize the handle."""
self.config_items = config.items()
self.echo = echo
def match(self, code):
"""Test if the received code matches the configured values.
The received values have to be a subset of the configured options.
"""
return self.config_items <= code.items()
def run(self, switch, turn_on):
"""Change the state of the switch."""
switch.set_state(turn_on=turn_on, send_code=self.echo)
class PilightSwitch(SwitchDevice):
"""Representation of a Pilight switch."""
@ -84,8 +107,15 @@ class PilightSwitch(SwitchDevice):
self._state = False
self._code_on = code_on
self._code_off = code_off
self._code_on_receive = code_on_receive
self._code_off_receive = code_off_receive
self._code_on_receive = []
self._code_off_receive = []
for code_list, conf in ((self._code_on_receive, code_on_receive),
(self._code_off_receive, code_off_receive)):
for code in conf:
echo = code.pop(CONF_ECHO, True)
code_list.append(_ReceiveHandle(code, echo))
if any(self._code_on_receive) or any(self._code_off_receive):
hass.bus.listen(pilight.EVENT, self._handle_code)
@ -116,26 +146,38 @@ class PilightSwitch(SwitchDevice):
# - Call turn on/off only once, even if more than one code is received
if any(self._code_on_receive):
for on_code in self._code_on_receive:
if on_code.items() <= call.data.items():
self.turn_on()
if on_code.match(call.data):
on_code.run(switch=self, turn_on=True)
break
if any(self._code_off_receive):
for off_code in self._code_off_receive:
if off_code.items() <= call.data.items():
self.turn_off()
if off_code.match(call.data):
off_code.run(switch=self, turn_on=False)
break
def set_state(self, turn_on, send_code=True):
"""Set the state of the switch.
This sets the state of the switch. If send_code is set to True, then
it will call the pilight.send service to actually send the codes
to the pilight daemon.
"""
if send_code:
if turn_on:
self._hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
self._code_on, blocking=True)
else:
self._hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
self._code_off, blocking=True)
self._state = turn_on
self.schedule_update_ha_state()
def turn_on(self):
"""Turn the switch on by calling pilight.send service with on code."""
self._hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
self._code_on, blocking=True)
self._state = True
self.schedule_update_ha_state()
self.set_state(turn_on=True)
def turn_off(self):
"""Turn the switch on by calling pilight.send service with off code."""
self._hass.services.call(pilight.DOMAIN, pilight.SERVICE_NAME,
self._code_off, blocking=True)
self._state = False
self.schedule_update_ha_state()
self.set_state(turn_on=False)