Skip to content

Commit

Permalink
husqvarna_automower_ble: Try to be more robust against drop outs
Browse files Browse the repository at this point in the history
Signed-off-by: Alistair Francis <alistair@alistair23.me>
  • Loading branch information
alistair23 committed Mar 25, 2024
1 parent 7c0c9f6 commit 311df40
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 17 deletions.
13 changes: 9 additions & 4 deletions homeassistant/components/husqvarna_automower_ble/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging

from automower_ble.mower import Mower
from bleak_retry_connector import close_stale_connections_by_address, get_device

from homeassistant.components import bluetooth
from homeassistant.config_entries import ConfigEntry
Expand All @@ -28,14 +29,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

mower = Mower(channel_id, address)

LOGGER.debug("connecting to " + address + " with channel ID " + str(channel_id))
device = bluetooth.async_ble_device_from_address(hass, address, connectable=True)
if await mower.connect(device) == False:
await close_stale_connections_by_address(address)

LOGGER.debug("connecting to %s with channel ID %s", address, str(channel_id))
device = bluetooth.async_ble_device_from_address(
hass, address, connectable=True
) or await get_device(address)
if not await mower.connect(device):
return False
LOGGER.debug("connected and paired")

model = await mower.get_model()
LOGGER.info("Connected to Automower: " + model)
LOGGER.info("Connected to Automower: %s", model)

device_info = DeviceInfo(
identifiers={(DOMAIN, str(address) + str(channel_id))},
Expand Down
56 changes: 43 additions & 13 deletions homeassistant/components/husqvarna_automower_ble/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@
from typing import Any

from automower_ble.mower import Mower
from bleak import BleakError
from bleak_retry_connector import close_stale_connections_by_address

from homeassistant.components import bluetooth
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
UpdateFailed,
)

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -51,25 +54,52 @@ async def async_shutdown(self) -> None:
if self.mower.is_connected():
await self.mower.disconnect()

async def _async_find_device(self):
_LOGGER.debug("Trying to reconnect")
await close_stale_connections_by_address(self.address)

device = bluetooth.async_ble_device_from_address(
self.hass, self.address, connectable=True
)
if not device:
_LOGGER.error("Can't find device")
raise UpdateFailed("Can't find device")

if not await self.mower.connect(device):
raise UpdateFailed("Failed to connect")

async def _async_update_data(self) -> dict[str, bytes]:
"""Poll the device."""
_LOGGER.debug("Polling device")

data: dict[str, bytes] = {}

if await self.mower.is_connected():
device = bluetooth.async_ble_device_from_address(
self.hass, self.address, connectable=True
)
if await self.mower.connect(device) == False:
return

data["battery_level"] = await self.mower.battery_level()
_LOGGER.debug(data["battery_level"])
data["activity"] = await self.mower.mower_activity()
_LOGGER.debug(data["activity"])
data["state"] = await self.mower.mower_state()
_LOGGER.debug(data["state"])
if not self.mower.is_connected():
await self._async_find_device()

try:
data["battery_level"] = await self.mower.battery_level()
_LOGGER.debug(data["battery_level"])
if data["battery_level"] is None:
await self._async_find_device()
raise UpdateFailed("Error getting data from device")

data["activity"] = await self.mower.mower_activity()
_LOGGER.debug(data["activity"])
if data["activity"] is None:
await self._async_find_device()
raise UpdateFailed("Error getting data from device")

data["state"] = await self.mower.mower_state()
_LOGGER.debug(data["state"])
if data["state"] is None:
await self._async_find_device()
raise UpdateFailed("Error getting data from device")

except BleakError as err:
_LOGGER.error("Error getting data from device")
await self._async_find_device()
raise UpdateFailed("Error getting data from device") from err

return data

Expand Down

0 comments on commit 311df40

Please sign in to comment.