From cf612c3d5bf6c47f8a1da7b26316549996f92f06 Mon Sep 17 00:00:00 2001 From: Ulrich Dobramysl <1979498+ulido@users.noreply.github.com> Date: Thu, 11 Jan 2018 12:47:05 +0000 Subject: [PATCH] Make the rpi_rf component thread-safe using an RLock (#11487) * Make the rpi_rf component thread-safe The previous implementation suffered from race conditions when two rpi_rf switches are triggered at the same time. This implementation uses an RLock to give one thread at a time exclusive access to the rfdevice object. * cleanup * fix lint --- homeassistant/components/switch/rpi_rf.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/homeassistant/components/switch/rpi_rf.py b/homeassistant/components/switch/rpi_rf.py index e48ac1a4d7d..94a61314d1d 100644 --- a/homeassistant/components/switch/rpi_rf.py +++ b/homeassistant/components/switch/rpi_rf.py @@ -48,18 +48,20 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ def setup_platform(hass, config, add_devices, discovery_info=None): """Find and return switches controlled by a generic RF device via GPIO.""" import rpi_rf + from threading import RLock gpio = config.get(CONF_GPIO) rfdevice = rpi_rf.RFDevice(gpio) + rfdevice_lock = RLock() switches = config.get(CONF_SWITCHES) devices = [] for dev_name, properties in switches.items(): devices.append( RPiRFSwitch( - hass, properties.get(CONF_NAME, dev_name), rfdevice, + rfdevice_lock, properties.get(CONF_PROTOCOL), properties.get(CONF_PULSELENGTH), properties.get(CONF_SIGNAL_REPETITIONS), @@ -79,13 +81,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class RPiRFSwitch(SwitchDevice): """Representation of a GPIO RF switch.""" - def __init__(self, hass, name, rfdevice, protocol, pulselength, + def __init__(self, name, rfdevice, lock, protocol, pulselength, signal_repetitions, code_on, code_off): """Initialize the switch.""" - self._hass = hass self._name = name self._state = False self._rfdevice = rfdevice + self._lock = lock self._protocol = protocol self._pulselength = pulselength self._code_on = code_on @@ -109,9 +111,10 @@ class RPiRFSwitch(SwitchDevice): def _send_code(self, code_list, protocol, pulselength): """Send the code(s) with a specified pulselength.""" - _LOGGER.info("Sending code(s): %s", code_list) - for code in code_list: - self._rfdevice.tx_code(code, protocol, pulselength) + with self._lock: + _LOGGER.info("Sending code(s): %s", code_list) + for code in code_list: + self._rfdevice.tx_code(code, protocol, pulselength) return True def turn_on(self):