Skip to content

Commit

Permalink
Merge pull request #23 from RobertD502/china_support
Browse files Browse the repository at this point in the history
Add support for PetKit China accounts
  • Loading branch information
RobertD502 authored Jul 18, 2023
2 parents 48c48f2 + 24d317c commit db8ecce
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 16 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Custom Home Assistant component for controlling and monitoring PetKit devices an

## **Prior To Installation**

- **This integration requires using your PetKit account `email` and `password`.**
- **This integration requires using your PetKit account `email` (`number` for PetKit China accounts) and `password`.**

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

Expand Down Expand Up @@ -96,6 +96,7 @@ Alternatively, follow the steps below:
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.

**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
27 changes: 25 additions & 2 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, DOMAIN, LOGGER, PETKIT_COORDINATOR, PLATFORMS, POLLING_INTERVAL, UPDATE_LISTENER
from .const import ASIA_ACCOUNT, CHINA_ACCOUNT, DOMAIN, LOGGER, PETKIT_COORDINATOR, PLATFORMS, POLLING_INTERVAL, 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 = 2
entry.version = 3

hass.config_entries.async_update_entry(
entry,
Expand All @@ -54,10 +54,33 @@ async def async_migrate_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
},
options={
ASIA_ACCOUNT: False,
CHINA_ACCOUNT: False,
POLLING_INTERVAL: 120,
},
)

if entry.version == 2:
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

hass.config_entries.async_update_entry(
entry,
data={
CONF_EMAIL: email,
CONF_PASSWORD: password,
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: False,
POLLING_INTERVAL: polling_interval,
},
)

return True

async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
Expand Down
27 changes: 22 additions & 5 deletions custom_components/petkit/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from collections.abc import Mapping
from typing import Any

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

from homeassistant import config_entries
Expand All @@ -13,7 +13,7 @@
from homeassistant.data_entry_flow import FlowResult
import homeassistant.helpers.config_validation as cv

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


Expand All @@ -22,14 +22,15 @@
vol.Required(CONF_EMAIL): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(ASIA_ACCOUNT): cv.boolean,
vol.Optional(CHINA_ACCOUNT): cv.boolean,
}
)


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

VERSION = 2
VERSION = 3

entry: config_entries.ConfigEntry | None

