Migrate from old config flow to new config flow

Catch authentication errors and show them in the UI
Limit last activity to 5 in attributes
This commit is contained in:
Ron Klinkien
2025-04-19 10:38:01 +00:00
parent 84ad53891b
commit 9cf1b3a3bb
6 changed files with 27 additions and 20 deletions

View File

@@ -15,9 +15,9 @@ from garminconnect import (
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
import binascii
from .const import (
DATA_COORDINATOR,
DAY_TO_NUMBER,
@@ -84,11 +84,15 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
async def async_login(self) -> bool:
"""Login to Garmin Connect."""
try:
# Check if the token exists in the entry data
if CONF_TOKEN not in self.entry.data:
raise KeyError("Token not found, migrating config entry")
await self.hass.async_add_executor_job(self.api.login, self.entry.data[CONF_TOKEN])
except GarminConnectAuthenticationError as err:
_LOGGER.error(
"Authentication error occurred during login: %s", err.response.text)
return False
raise ConfigEntryAuthFailed from err
except GarminConnectTooManyRequestsError as err:
_LOGGER.error(
"Too many request error occurred during login: %s", err)
@@ -101,7 +105,7 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
if err.response.status_code == 401:
_LOGGER.error(
"Authentication error occurred during login: %s", err.response.text)
return False
raise ConfigEntryAuthFailed from err
if err.response.status_code == 429:
_LOGGER.error(
"Too many requests error occurred during login: %s", err.response.text)
@@ -109,6 +113,10 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
_LOGGER.error(
"Unknown HTTP error occurred during login: %s", err)
return False
except KeyError as err:
_LOGGER.error(
"Found old config during login: %s", err)
raise ConfigEntryAuthFailed from err
except Exception as err: # pylint: disable=broad-except
_LOGGER.exception(
"Unknown error occurred during login: %s", err)
@@ -254,7 +262,7 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
except GarminConnectAuthenticationError as err:
_LOGGER.error(
"Authentication error occurred during update: %s", err.response.text)
return False
raise ConfigEntryAuthFailed from err
except GarminConnectTooManyRequestsError as err:
_LOGGER.error(
"Too many request error occurred during update: %s", err)
@@ -267,7 +275,7 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
if err.response.status_code == 401:
_LOGGER.error(
"Authentication error occurred during update: %s", err.response.text)
return False
raise ConfigEntryAuthFailed from err
if err.response.status_code == 429:
_LOGGER.error(
"Too many requests error occurred during update: %s", err.response.text)

View File

@@ -13,6 +13,7 @@ from garminconnect import (
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
from homeassistant.const import CONF_ID, CONF_TOKEN, CONF_PASSWORD, CONF_USERNAME
import voluptuous as vol
import garth
from .const import CONF_MFA, DOMAIN
@@ -57,8 +58,6 @@ class GarminConnectConfigFlowHandler(ConfigFlow, domain=DOMAIN):
try:
self._login_result1, self._login_result2 = await self.hass.async_add_executor_job(self._api.login)
_LOGGER.debug(f"Login result1: {self._login_result1}")
_LOGGER.debug(f"Login result2: {self._login_result2}")
if self._login_result1 == "needs_mfa": # MFA is required
return await self.async_step_mfa()
@@ -89,12 +88,10 @@ class GarminConnectConfigFlowHandler(ConfigFlow, domain=DOMAIN):
async def _async_garmin_connect_mfa_login(self) -> ConfigFlowResult:
"""Handle multi-factor authentication (MFA) login with Garmin Connect."""
try:
await self.hass.async_add_executor_job(self._api.resume_login, self._login_result2, self._mfa_code)
oauth1, oauth2 = await self.hass.async_add_executor_job(self._api.resume_login, self._login_result2, self._mfa_code)
_LOGGER.info(f"Oauth1: {oauth1}, Oauth2: {oauth2}")
except GarminConnectAuthenticationError:
except garth.exc.GarthException as err:
_LOGGER.error(f"Error during MFA login: {err}")
return self.async_show_form(
step_id="mfa",
data_schema=vol.Schema(self.mfa_data_schema),

View File

@@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/cyberjunky/home-assistant-garmin_connect/issues",
"requirements": ["garminconnect>=0.2.26"],
"version": "0.2.31-beta-03"
"version": "0.2.31-beta-04"
}

View File

@@ -244,7 +244,7 @@ class GarminConnectSensor(CoordinatorEntity, SensorEntity):
activities = self.coordinator.data.get(self._type, [])
sorted_activities = sorted(
activities, key=lambda x: x["activityId"])
attributes["last_activities"] = sorted_activities[-10:]
attributes["last_activities"] = sorted_activities[-5:]
if self._type == "lastActivity":
attributes = {**attributes, **self.coordinator.data[self._type]}

View File

@@ -25,7 +25,7 @@
"error": {
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]",
"too_many_requests": "Too many requests, retry later.",
"too_many_requests": "Too many requests, retry later",
"unknown": "[%key:common::config_flow::error::unknown%]",
"invalid_mfa_code": "Invalid MFA code"
},

View File

@@ -24,13 +24,15 @@
}
},
"abort": {
"already_configured": "Account is already configured"
"already_configured": "Account is already configured",
"reauth_successful": "Reauthentication successful"
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_auth": "Invalid authentication",
"too_many_requests": "Too many requests, retry later.",
"unknown": "Unexpected error"
"too_many_requests": "Too many requests, retry later",
"unknown": "Unexpected error",
"invalid_mfa_code": "Invalid MFA code"
}
}
}