From 2ba9d825a074f50bd9a12185633805b12cb64c4c Mon Sep 17 00:00:00 2001 From: Alex Osadchyy <21959540+aosadchyy@users.noreply.github.com> Date: Sun, 7 Jan 2018 23:32:24 -0800 Subject: [PATCH] Reconnect before mochad switch send command (#11296) * Connection to mochad occasionally stalls on RPi and CM19A. Reconnect one switch send command. * Formatting and exception hanling fixes * Moved import inside the method. Logging outside the try-catch. * Tailing whitespaces. * MockDependency on pymochad in unit tests to resolve exceptions * patch pymochad MochadException in unit tests to resolve exceptions * patch pymochad MochadException in unit tests to resolve exceptions * cleaned unused import * lint issue fixed * pylint issue fixed --- homeassistant/components/switch/mochad.py | 39 +++++++++++++++++++---- tests/components/switch/test_mochad.py | 1 + 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/switch/mochad.py b/homeassistant/components/switch/mochad.py index da8f96dc1f0..f80784271c2 100644 --- a/homeassistant/components/switch/mochad.py +++ b/homeassistant/components/switch/mochad.py @@ -50,7 +50,12 @@ class MochadSwitch(SwitchDevice): self._comm_type = dev.get(mochad.CONF_COMM_TYPE, 'pl') self.device = device.Device(ctrl, self._address, comm_type=self._comm_type) - self._state = self._get_device_status() + # Init with false to avoid locking HA for long on CM19A (goes from rf + # to pl via TM751, but not other way around) + if self._comm_type == 'pl': + self._state = self._get_device_status() + else: + self._state = False @property def name(self): @@ -59,17 +64,37 @@ class MochadSwitch(SwitchDevice): def turn_on(self, **kwargs): """Turn the switch on.""" - self._state = True + from pymochad.exceptions import MochadException + _LOGGER.debug("Reconnect %s:%s", self._controller.server, + self._controller.port) with mochad.REQ_LOCK: - self.device.send_cmd('on') - self._controller.read_data() + try: + # Recycle socket on new command to recover mochad connection + self._controller.reconnect() + self.device.send_cmd('on') + # No read data on CM19A which is rf only + if self._comm_type == 'pl': + self._controller.read_data() + self._state = True + except (MochadException, OSError) as exc: + _LOGGER.error("Error with mochad communication: %s", exc) def turn_off(self, **kwargs): """Turn the switch off.""" - self._state = False + from pymochad.exceptions import MochadException + _LOGGER.debug("Reconnect %s:%s", self._controller.server, + self._controller.port) with mochad.REQ_LOCK: - self.device.send_cmd('off') - self._controller.read_data() + try: + # Recycle socket on new command to recover mochad connection + self._controller.reconnect() + self.device.send_cmd('off') + # No read data on CM19A which is rf only + if self._comm_type == 'pl': + self._controller.read_data() + self._state = False + except (MochadException, OSError) as exc: + _LOGGER.error("Error with mochad communication: %s", exc) def _get_device_status(self): """Get the status of the switch from mochad.""" diff --git a/tests/components/switch/test_mochad.py b/tests/components/switch/test_mochad.py index 8011d85860e..a5e6e2c9ae6 100644 --- a/tests/components/switch/test_mochad.py +++ b/tests/components/switch/test_mochad.py @@ -16,6 +16,7 @@ def pymochad_mock(): """Mock pymochad.""" with mock.patch.dict('sys.modules', { 'pymochad': mock.MagicMock(), + 'pymochad.exceptions': mock.MagicMock(), }): yield