diff --git a/homeassistant/components/zerproc/config_flow.py b/homeassistant/components/zerproc/config_flow.py index 28597b3859e..6e3d70b0815 100644 --- a/homeassistant/components/zerproc/config_flow.py +++ b/homeassistant/components/zerproc/config_flow.py @@ -14,7 +14,7 @@ _LOGGER = logging.getLogger(__name__) async def _async_has_devices(hass) -> bool: """Return if there are devices that can be discovered.""" try: - devices = await hass.async_add_executor_job(pyzerproc.discover) + devices = await pyzerproc.discover() return len(devices) > 0 except pyzerproc.ZerprocException: _LOGGER.error("Unable to discover nearby Zerproc devices", exc_info=True) diff --git a/homeassistant/components/zerproc/light.py b/homeassistant/components/zerproc/light.py index b45ca4497a4..ed44f1aa728 100644 --- a/homeassistant/components/zerproc/light.py +++ b/homeassistant/components/zerproc/light.py @@ -28,25 +28,10 @@ SUPPORT_ZERPROC = SUPPORT_BRIGHTNESS | SUPPORT_COLOR DISCOVERY_INTERVAL = timedelta(seconds=60) -PARALLEL_UPDATES = 0 - -def connect_lights(lights: List[pyzerproc.Light]) -> List[pyzerproc.Light]: - """Attempt to connect to lights, and return the connected lights.""" - connected = [] - for light in lights: - try: - light.connect() - connected.append(light) - except pyzerproc.ZerprocException: - _LOGGER.debug("Unable to connect to '%s'", light.address, exc_info=True) - - return connected - - -def discover_entities(hass: HomeAssistant) -> List[Entity]: +async def discover_entities(hass: HomeAssistant) -> List[Entity]: """Attempt to discover new lights.""" - lights = pyzerproc.discover() + lights = await pyzerproc.discover() # Filter out already discovered lights new_lights = [ @@ -54,8 +39,13 @@ def discover_entities(hass: HomeAssistant) -> List[Entity]: ] entities = [] - for light in connect_lights(new_lights): - # Double-check the light hasn't been added in another thread + for light in new_lights: + try: + await light.connect() + except pyzerproc.ZerprocException: + _LOGGER.debug("Unable to connect to '%s'", light.address, exc_info=True) + continue + # Double-check the light hasn't been added in the meantime if light.address not in hass.data[DOMAIN]["addresses"]: hass.data[DOMAIN]["addresses"].add(light.address) entities.append(ZerprocLight(light)) @@ -68,7 +58,7 @@ async def async_setup_entry( config_entry: ConfigEntry, async_add_entities: Callable[[List[Entity], bool], None], ) -> None: - """Set up Abode light devices.""" + """Set up Zerproc light devices.""" if DOMAIN not in hass.data: hass.data[DOMAIN] = {} if "addresses" not in hass.data[DOMAIN]: @@ -80,7 +70,7 @@ async def async_setup_entry( """Wrap discovery to include params.""" nonlocal warned try: - entities = await hass.async_add_executor_job(discover_entities, hass) + entities = await discover_entities(hass) async_add_entities(entities, update_before_add=True) warned = False except pyzerproc.ZerprocException: @@ -117,11 +107,11 @@ class ZerprocLight(LightEntity): async def async_will_remove_from_hass(self) -> None: """Run when entity will be removed from hass.""" - await self.hass.async_add_executor_job(self._light.disconnect) + await self._light.disconnect() - def on_hass_shutdown(self, event): + async def on_hass_shutdown(self, event): """Execute when Home Assistant is shutting down.""" - self._light.disconnect() + await self._light.disconnect() @property def name(self): @@ -172,7 +162,7 @@ class ZerprocLight(LightEntity): """Return True if entity is available.""" return self._available - def turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs): """Instruct the light to turn on.""" if ATTR_BRIGHTNESS in kwargs or ATTR_HS_COLOR in kwargs: default_hs = (0, 0) if self._hs_color is None else self._hs_color @@ -182,20 +172,20 @@ class ZerprocLight(LightEntity): brightness = kwargs.get(ATTR_BRIGHTNESS, default_brightness) rgb = color_util.color_hsv_to_RGB(*hue_sat, brightness / 255 * 100) - self._light.set_color(*rgb) + await self._light.set_color(*rgb) else: - self._light.turn_on() + await self._light.turn_on() - def turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Instruct the light to turn off.""" - self._light.turn_off() + await self._light.turn_off() - def update(self): + async def async_update(self): """Fetch new state data for this light.""" try: - if not self._light.connected: - self._light.connect() - state = self._light.get_state() + if not await self._light.is_connected(): + await self._light.connect() + state = await self._light.get_state() except pyzerproc.ZerprocException: if self._available: _LOGGER.warning("Unable to connect to %s", self.entity_id) diff --git a/homeassistant/components/zerproc/manifest.json b/homeassistant/components/zerproc/manifest.json index 344ea569104..d5a61fd18ae 100644 --- a/homeassistant/components/zerproc/manifest.json +++ b/homeassistant/components/zerproc/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/zerproc", "requirements": [ - "pyzerproc==0.3.0" + "pyzerproc==0.4.3" ], "codeowners": [ "@emlove" diff --git a/requirements_all.txt b/requirements_all.txt index 411b7825773..91c5de815b9 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1904,7 +1904,7 @@ pyxeoma==1.4.1 pyzbar==0.1.7 # homeassistant.components.zerproc -pyzerproc==0.3.0 +pyzerproc==0.4.3 # homeassistant.components.qnap qnapstats==0.3.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e22f5503fc6..1e9eb6842ad 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -939,7 +939,7 @@ pywemo==0.5.3 pywilight==0.0.65 # homeassistant.components.zerproc -pyzerproc==0.3.0 +pyzerproc==0.4.3 # homeassistant.components.rachio rachiopy==1.0.3 diff --git a/tests/components/zerproc/test_light.py b/tests/components/zerproc/test_light.py index 14756f1183c..3649c954b52 100644 --- a/tests/components/zerproc/test_light.py +++ b/tests/components/zerproc/test_light.py @@ -44,7 +44,7 @@ async def mock_light(hass, mock_entry): light = MagicMock(spec=pyzerproc.Light) light.address = "AA:BB:CC:DD:EE:FF" light.name = "LEDBlue-CCDDEEFF" - light.connected = False + light.is_connected.return_value = False mock_state = pyzerproc.LightState(False, (0, 0, 0)) @@ -57,7 +57,7 @@ async def mock_light(hass, mock_entry): await hass.config_entries.async_setup(mock_entry.entry_id) await hass.async_block_till_done() - light.connected = True + light.is_connected.return_value = True return light @@ -71,12 +71,12 @@ async def test_init(hass, mock_entry): mock_light_1 = MagicMock(spec=pyzerproc.Light) mock_light_1.address = "AA:BB:CC:DD:EE:FF" mock_light_1.name = "LEDBlue-CCDDEEFF" - mock_light_1.connected = True + mock_light_1.is_connected.return_value = True mock_light_2 = MagicMock(spec=pyzerproc.Light) mock_light_2.address = "11:22:33:44:55:66" mock_light_2.name = "LEDBlue-33445566" - mock_light_2.connected = True + mock_light_2.is_connected.return_value = True mock_state_1 = pyzerproc.LightState(False, (0, 0, 0)) mock_state_2 = pyzerproc.LightState(True, (0, 80, 255)) @@ -144,7 +144,7 @@ async def test_connect_exception(hass, mock_entry): mock_light = MagicMock(spec=pyzerproc.Light) mock_light.address = "AA:BB:CC:DD:EE:FF" mock_light.name = "LEDBlue-CCDDEEFF" - mock_light.connected = False + mock_light.is_connected.return_value = False with patch( "homeassistant.components.zerproc.light.pyzerproc.discover",