Fixed config migration issue

This commit is contained in:
Ron Klinkien
2025-11-04 17:37:40 +00:00
parent 79dec62b81
commit 8d00693332
2 changed files with 68 additions and 22 deletions

View File

@@ -15,10 +15,10 @@ from garminconnect import (
import requests import requests
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_TOKEN from homeassistant.const import CONF_ID, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from .const import ( from .const import (
DATA_COORDINATOR, DATA_COORDINATOR,
DAY_TO_NUMBER, DAY_TO_NUMBER,
@@ -33,6 +33,56 @@ _LOGGER = logging.getLogger(__name__)
PLATFORMS = ["sensor"] PLATFORMS = ["sensor"]
async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Migrate old config entry from username/password to token-based authentication."""
_LOGGER.debug(
"Migrating Garmin Connect config entry from version %s", entry.version)
if entry.version == 1:
# Check if we need to migrate (old entries have username/password, new ones have token)
if CONF_TOKEN not in entry.data and CONF_USERNAME in entry.data and CONF_PASSWORD in entry.data:
_LOGGER.info(
"Migrating Garmin Connect config entry to token-based authentication")
username = entry.data[CONF_USERNAME]
password = entry.data[CONF_PASSWORD]
# Determine if user is in China
in_china = hass.config.country == "CN"
# Create temporary API client to get token
api = Garmin(email=username, password=password, is_cn=in_china)
try:
# Login to get the token
await hass.async_add_executor_job(api.login)
# Get the OAuth tokens
tokens = api.garth.dumps()
# Create new data with token, keeping the ID
new_data = {
CONF_ID: entry.data.get(CONF_ID, username),
CONF_TOKEN: tokens,
}
# Update the config entry
hass.config_entries.async_update_entry(entry, data=new_data)
_LOGGER.info(
"Successfully migrated Garmin Connect config entry")
return True
except Exception as err: # pylint: disable=broad-except
_LOGGER.error(
"Failed to migrate Garmin Connect config entry. "
"Please re-add the integration. Error: %s", err
)
return False
return True
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Garmin Connect from a config entry.""" """Set up Garmin Connect from a config entry."""
@@ -102,7 +152,12 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
try: try:
# Check if the token exists in the entry data # Check if the token exists in the entry data
if CONF_TOKEN not in self.entry.data: if CONF_TOKEN not in self.entry.data:
raise KeyError("Token not found, migrating config entry") _LOGGER.error(
"Token not found in config entry. This may be an old config entry that needs migration. "
"Please remove and re-add the Garmin Connect integration."
)
raise ConfigEntryAuthFailed(
"Token not found, please re-add the integration")
await self.hass.async_add_executor_job(self.api.login, self.entry.data[CONF_TOKEN]) await self.hass.async_add_executor_job(self.api.login, self.entry.data[CONF_TOKEN])
except GarminConnectAuthenticationError as err: except GarminConnectAuthenticationError as err:
@@ -118,11 +173,6 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
"Connection error occurred during Garmin Connect login request: %s", err "Connection error occurred during Garmin Connect login request: %s", err
) )
raise ConfigEntryNotReady from err raise ConfigEntryNotReady from err
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Unknown error occurred during Garmin Connect login request"
)
raise ConfigEntryNotReady
except requests.exceptions.HTTPError as err: except requests.exceptions.HTTPError as err:
if err.response.status_code == 401: if err.response.status_code == 401:
_LOGGER.error( _LOGGER.error(
@@ -135,10 +185,6 @@ class GarminConnectDataUpdateCoordinator(DataUpdateCoordinator):
_LOGGER.error( _LOGGER.error(
"Unknown HTTP error occurred during login: %s", err) "Unknown HTTP error occurred during login: %s", err)
return False 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 except Exception as err: # pylint: disable=broad-except
_LOGGER.exception( _LOGGER.exception(
"Unknown error occurred during login: %s", err) "Unknown error occurred during login: %s", err)

View File

@@ -7,6 +7,6 @@
"documentation": "https://github.com/cyberjunky/home-assistant-garmin_connect", "documentation": "https://github.com/cyberjunky/home-assistant-garmin_connect",
"iot_class": "cloud_polling", "iot_class": "cloud_polling",
"issue_tracker": "https://github.com/cyberjunky/home-assistant-garmin_connect/issues", "issue_tracker": "https://github.com/cyberjunky/home-assistant-garmin_connect/issues",
"requirements": ["garminconnect>=0.2.31"], "requirements": ["garminconnect>=0.2.32"],
"version": "0.2.32" "version": "0.2.32"
} }