async def validate_login_creds(self, data): """Validate the user input allows us to connect. data: contains values provided by the user. """ websession = aiohttp_client.async_get_clientsession(self.hass) now = datetime.now() if not data.get(CONF_DEVICE_ID): data[CONF_DEVICE_ID] = int(now.timestamp()) date = now.strftime("%Y-%m-%d") device_name = "Home Assistant: Added " + date self.controller = SubaruAPI( websession, username=data[CONF_USERNAME], password=data[CONF_PASSWORD], device_id=data[CONF_DEVICE_ID], pin=None, device_name=device_name, country=data[CONF_COUNTRY], ) _LOGGER.debug( "Setting up first time connection to Subaru API. This may take up to 20 seconds" ) if await self.controller.connect(): _LOGGER.debug("Successfully authenticated and authorized with Subaru API") self.config_data.update(data)
async def async_setup_entry(hass, entry): """Set up Subaru from a config entry.""" config = entry.data websession = aiohttp_client.async_get_clientsession(hass) try: controller = SubaruAPI( websession, config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_DEVICE_ID], config[CONF_PIN], None, config[CONF_COUNTRY], update_interval=UPDATE_INTERVAL, fetch_interval=FETCH_INTERVAL, ) _LOGGER.debug("Using subarulink %s", controller.version) await controller.connect() except InvalidCredentials: _LOGGER.error("Invalid account") return False except SubaruException as err: raise ConfigEntryNotReady(err.message) from err vehicle_info = {} for vin in controller.get_vehicles(): vehicle_info[vin] = get_vehicle_info(controller, vin) async def async_update_data(): """Fetch data from API endpoint.""" try: return await refresh_subaru_data(entry, vehicle_info, controller) except SubaruException as err: raise UpdateFailed(err.message) from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=COORDINATOR_NAME, update_method=async_update_data, update_interval=timedelta(seconds=FETCH_INTERVAL), ) await coordinator.async_refresh() hass.data[DOMAIN][entry.entry_id] = { ENTRY_CONTROLLER: controller, ENTRY_COORDINATOR: coordinator, ENTRY_VEHICLES: vehicle_info, } for component in SUPPORTED_PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component) ) return True
async def validate_input(hass: core.HomeAssistant, data): """Validate the user input allows us to connect. data: contains values provided by the user. """ websession = aiohttp_client.async_get_clientsession(hass) now = datetime.now() if not data.get(CONF_DEVICE_ID): data[CONF_DEVICE_ID] = int(now.timestamp()) date = now.strftime("%Y-%m-%d") device_name = "Home Assistant: Added " + date controller = SubaruAPI( websession, username=data[CONF_USERNAME], password=data[CONF_PASSWORD], device_id=data[CONF_DEVICE_ID], pin=data[CONF_PIN], device_name=device_name, ) _LOGGER.info( "Setting up first time connection to Subuaru API. This may take up to 20 seconds." ) if await controller.connect(): _LOGGER.debug( "Successfully authenticated and authorized with Subaru API") _LOGGER.debug( "Testing user provided PIN with Subaru remote service requests") if await controller.test_pin(): _LOGGER.debug( "User provided PIN is valid for Subaru remote service requests") else: _LOGGER.info( "No active remote service subscription, PIN number will not be used" ) return data
async def async_setup_entry(hass, entry): """Set up Subaru from a config entry.""" config = entry.data websession = aiohttp_client.async_get_clientsession(hass) date = datetime.now().strftime("%Y-%m-%d") device_name = "Home Assistant: Added " + date try: controller = SubaruAPI( websession, config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_DEVICE_ID], config[CONF_PIN], device_name, update_interval=entry.options.get( CONF_HARD_POLL_INTERVAL, DEFAULT_HARD_POLL_INTERVAL ), ) await controller.connect() except SubaruException as err: raise ConfigEntryNotReady(err) from err vehicle_info = {} remote_services = [] for vin in controller.get_vehicles(): vehicle_info[vin] = get_vehicle_info(controller, vin) if vehicle_info[vin][VEHICLE_HAS_SAFETY_SERVICE]: remote_services.append(REMOTE_SERVICE_FETCH) if vehicle_info[vin][VEHICLE_HAS_REMOTE_SERVICE]: remote_services.append(REMOTE_SERVICE_HORN) remote_services.append(REMOTE_SERVICE_LIGHTS) remote_services.append(REMOTE_SERVICE_LOCK) remote_services.append(REMOTE_SERVICE_UNLOCK) remote_services.append(REMOTE_SERVICE_UPDATE) if ( vehicle_info[vin][VEHICLE_HAS_REMOTE_START] or vehicle_info[vin][VEHICLE_HAS_EV] ): remote_services.append(REMOTE_SERVICE_REMOTE_START) remote_services.append(REMOTE_SERVICE_REMOTE_STOP) if vehicle_info[vin][VEHICLE_HAS_EV]: remote_services.append(REMOTE_SERVICE_CHARGE_START) async def async_update_data(): """Fetch data from API endpoint.""" try: return await subaru_update(vehicle_info, controller) except SubaruException as err: raise UpdateFailed(err) from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=COORDINATOR_NAME, update_method=async_update_data, update_interval=timedelta( seconds=entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) ), ) await coordinator.async_refresh() hass.data.get(DOMAIN)[entry.entry_id] = { ENTRY_CONTROLLER: controller, ENTRY_COORDINATOR: coordinator, ENTRY_VEHICLES: vehicle_info, ENTRY_LISTENER: entry.add_update_listener(update_listener), } for component in SUPPORTED_PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component) ) async def async_remote_service(call): """Execute remote services.""" vin = call.data[VEHICLE_VIN].upper() success = False if vin not in vehicle_info.keys(): hass.components.persistent_notification.create( f"ERROR - Invalid VIN: {vin}", "Subaru" ) else: if call.service == REMOTE_SERVICE_FETCH: await coordinator.async_refresh() return try: _LOGGER.debug("calling %s", call.service) hass.components.persistent_notification.create( f"Calling Subaru Service: {call.service}:{vin}\nThis may take 10-15 seconds.", "Subaru", DOMAIN, ) if call.service == REMOTE_SERVICE_UPDATE: vehicle = vehicle_info[vin] success = await refresh_subaru_data( vehicle, controller, override_interval=True ) else: success = await getattr(controller, call.service)(vin) except InvalidPIN: hass.components.persistent_notification.dismiss(DOMAIN) hass.components.persistent_notification.create( "ERROR - Invalid PIN", "Subaru" ) if success and call.service in SERVICES_THAT_NEED_FETCH: await coordinator.async_refresh() hass.components.persistent_notification.dismiss(DOMAIN) if success: hass.components.persistent_notification.create( f"Command completed: {call.service}:{vin}", "Subaru" ) else: hass.components.persistent_notification.create( f"ERROR - Command failed: {call.service}:{vin}", "Subaru" ) for service in remote_services: hass.services.async_register( DOMAIN, service, async_remote_service, schema=REMOTE_SERVICE_SCHEMA ) return True
async def async_setup_entry(hass, entry): """Set up Subaru from a config entry.""" config = entry.data websession = aiohttp_client.async_create_clientsession(hass) # Backwards compatibility for configs made before v0.3.0 country = config.get(CONF_COUNTRY) if not country: country = COUNTRY_USA try: controller = SubaruAPI( websession, config[CONF_USERNAME], config[CONF_PASSWORD], config[CONF_DEVICE_ID], config[CONF_PIN], None, country=country, update_interval=UPDATE_INTERVAL, fetch_interval=FETCH_INTERVAL, ) _LOGGER.debug("Using subarulink %s", controller.version) await controller.connect() except InvalidCredentials: _LOGGER.error("Invalid account") return False except SubaruException as err: raise ConfigEntryNotReady(err) from err vehicles = {} for vin in controller.get_vehicles(): vehicles[vin] = get_vehicle_info(controller, vin) async def async_update_data(): """Fetch data from API endpoint.""" try: return await refresh_subaru_data(entry, vehicles, controller) except SubaruException as err: raise UpdateFailed(err.message) from err coordinator = DataUpdateCoordinator( hass, _LOGGER, name=COORDINATOR_NAME, update_method=async_update_data, update_interval=timedelta(seconds=FETCH_INTERVAL), ) await coordinator.async_refresh() hass.data.get(DOMAIN)[entry.entry_id] = { ENTRY_CONTROLLER: controller, ENTRY_COORDINATOR: coordinator, ENTRY_VEHICLES: vehicles, } for component in SUPPORTED_PLATFORMS: hass.async_create_task( hass.config_entries.async_forward_entry_setup(entry, component)) async def async_call_service(call): """Execute subaru service.""" _LOGGER.warn( "This Subaru-specific service is deprecated and will be removed in v0.7.0. Use button or lock entities (or their respective services) to actuate remove vehicle services." ) vin = call.data[VEHICLE_VIN].upper() arg = None if vin in vehicles: await async_call_remote_service( hass, controller, call.service, vehicles[vin], arg, entry.options.get(CONF_NOTIFICATION_OPTION), ) await coordinator.async_refresh() return hass.components.persistent_notification.create( f"ERROR - Invalid VIN provided while calling {call.service}", "Subaru") raise HomeAssistantError( f"Invalid VIN provided while calling {call.service}") async def async_remote_start(call): """Start the vehicle engine.""" dev_reg = device_registry.async_get(hass) device_entry = dev_reg.async_get(call.data[ATTR_DEVICE_ID]) if device_entry: vin = list(device_entry.identifiers)[0][1] _LOGGER.info( "Remote engine start initiated with climate preset: %s", call.data[REMOTE_CLIMATE_PRESET_NAME], ) await async_call_remote_service( hass, controller, call.service, vehicles[vin], call.data[REMOTE_CLIMATE_PRESET_NAME], entry.options.get(CONF_NOTIFICATION_OPTION), ) await coordinator.async_refresh() else: raise HomeAssistantError( f"device_id {call.data[ATTR_DEVICE_ID]} not found") supported_services = get_supported_services(vehicles) for service in supported_services: if service == REMOTE_SERVICE_REMOTE_START: hass.services.async_register( DOMAIN, service, async_remote_start, schema=vol.Schema({ vol.Required(ATTR_DEVICE_ID): cv.string, vol.Required(REMOTE_CLIMATE_PRESET_NAME): cv.string, }), ) else: hass.services.async_register( DOMAIN, service, async_call_service, schema=vol.Schema({vol.Required(VEHICLE_VIN): cv.string}), ) return True