Convert zerproc to use new upstream async api (#44357)
This commit is contained in:
parent
896f51fd82
commit
9de393d116
6 changed files with 32 additions and 42 deletions
|
@ -14,7 +14,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
async def _async_has_devices(hass) -> bool:
|
async def _async_has_devices(hass) -> bool:
|
||||||
"""Return if there are devices that can be discovered."""
|
"""Return if there are devices that can be discovered."""
|
||||||
try:
|
try:
|
||||||
devices = await hass.async_add_executor_job(pyzerproc.discover)
|
devices = await pyzerproc.discover()
|
||||||
return len(devices) > 0
|
return len(devices) > 0
|
||||||
except pyzerproc.ZerprocException:
|
except pyzerproc.ZerprocException:
|
||||||
_LOGGER.error("Unable to discover nearby Zerproc devices", exc_info=True)
|
_LOGGER.error("Unable to discover nearby Zerproc devices", exc_info=True)
|
||||||
|
|
|
@ -28,25 +28,10 @@ SUPPORT_ZERPROC = SUPPORT_BRIGHTNESS | SUPPORT_COLOR
|
||||||
|
|
||||||
DISCOVERY_INTERVAL = timedelta(seconds=60)
|
DISCOVERY_INTERVAL = timedelta(seconds=60)
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
|
||||||
|
|
||||||
|
async def discover_entities(hass: HomeAssistant) -> List[Entity]:
|
||||||
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]:
|
|
||||||
"""Attempt to discover new lights."""
|
"""Attempt to discover new lights."""
|
||||||
lights = pyzerproc.discover()
|
lights = await pyzerproc.discover()
|
||||||
|
|
||||||
# Filter out already discovered lights
|
# Filter out already discovered lights
|
||||||
new_lights = [
|
new_lights = [
|
||||||
|
@ -54,8 +39,13 @@ def discover_entities(hass: HomeAssistant) -> List[Entity]:
|
||||||
]
|
]
|
||||||
|
|
||||||
entities = []
|
entities = []
|
||||||
for light in connect_lights(new_lights):
|
for light in new_lights:
|
||||||
# Double-check the light hasn't been added in another thread
|
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"]:
|
if light.address not in hass.data[DOMAIN]["addresses"]:
|
||||||
hass.data[DOMAIN]["addresses"].add(light.address)
|
hass.data[DOMAIN]["addresses"].add(light.address)
|
||||||
entities.append(ZerprocLight(light))
|
entities.append(ZerprocLight(light))
|
||||||
|
@ -68,7 +58,7 @@ async def async_setup_entry(
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[List[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up Abode light devices."""
|
"""Set up Zerproc light devices."""
|
||||||
if DOMAIN not in hass.data:
|
if DOMAIN not in hass.data:
|
||||||
hass.data[DOMAIN] = {}
|
hass.data[DOMAIN] = {}
|
||||||
if "addresses" not in hass.data[DOMAIN]:
|
if "addresses" not in hass.data[DOMAIN]:
|
||||||
|
@ -80,7 +70,7 @@ async def async_setup_entry(
|
||||||
"""Wrap discovery to include params."""
|
"""Wrap discovery to include params."""
|
||||||
nonlocal warned
|
nonlocal warned
|
||||||
try:
|
try:
|
||||||
entities = await hass.async_add_executor_job(discover_entities, hass)
|
entities = await discover_entities(hass)
|
||||||
async_add_entities(entities, update_before_add=True)
|
async_add_entities(entities, update_before_add=True)
|
||||||
warned = False
|
warned = False
|
||||||
except pyzerproc.ZerprocException:
|
except pyzerproc.ZerprocException:
|
||||||
|
@ -117,11 +107,11 @@ class ZerprocLight(LightEntity):
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
"""Run when entity will be removed from hass."""
|
"""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."""
|
"""Execute when Home Assistant is shutting down."""
|
||||||
self._light.disconnect()
|
await self._light.disconnect()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -172,7 +162,7 @@ class ZerprocLight(LightEntity):
|
||||||
"""Return True if entity is available."""
|
"""Return True if entity is available."""
|
||||||
return self._available
|
return self._available
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
async def async_turn_on(self, **kwargs):
|
||||||
"""Instruct the light to turn on."""
|
"""Instruct the light to turn on."""
|
||||||
if ATTR_BRIGHTNESS in kwargs or ATTR_HS_COLOR in kwargs:
|
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
|
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)
|
brightness = kwargs.get(ATTR_BRIGHTNESS, default_brightness)
|
||||||
|
|
||||||
rgb = color_util.color_hsv_to_RGB(*hue_sat, brightness / 255 * 100)
|
rgb = color_util.color_hsv_to_RGB(*hue_sat, brightness / 255 * 100)
|
||||||
self._light.set_color(*rgb)
|
await self._light.set_color(*rgb)
|
||||||
else:
|
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."""
|
"""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."""
|
"""Fetch new state data for this light."""
|
||||||
try:
|
try:
|
||||||
if not self._light.connected:
|
if not await self._light.is_connected():
|
||||||
self._light.connect()
|
await self._light.connect()
|
||||||
state = self._light.get_state()
|
state = await self._light.get_state()
|
||||||
except pyzerproc.ZerprocException:
|
except pyzerproc.ZerprocException:
|
||||||
if self._available:
|
if self._available:
|
||||||
_LOGGER.warning("Unable to connect to %s", self.entity_id)
|
_LOGGER.warning("Unable to connect to %s", self.entity_id)
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/zerproc",
|
"documentation": "https://www.home-assistant.io/integrations/zerproc",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pyzerproc==0.3.0"
|
"pyzerproc==0.4.3"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@emlove"
|
"@emlove"
|
||||||
|
|
|
@ -1904,7 +1904,7 @@ pyxeoma==1.4.1
|
||||||
pyzbar==0.1.7
|
pyzbar==0.1.7
|
||||||
|
|
||||||
# homeassistant.components.zerproc
|
# homeassistant.components.zerproc
|
||||||
pyzerproc==0.3.0
|
pyzerproc==0.4.3
|
||||||
|
|
||||||
# homeassistant.components.qnap
|
# homeassistant.components.qnap
|
||||||
qnapstats==0.3.0
|
qnapstats==0.3.0
|
||||||
|
|
|
@ -939,7 +939,7 @@ pywemo==0.5.3
|
||||||
pywilight==0.0.65
|
pywilight==0.0.65
|
||||||
|
|
||||||
# homeassistant.components.zerproc
|
# homeassistant.components.zerproc
|
||||||
pyzerproc==0.3.0
|
pyzerproc==0.4.3
|
||||||
|
|
||||||
# homeassistant.components.rachio
|
# homeassistant.components.rachio
|
||||||
rachiopy==1.0.3
|
rachiopy==1.0.3
|
||||||
|
|
|
@ -44,7 +44,7 @@ async def mock_light(hass, mock_entry):
|
||||||
light = MagicMock(spec=pyzerproc.Light)
|
light = MagicMock(spec=pyzerproc.Light)
|
||||||
light.address = "AA:BB:CC:DD:EE:FF"
|
light.address = "AA:BB:CC:DD:EE:FF"
|
||||||
light.name = "LEDBlue-CCDDEEFF"
|
light.name = "LEDBlue-CCDDEEFF"
|
||||||
light.connected = False
|
light.is_connected.return_value = False
|
||||||
|
|
||||||
mock_state = pyzerproc.LightState(False, (0, 0, 0))
|
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.config_entries.async_setup(mock_entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
light.connected = True
|
light.is_connected.return_value = True
|
||||||
|
|
||||||
return light
|
return light
|
||||||
|
|
||||||
|
@ -71,12 +71,12 @@ async def test_init(hass, mock_entry):
|
||||||
mock_light_1 = MagicMock(spec=pyzerproc.Light)
|
mock_light_1 = MagicMock(spec=pyzerproc.Light)
|
||||||
mock_light_1.address = "AA:BB:CC:DD:EE:FF"
|
mock_light_1.address = "AA:BB:CC:DD:EE:FF"
|
||||||
mock_light_1.name = "LEDBlue-CCDDEEFF"
|
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 = MagicMock(spec=pyzerproc.Light)
|
||||||
mock_light_2.address = "11:22:33:44:55:66"
|
mock_light_2.address = "11:22:33:44:55:66"
|
||||||
mock_light_2.name = "LEDBlue-33445566"
|
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_1 = pyzerproc.LightState(False, (0, 0, 0))
|
||||||
mock_state_2 = pyzerproc.LightState(True, (0, 80, 255))
|
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 = MagicMock(spec=pyzerproc.Light)
|
||||||
mock_light.address = "AA:BB:CC:DD:EE:FF"
|
mock_light.address = "AA:BB:CC:DD:EE:FF"
|
||||||
mock_light.name = "LEDBlue-CCDDEEFF"
|
mock_light.name = "LEDBlue-CCDDEEFF"
|
||||||
mock_light.connected = False
|
mock_light.is_connected.return_value = False
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.zerproc.light.pyzerproc.discover",
|
"homeassistant.components.zerproc.light.pyzerproc.discover",
|
||||||
|
|
Loading…
Add table
Reference in a new issue