Expand Down Expand Up @@ -58,8 +59,12 @@ async def async_step_reauth_confirm(
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

try:
await async_validate_api(self.hass, email, password, asia_account)
await async_validate_api(self.hass, email, password, asia_account, china_account)
except AccountTypeError:
errors["base"] = "dual_region"
except AuthError:
errors["base"] = "invalid_auth"
except ConnectionError:
Expand All @@ -82,6 +87,7 @@ async def async_step_reauth_confirm(
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: china_account,
POLLING_INTERVAL: self.entry.options[POLLING_INTERVAL],
}
)
Expand All @@ -106,8 +112,12 @@ async def async_step_user(
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

try:
await async_validate_api(self.hass, email, password, asia_account)
await async_validate_api(self.hass, email, password, asia_account, china_account)
except AccountTypeError:
errors["base"] = "dual_region"
except AuthError:
errors["base"] = "invalid_auth"
except ConnectionError:
Expand All @@ -130,6 +140,7 @@ async def async_step_user(
},
options={
ASIA_ACCOUNT: asia_account,
CHINA_ACCOUNT: china_account,
POLLING_INTERVAL: 120,
}
)
Expand Down Expand Up @@ -164,6 +175,12 @@ async def async_step_petkit_options(self, user_input=None):
ASIA_ACCOUNT, False
),
): bool,
vol.Required(
CHINA_ACCOUNT,
default=self.config_entry.options.get(
CHINA_ACCOUNT, False
),
): bool,
vol.Required(
POLLING_INTERVAL,
default=self.config_entry.options.get(
Expand Down
1 change: 1 addition & 0 deletions custom_components/petkit/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

DEFAULT_NAME = "PetKit"
ASIA_ACCOUNT = "asia_account"
CHINA_ACCOUNT = "china_account"
PETKIT_COORDINATOR = "petkit_coordinator"
POLLING_INTERVAL = "polling_interval"
TIMEOUT = 20
Expand Down
3 changes: 2 additions & 1 deletion custom_components/petkit/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import ASIA_ACCOUNT, DOMAIN, LOGGER, POLLING_INTERVAL, TIMEOUT
from .const import ASIA_ACCOUNT, CHINA_ACCOUNT, DOMAIN, LOGGER, POLLING_INTERVAL, TIMEOUT


class PetKitDataUpdateCoordinator(DataUpdateCoordinator):
Expand All @@ -31,6 +31,7 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
entry.data[CONF_PASSWORD],
session=async_get_clientsession(hass),
asia_account=entry.options[ASIA_ACCOUNT],
china_account=entry.options[CHINA_ACCOUNT],
timeout=TIMEOUT,
)
super().__init__(
Expand Down
4 changes: 2 additions & 2 deletions custom_components/petkit/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
"integration_type": "hub",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/RobertD502/home-assistant-petkit/issues",
"requirements": ["petkitaio==0.1.6.1", "tzlocal>=4.2"],
"version": "0.1.6.1"
"requirements": ["petkitaio==0.1.7", "tzlocal>=4.2"],
"version": "0.1.7"
}
6 changes: 5 additions & 1 deletion custom_components/petkit/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"email": "PetKit account email",
"password": "PetKit account password",
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
}
},
Expand All @@ -16,6 +17,7 @@
"email": "PetKit account email",
"password": "PetKit account password",
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
}
}
Expand All @@ -25,7 +27,8 @@
"invalid_auth": "Invalid authentication. Are your credentials correct?",
"no_devices": "No devices found on account",
"server_busy": "PetKit servers are busy. Please try again later.",
"petkit_error": "Unknown error encountered. Please see Home Assistant logs for more details."
"petkit_error": "Unknown error encountered. Please see Home Assistant logs for more details.",
"dual_region": "Only one of PetKit Asia or China can be selected. Not both."
},
"abort": {
"already_configured": "PetKit account is already configured",
Expand All @@ -37,6 +40,7 @@
"petkit_options": {
"data": {
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
}
}
Expand Down
6 changes: 5 additions & 1 deletion custom_components/petkit/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
"invalid_auth": "Invalid authentication. Are your credentials correct?",
"no_devices": "No devices found on account",
"server_busy": "PetKit servers are busy. Please try again later.",
"petkit_error": "Unknown error encountered. Please see Home Assistant logs for more details."
"petkit_error": "Unknown error encountered. Please see Home Assistant logs for more details.",
"dual_region": "Only one of PetKit Asia or China can be selected. Not both."
},
"step": {
"user": {
"data": {
"email": "PetKit account email",
"password": "PetKit account password",
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
},
"title": "Fill in your PetKit credentials"
Expand All @@ -26,6 +28,7 @@
"email": "PetKit account email",
"password": "PetKit account password",
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
},
"title": "Reauthenticate with your PetKit credentials"
Expand All @@ -37,6 +40,7 @@
"petkit_options": {
"data": {
"asia_account": "PetKit Asia account",
"china_account": "PetKit China account",
"polling_interval": "Polling interval (seconds)"
}
}
Expand Down
6 changes: 5 additions & 1 deletion custom_components/petkit/translations/hr.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
"invalid_auth": "Nevažeća provjera autentičnosti. Jesu li vaše vjerodajnice točne?",
"no_devices": "Na vašem računu nisu pronađeni uređaji",
"server_busy": "PetKit serveri su zauzeti. Molimo pokušajte ponovo kasnije.",
"petkit_error": "Došlo je do nepoznate pogreške. Za više detalja pogledajte Home Assistant zapisnike."
"petkit_error": "Došlo je do nepoznate pogreške. Za više detalja pogledajte Home Assistant zapisnike.",
"dual_region": "Može se odabrati samo jedan od PetKit Asia ili China. Ne oboje."
},
"step": {
"user": {
"data": {
"email": "PetKit e-pošta računa",
"password": "PetKit lozinka računa",
"asia_account": "PetKit Asia račun",
"china_account": "PetKit Kineski račun",
"polling_interval": "Interval prozivanja (sekunde)"
},
"title": "Ispunite svoje vjerodajnice za PetKit"
Expand All @@ -26,6 +28,7 @@
"email": "PetKit e-pošta računa",
"password": "PetKit lozinka računa",
"asia_account": "PetKit Asia račun",
"china_account": "PetKit Kineski račun",
"polling_interval": "Interval prozivanja (sekunde)"
},
"title": "Ponovo potvrdite autentičnost svojim PetKit vjerodajnicama"
Expand All @@ -37,6 +40,7 @@
"petkit_options": {
"data": {
"asia_account": "PetKit Asia račun",
"china_account": "PetKit Kineski račun",
"polling_interval": "Interval prozivanja (sekunde)"
}
}
Expand Down
8 changes: 6 additions & 2 deletions custom_components/petkit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
import async_timeout

from petkitaio import PetKitClient
from petkitaio.exceptions import AuthError, PetKitError, ServerError
from petkitaio.exceptions import AccountTypeError, AuthError, PetKitError, ServerError

from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import LOGGER, PETKIT_ERRORS, TIMEOUT


async def async_validate_api(hass: HomeAssistant, email: str, password: str, asia_account: bool) -> bool:
async def async_validate_api(hass: HomeAssistant, email: str, password: str, asia_account: bool, china_account: bool) -> bool:
"""Get data from API."""

client = PetKitClient(
email,
password,
session=async_get_clientsession(hass),
asia_account=asia_account,
china_account=china_account,
timeout=TIMEOUT,
)

Expand All @@ -33,6 +34,9 @@ async def async_validate_api(hass: HomeAssistant, email: str, password: str, asi
except ServerError as err:
LOGGER.error(f'PetKit servers are busy.Please try again later.')
raise ServerError(err)
except AccountTypeError as err:
LOGGER.error(f'{err}')
raise AccountTypeError(err)
except PetKitError as err:
LOGGER.error(f'Unknown PetKit Error: {err}')
raise PetKitError(err)
Expand Down

0 comments on commit db8ecce

Please sign in to comment.