Skip to content

Commit

Permalink
Merge pull request #30 from RobertD502/api_fix
Browse files Browse the repository at this point in the history
Fix for EU API changes PetKit introduced
  • Loading branch information
RobertD502 authored Aug 3, 2023
2 parents 805a6f5 + 7873872 commit b20bc5d
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 89 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ ___

- **This integration requires using your PetKit account `email` (`number` for PetKit China accounts) and `password`.** Third-party account sign-in methods (Facebook, Apple, Twitter) are **not supported**.

- You will need to select the region (country) associated with your account during setup. Note: Hong Kong users should select Hong Kong from the list, not China!

- **If using another PetKit integration that uses the petkit domain, you will need to delete it prior to installing this integration.**

- **If you are running Home Assistant as a Docker container, the `TZ` environment variable must be set.**
Expand Down Expand Up @@ -109,8 +111,7 @@ Alternatively, follow the steps below:
1. Navigate to the Home Assistant Integrations page (Settings --> Devices & Services)
2. Click the `+ ADD INTEGRATION` button in the lower right-hand corner
3. Search for `PetKit`
4. If using a PetKit Asia account, be sure the PetKit Asia account option is checked.
5. If using a PetKit China account (accounts where the username is a number instead of email), be sure the PetKit China account option is checked.
4. Be sure to select the country associated with your account (Hong Kong users should select Hong Kong, not China).

**The current polling interval is set to 2 minutes. If you would like to set a different polling interval, change the polling interval option (via the UI). Keep in mind, setting the polling interval too short may result in your account getting rate limited/blocked.**

Expand Down
17 changes: 8 additions & 9 deletions custom_components/petkit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import HomeAssistant

from .const import ASIA_ACCOUNT, CHINA_ACCOUNT, DOMAIN, LOGGER, PETKIT_COORDINATOR, PLATFORMS, POLLING_INTERVAL, UPDATE_LISTENER
from .const import DOMAIN, LOGGER, PETKIT_COORDINATOR, PLATFORMS, POLLING_INTERVAL, REGION, UPDATE_LISTENER
from .coordinator import PetKitDataUpdateCoordinator
from .util import async_validate_api, NoDevicesError

Expand Down Expand Up @@ -44,7 +44,7 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
password = entry.data[CONF_PASSWORD]

LOGGER.debug('Migrating PetKit config entry')
entry.version = 3
entry.version = 4

hass.config_entries.async_update_entry(
entry,
Expand All @@ -53,20 +53,19 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
CONF_PASSWORD: password,
},
options={
ASIA_ACCOUNT: False,
CHINA_ACCOUNT: False,
REGION: None,
POLLING_INTERVAL: 120,
},
)
LOGGER.error("PetKit API has changed. Please reauthenticate and select your country.")

if entry.version == 2:
if entry.version in [2,3]:
email = entry.data[CONF_EMAIL]
password = entry.data[CONF_PASSWORD]
asia_account = entry.options[ASIA_ACCOUNT]
polling_interval = entry.options[POLLING_INTERVAL]

LOGGER.debug('Migrating PetKit config entry')
entry.version = 3
entry.version = 4

hass.config_entries.async_update_entry(
entry,
Expand All @@ -75,11 +74,11 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
CONF_PASSWORD: password,
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: False,
REGION: None,
POLLING_INTERVAL: polling_interval,
},
)
LOGGER.error("PetKit API has changed. Please reauthenticate and select your country.")

return True

Expand Down
51 changes: 23 additions & 28 deletions custom_components/petkit/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,36 @@
from collections.abc import Mapping
from typing import Any

from petkitaio.exceptions import AccountTypeError, AuthError, PetKitError, ServerError
from petkitaio.exceptions import AuthError, PetKitError, RegionError, ServerError
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import selector
import homeassistant.helpers.config_validation as cv

from .const import ASIA_ACCOUNT, CHINA_ACCOUNT, DEFAULT_NAME, DOMAIN, POLLING_INTERVAL
from .const import DEFAULT_NAME, DOMAIN, POLLING_INTERVAL, REGION, REGIONS_LIST
from .util import NoDevicesError, async_validate_api


DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_EMAIL): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(ASIA_ACCOUNT): cv.boolean,
vol.Optional(CHINA_ACCOUNT): cv.boolean,
vol.Required(REGION): selector.SelectSelector(
selector.SelectSelectorConfig(options=REGIONS_LIST),
)

}
)


class PetKitConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for PetKit integration."""

VERSION = 3
VERSION = 4

entry: config_entries.ConfigEntry | None

Expand Down Expand Up @@ -58,13 +61,12 @@ async def async_step_reauth_confirm(
if user_input:
email = user_input[CONF_EMAIL]
password = user_input[CONF_PASSWORD]
asia_account = user_input[ASIA_ACCOUNT] if ASIA_ACCOUNT in user_input else False
china_account = user_input[CHINA_ACCOUNT] if CHINA_ACCOUNT in user_input else False
region = user_input[REGION] if REGION else None

try:
await async_validate_api(self.hass, email, password, asia_account, china_account)
except AccountTypeError:
errors["base"] = "dual_region"
await async_validate_api(self.hass, email, password, region)
except RegionError:
errors["base"] = "region_error"
except AuthError:
errors["base"] = "invalid_auth"
except ConnectionError:
Expand All @@ -86,8 +88,7 @@ async def async_step_reauth_confirm(
CONF_PASSWORD: password,
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: china_account,
REGION: region,
POLLING_INTERVAL: self.entry.options[POLLING_INTERVAL],
}
)
Expand All @@ -111,13 +112,12 @@ async def async_step_user(
if user_input:
email = user_input[CONF_EMAIL]
password = user_input[CONF_PASSWORD]
asia_account = user_input[ASIA_ACCOUNT] if ASIA_ACCOUNT in user_input else False
china_account = user_input[CHINA_ACCOUNT] if CHINA_ACCOUNT in user_input else False
region = user_input[REGION] if REGION else None

try:
await async_validate_api(self.hass, email, password, asia_account, china_account)
except AccountTypeError:
errors["base"] = "dual_region"
await async_validate_api(self.hass, email, password, region)
except RegionError:
errors["base"] = "region_error"
except AuthError:
errors["base"] = "invalid_auth"
except ConnectionError:
Expand All @@ -139,8 +139,7 @@ async def async_step_user(
CONF_PASSWORD: password
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: china_account,
REGION: region,
POLLING_INTERVAL: 120,
}
)
Expand Down Expand Up @@ -170,17 +169,13 @@ async def async_step_petkit_options(self, user_input=None):

options = {
vol.Required(
ASIA_ACCOUNT,
default=self.config_entry.options.get(
ASIA_ACCOUNT, False
),
): bool,
vol.Required(
CHINA_ACCOUNT,
REGION,
default=self.config_entry.options.get(
CHINA_ACCOUNT, False
REGION, None
),
): bool,
): selector.SelectSelector(
selector.SelectSelectorConfig(options=REGIONS_LIST)
),
vol.Required(
POLLING_INTERVAL,
default=self.config_entry.options.get(
Expand Down
Loading

0 comments on commit b20bc5d

Please sign in to comment.