"""Support for N26 bank accounts.""" from datetime import datetime, timedelta, timezone import logging from n26 import api as n26_api, config as n26_config from requests import HTTPError import voluptuous as vol from homeassistant.const import CONF_PASSWORD, CONF_SCAN_INTERVAL, CONF_USERNAME import homeassistant.helpers.config_validation as cv from homeassistant.helpers.discovery import load_platform from homeassistant.util import Throttle from .const import DATA, DOMAIN _LOGGER = logging.getLogger(__name__) DEFAULT_SCAN_INTERVAL = timedelta(minutes=30) # define configuration parameters CONFIG_SCHEMA = vol.Schema( { DOMAIN: vol.All( cv.ensure_list, [ { vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_PASSWORD): cv.string, vol.Optional( CONF_SCAN_INTERVAL, default=DEFAULT_SCAN_INTERVAL ): cv.time_period, } ], ) }, extra=vol.ALLOW_EXTRA, ) N26_COMPONENTS = ["sensor", "switch"] def setup(hass, config): """Set up N26 Component.""" acc_list = config[DOMAIN] api_data_list = [] for acc in acc_list: user = acc[CONF_USERNAME] password = acc[CONF_PASSWORD] api = n26_api.Api(n26_config.Config(user, password)) try: api.get_token() except HTTPError as err: _LOGGER.error(str(err)) return False api_data = N26Data(api) api_data.update() api_data_list.append(api_data) hass.data[DOMAIN] = {} hass.data[DOMAIN][DATA] = api_data_list # Load components for supported devices for component in N26_COMPONENTS: load_platform(hass, component, DOMAIN, {}, config) return True def timestamp_ms_to_date(epoch_ms) -> datetime or None: """Convert millisecond timestamp to datetime.""" if epoch_ms: return datetime.fromtimestamp(epoch_ms / 1000, timezone.utc) class N26Data: """Handle N26 API object and limit updates.""" def __init__(self, api): """Initialize the data object.""" self._api = api self._account_info = {} self._balance = {} self._limits = {} self._account_statuses = {} self._cards = {} self._spaces = {} @property def api(self): """Return N26 api client.""" return self._api @property def account_info(self): """Return N26 account info.""" return self._account_info @property def balance(self): """Return N26 account balance.""" return self._balance @property def limits(self): """Return N26 account limits.""" return self._limits @property def account_statuses(self): """Return N26 account statuses.""" return self._account_statuses @property def cards(self): """Return N26 cards.""" return self._cards def card(self, card_id: str, default: dict = None): """Return a card by its id or the given default.""" return next((card for card in self.cards if card["id"] == card_id), default) @property def spaces(self): """Return N26 spaces.""" return self._spaces def space(self, space_id: str, default: dict = None): """Return a space by its id or the given default.""" return next( (space for space in self.spaces["spaces"] if space["id"] == space_id), default, ) @Throttle(min_time=DEFAULT_SCAN_INTERVAL * 0.8) def update_account(self): """Get the latest account data from N26.""" self._account_info = self._api.get_account_info() self._balance = self._api.get_balance() self._limits = self._api.get_account_limits() self._account_statuses = self._api.get_account_statuses() @Throttle(min_time=DEFAULT_SCAN_INTERVAL * 0.8) def update_cards(self): """Get the latest cards data from N26.""" self._cards = self._api.get_cards() @Throttle(min_time=DEFAULT_SCAN_INTERVAL * 0.8) def update_spaces(self): """Get the latest spaces data from N26.""" self._spaces = self._api.get_spaces() def update(self): """Get the latest data from N26.""" self.update_account() self.update_cards() self.update_spaces()